Commit 3e101410 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Optionally compress V8 code cache data with snappy.

R=jochen@chromium.org, vogelheim@chromium.org

Review URL: https://codereview.chromium.org/720783002

git-svn-id: svn://svn.chromium.org/blink/trunk@185305 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 55cd997a
...@@ -7,6 +7,7 @@ include_rules = [ ...@@ -7,6 +7,7 @@ include_rules = [
"-modules", "-modules",
"+platform", "+platform",
"+public/platform", "+public/platform",
"+third_party/snappy",
"-web", "-web",
# TODO(tasak): Get this list to zero. # TODO(tasak): Get this list to zero.
......
...@@ -545,7 +545,7 @@ bool ScriptStreamer::startStreamingInternal(PendingScript& script, Settings* set ...@@ -545,7 +545,7 @@ bool ScriptStreamer::startStreamingInternal(PendingScript& script, Settings* set
// default, we generate the parser cache for streamed scripts, to emulate // default, we generate the parser cache for streamed scripts, to emulate
// the non-streaming behavior (see V8ScriptRunner::compileScript). // the non-streaming behavior (see V8ScriptRunner::compileScript).
v8::ScriptCompiler::CompileOptions compileOption = v8::ScriptCompiler::kProduceParserCache; v8::ScriptCompiler::CompileOptions compileOption = v8::ScriptCompiler::kProduceParserCache;
if (settings->v8CacheOptions() == V8CacheOptionsCode) if (settings->v8CacheOptions() == V8CacheOptionsCode || settings->v8CacheOptions() == V8CacheOptionsCodeCompressed)
compileOption = v8::ScriptCompiler::kProduceCodeCache; compileOption = v8::ScriptCompiler::kProduceCodeCache;
// The Resource might go out of scope if the script is no longer // The Resource might go out of scope if the script is no longer
......
...@@ -36,7 +36,8 @@ namespace blink { ...@@ -36,7 +36,8 @@ namespace blink {
enum V8CacheOptions { enum V8CacheOptions {
V8CacheOptionsOff, V8CacheOptionsOff,
V8CacheOptionsParse, V8CacheOptionsParse,
V8CacheOptionsCode V8CacheOptionsCode,
V8CacheOptionsCodeCompressed
}; };
} // namespace blink } // namespace blink
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "core/fetch/ScriptResource.h" #include "core/fetch/ScriptResource.h"
#include "platform/ScriptForbiddenScope.h" #include "platform/ScriptForbiddenScope.h"
#include "platform/TraceEvent.h" #include "platform/TraceEvent.h"
#include "third_party/snappy/src/snappy.h"
namespace blink { namespace blink {
...@@ -64,29 +65,49 @@ v8::Local<v8::Value> throwStackOverflowExceptionIfNeeded(v8::Isolate* isolate) ...@@ -64,29 +65,49 @@ v8::Local<v8::Value> throwStackOverflowExceptionIfNeeded(v8::Isolate* isolate)
return result; return result;
} }
v8::Local<v8::Script> compileAndProduceCache(v8::Isolate* isolate, v8::Handle<v8::String> code, v8::ScriptOrigin origin, ScriptResource* resource, v8::ScriptCompiler::CompileOptions options, unsigned cacheTag, Resource::MetadataCacheType cacheType) void writeToCache(ScriptResource* resource, unsigned cacheTag, Resource::MetadataCacheType cacheType, const v8::ScriptCompiler::CachedData* cachedData, bool compressed)
{
const char* data = reinterpret_cast<const char*>(cachedData->data);
int length = cachedData->length;
std::string compressedOutput;
if (compressed) {
snappy::Compress(data, length, &compressedOutput);
data = compressedOutput.data();
length = compressedOutput.length();
}
resource->clearCachedMetadata();
resource->setCachedMetadata(
cacheTag,
data,
length,
cacheType);
}
v8::Local<v8::Script> compileAndProduceCache(v8::Isolate* isolate, v8::Handle<v8::String> code, v8::ScriptOrigin origin, ScriptResource* resource, v8::ScriptCompiler::CompileOptions options, unsigned cacheTag, Resource::MetadataCacheType cacheType, bool compressed)
{ {
v8::ScriptCompiler::Source source(code, origin); v8::ScriptCompiler::Source source(code, origin);
v8::Local<v8::Script> script = v8::ScriptCompiler::Compile(isolate, &source, options); v8::Local<v8::Script> script = v8::ScriptCompiler::Compile(isolate, &source, options);
const v8::ScriptCompiler::CachedData* cachedData = source.GetCachedData(); const v8::ScriptCompiler::CachedData* cachedData = source.GetCachedData();
if (resource && cachedData) { if (resource && cachedData)
resource->clearCachedMetadata(); writeToCache(resource, cacheTag, cacheType, cachedData, compressed);
resource->setCachedMetadata(
cacheTag,
reinterpret_cast<const char*>(cachedData->data),
cachedData->length,
cacheType);
}
return script; return script;
} }
v8::Local<v8::Script> compileAndConsumeCache(v8::Isolate* isolate, v8::Handle<v8::String> code, v8::ScriptOrigin origin, ScriptResource* resource, v8::ScriptCompiler::CompileOptions options, unsigned cacheTag) v8::Local<v8::Script> compileAndConsumeCache(v8::Isolate* isolate, v8::Handle<v8::String> code, v8::ScriptOrigin origin, ScriptResource* resource, v8::ScriptCompiler::CompileOptions options, unsigned cacheTag, bool compressed)
{ {
// Consume existing cache data: // Consume existing cache data:
CachedMetadata* cachedMetadata = resource->cachedMetadata(cacheTag); CachedMetadata* cachedMetadata = resource->cachedMetadata(cacheTag);
const char* data = cachedMetadata->data();
int length = cachedMetadata->size();
std::string uncompressedOutput;
if (compressed) {
snappy::Uncompress(data, length, &uncompressedOutput);
data = uncompressedOutput.data();
length = uncompressedOutput.length();
}
v8::ScriptCompiler::CachedData* cachedData = new v8::ScriptCompiler::CachedData( v8::ScriptCompiler::CachedData* cachedData = new v8::ScriptCompiler::CachedData(
reinterpret_cast<const uint8_t*>(cachedMetadata->data()), reinterpret_cast<const uint8_t*>(data),
cachedMetadata->size(), length,
v8::ScriptCompiler::CachedData::BufferNotOwned); v8::ScriptCompiler::CachedData::BufferNotOwned);
v8::ScriptCompiler::Source source(code, origin, cachedData); v8::ScriptCompiler::Source source(code, origin, cachedData);
return v8::ScriptCompiler::Compile(isolate, &source, options); return v8::ScriptCompiler::Compile(isolate, &source, options);
...@@ -114,6 +135,7 @@ v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code, ...@@ -114,6 +135,7 @@ v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code,
v8::Local<v8::Script> script; v8::Local<v8::Script> script;
unsigned cacheTag = 0; unsigned cacheTag = 0;
bool compressed = cacheOptions == V8CacheOptionsCodeCompressed;
if (streamer) { if (streamer) {
// We don't stream scripts which don't have a Resource. // We don't stream scripts which don't have a Resource.
ASSERT(resource); ASSERT(resource);
...@@ -126,37 +148,38 @@ v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code, ...@@ -126,37 +148,38 @@ v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code,
// streamer is started. Here we only need to get the data out. // streamer is started. Here we only need to get the data out.
const v8::ScriptCompiler::CachedData* newCachedData = streamer->source()->GetCachedData(); const v8::ScriptCompiler::CachedData* newCachedData = streamer->source()->GetCachedData();
if (newCachedData) { if (newCachedData) {
resource->clearCachedMetadata(); // TODO(yangguo,vogelheim): code cache should use Resource::SendToPlatform.
resource->setCachedMetadata(streamer->cachedDataType(), reinterpret_cast<const char*>(newCachedData->data), newCachedData->length, Resource::CacheLocally); writeToCache(resource, streamer->cachedDataType(), Resource::CacheLocally, newCachedData, compressed);
} }
} else if (!resource || !resource->url().protocolIsInHTTPFamily() || code->Length() < 1024) { } else if (!resource || !resource->url().protocolIsInHTTPFamily() || code->Length() < 1024) {
v8::ScriptCompiler::Source source(code, origin); v8::ScriptCompiler::Source source(code, origin);
script = v8::ScriptCompiler::Compile(isolate, &source, v8::ScriptCompiler::kNoCompileOptions); script = v8::ScriptCompiler::Compile(isolate, &source, v8::ScriptCompiler::kNoCompileOptions);
} else { } else {
Resource::MetadataCacheType cacheType = Resource::CacheLocally;
v8::ScriptCompiler::CompileOptions consumeOption = v8::ScriptCompiler::kConsumeParserCache;
v8::ScriptCompiler::CompileOptions produceOption = v8::ScriptCompiler::kProduceParserCache;
switch (cacheOptions) { switch (cacheOptions) {
case V8CacheOptionsOff:
// Use default.
cacheTag = tagForParserCache();
break;
case V8CacheOptionsParse: case V8CacheOptionsParse:
cacheTag = tagForParserCache(); cacheTag = tagForParserCache();
script = resource->cachedMetadata(cacheTag) cacheType = Resource::SendToPlatform;
? compileAndConsumeCache(isolate, code, origin, resource, v8::ScriptCompiler::kConsumeParserCache, cacheTag) consumeOption = v8::ScriptCompiler::kConsumeParserCache;
: compileAndProduceCache(isolate, code, origin, resource, v8::ScriptCompiler::kProduceParserCache, cacheTag, Resource::SendToPlatform); produceOption = v8::ScriptCompiler::kProduceParserCache;
break; break;
case V8CacheOptionsCodeCompressed:
case V8CacheOptionsCode: case V8CacheOptionsCode:
cacheTag = tagForCodeCache(); cacheTag = tagForCodeCache();
script = resource->cachedMetadata(cacheTag) cacheType = Resource::SendToPlatform;
? compileAndConsumeCache(isolate, code, origin, resource, v8::ScriptCompiler::kConsumeCodeCache, cacheTag) consumeOption = v8::ScriptCompiler::kConsumeCodeCache;
: compileAndProduceCache(isolate, code, origin, resource, v8::ScriptCompiler::kProduceCodeCache, cacheTag, Resource::SendToPlatform); produceOption = v8::ScriptCompiler::kProduceCodeCache;
break;
case V8CacheOptionsOff:
// Previous behaviour was to always generate an in-memory parser
// cache. We emulate this here.
// FIXME: Determine whether this should get its own setting, so we
// can also have a true 'off'.
cacheTag = tagForParserCache();
script = resource->cachedMetadata(cacheTag)
? compileAndConsumeCache(isolate, code, origin, resource, v8::ScriptCompiler::kConsumeParserCache, cacheTag)
: compileAndProduceCache(isolate, code, origin, resource, v8::ScriptCompiler::kProduceParserCache, cacheTag, Resource::CacheLocally);
break; break;
} }
script = resource->cachedMetadata(cacheTag)
? compileAndConsumeCache(isolate, code, origin, resource, consumeOption, cacheTag, compressed)
: compileAndProduceCache(isolate, code, origin, resource, produceOption, cacheTag, cacheType, compressed);
} }
return script; return script;
} }
......
...@@ -136,6 +136,17 @@ TEST_F(V8ScriptRunnerTest, codeOptions) ...@@ -136,6 +136,17 @@ TEST_F(V8ScriptRunnerTest, codeOptions)
EXPECT_TRUE(compileScript(V8CacheOptionsCode)); EXPECT_TRUE(compileScript(V8CacheOptionsCode));
EXPECT_FALSE(m_resource->cachedMetadata(tagForParserCache())); EXPECT_FALSE(m_resource->cachedMetadata(tagForParserCache()));
// FIXME: Code caching is presently still disabled.
// Enable EXPECT when code caching lands.
// EXPECT_TRUE(m_resource->cachedMetadata(tagForCodeCache(false)));
}
TEST_F(V8ScriptRunnerTest, codeCompressedOptions)
{
setResource();
EXPECT_TRUE(compileScript(V8CacheOptionsCodeCompressed));
EXPECT_FALSE(m_resource->cachedMetadata(tagForParserCache()));
// FIXME: Code caching is presently still disabled. // FIXME: Code caching is presently still disabled.
// Enable EXPECT when code caching lands. // Enable EXPECT when code caching lands.
// EXPECT_TRUE(m_resource->cachedMetadata(tagForCodeCache())); // EXPECT_TRUE(m_resource->cachedMetadata(tagForCodeCache()));
......
...@@ -90,6 +90,7 @@ source_set("prerequisites") { ...@@ -90,6 +90,7 @@ source_set("prerequisites") {
"//third_party/npapi", "//third_party/npapi",
"//third_party/ots", "//third_party/ots",
"//third_party/qcms", "//third_party/qcms",
"//third_party/snappy",
"//third_party/sqlite", "//third_party/sqlite",
"//third_party/zlib", "//third_party/zlib",
"//url", "//url",
......
...@@ -187,6 +187,7 @@ ...@@ -187,6 +187,7 @@
'<(DEPTH)/third_party/libxslt/libxslt.gyp:libxslt', '<(DEPTH)/third_party/libxslt/libxslt.gyp:libxslt',
'<(DEPTH)/third_party/npapi/npapi.gyp:npapi', '<(DEPTH)/third_party/npapi/npapi.gyp:npapi',
'<(DEPTH)/third_party/qcms/qcms.gyp:qcms', '<(DEPTH)/third_party/qcms/qcms.gyp:qcms',
'<(DEPTH)/third_party/snappy/snappy.gyp:snappy',
'<(DEPTH)/third_party/sqlite/sqlite.gyp:sqlite', '<(DEPTH)/third_party/sqlite/sqlite.gyp:sqlite',
'<(DEPTH)/url/url.gyp:url_lib', '<(DEPTH)/url/url.gyp:url_lib',
'<(DEPTH)/v8/tools/gyp/v8.gyp:v8', '<(DEPTH)/v8/tools/gyp/v8.gyp:v8',
......
...@@ -639,6 +639,7 @@ COMPILE_ASSERT_MATCHING_ENUM(WebSelectionBound::SelectionRight, CompositedSelect ...@@ -639,6 +639,7 @@ COMPILE_ASSERT_MATCHING_ENUM(WebSelectionBound::SelectionRight, CompositedSelect
COMPILE_ASSERT_MATCHING_ENUM(WebSettings::V8CacheOptionsOff, V8CacheOptionsOff); COMPILE_ASSERT_MATCHING_ENUM(WebSettings::V8CacheOptionsOff, V8CacheOptionsOff);
COMPILE_ASSERT_MATCHING_ENUM(WebSettings::V8CacheOptionsParse, V8CacheOptionsParse); COMPILE_ASSERT_MATCHING_ENUM(WebSettings::V8CacheOptionsParse, V8CacheOptionsParse);
COMPILE_ASSERT_MATCHING_ENUM(WebSettings::V8CacheOptionsCode, V8CacheOptionsCode); COMPILE_ASSERT_MATCHING_ENUM(WebSettings::V8CacheOptionsCode, V8CacheOptionsCode);
COMPILE_ASSERT_MATCHING_ENUM(WebSettings::V8CacheOptionsCodeCompressed, V8CacheOptionsCodeCompressed);
COMPILE_ASSERT_MATCHING_ENUM(WebSettings::PointerTypeNone, PointerTypeNone); COMPILE_ASSERT_MATCHING_ENUM(WebSettings::PointerTypeNone, PointerTypeNone);
COMPILE_ASSERT_MATCHING_ENUM(WebSettings::PointerTypeCoarse, PointerTypeCoarse); COMPILE_ASSERT_MATCHING_ENUM(WebSettings::PointerTypeCoarse, PointerTypeCoarse);
......
...@@ -55,7 +55,8 @@ public: ...@@ -55,7 +55,8 @@ public:
enum V8CacheOptions { enum V8CacheOptions {
V8CacheOptionsOff, V8CacheOptionsOff,
V8CacheOptionsParse, V8CacheOptionsParse,
V8CacheOptionsCode V8CacheOptionsCode,
V8CacheOptionsCodeCompressed
}; };
enum V8ScriptStreamingMode { enum V8ScriptStreamingMode {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment