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 = [
"-modules",
"+platform",
"+public/platform",
"+third_party/snappy",
"-web",
# TODO(tasak): Get this list to zero.
......
......@@ -545,7 +545,7 @@ bool ScriptStreamer::startStreamingInternal(PendingScript& script, Settings* set
// default, we generate the parser cache for streamed scripts, to emulate
// the non-streaming behavior (see V8ScriptRunner::compileScript).
v8::ScriptCompiler::CompileOptions compileOption = v8::ScriptCompiler::kProduceParserCache;
if (settings->v8CacheOptions() == V8CacheOptionsCode)
if (settings->v8CacheOptions() == V8CacheOptionsCode || settings->v8CacheOptions() == V8CacheOptionsCodeCompressed)
compileOption = v8::ScriptCompiler::kProduceCodeCache;
// The Resource might go out of scope if the script is no longer
......
......@@ -36,7 +36,8 @@ namespace blink {
enum V8CacheOptions {
V8CacheOptionsOff,
V8CacheOptionsParse,
V8CacheOptionsCode
V8CacheOptionsCode,
V8CacheOptionsCodeCompressed
};
} // namespace blink
......
......@@ -37,6 +37,7 @@
#include "core/fetch/ScriptResource.h"
#include "platform/ScriptForbiddenScope.h"
#include "platform/TraceEvent.h"
#include "third_party/snappy/src/snappy.h"
namespace blink {
......@@ -64,29 +65,49 @@ v8::Local<v8::Value> throwStackOverflowExceptionIfNeeded(v8::Isolate* isolate)
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::Local<v8::Script> script = v8::ScriptCompiler::Compile(isolate, &source, options);
const v8::ScriptCompiler::CachedData* cachedData = source.GetCachedData();
if (resource && cachedData) {
resource->clearCachedMetadata();
resource->setCachedMetadata(
cacheTag,
reinterpret_cast<const char*>(cachedData->data),
cachedData->length,
cacheType);
}
if (resource && cachedData)
writeToCache(resource, cacheTag, cacheType, cachedData, compressed);
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:
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(
reinterpret_cast<const uint8_t*>(cachedMetadata->data()),
cachedMetadata->size(),
reinterpret_cast<const uint8_t*>(data),
length,
v8::ScriptCompiler::CachedData::BufferNotOwned);
v8::ScriptCompiler::Source source(code, origin, cachedData);
return v8::ScriptCompiler::Compile(isolate, &source, options);
......@@ -114,6 +135,7 @@ v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code,
v8::Local<v8::Script> script;
unsigned cacheTag = 0;
bool compressed = cacheOptions == V8CacheOptionsCodeCompressed;
if (streamer) {
// We don't stream scripts which don't have a Resource.
ASSERT(resource);
......@@ -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.
const v8::ScriptCompiler::CachedData* newCachedData = streamer->source()->GetCachedData();
if (newCachedData) {
resource->clearCachedMetadata();
resource->setCachedMetadata(streamer->cachedDataType(), reinterpret_cast<const char*>(newCachedData->data), newCachedData->length, Resource::CacheLocally);
// TODO(yangguo,vogelheim): code cache should use Resource::SendToPlatform.
writeToCache(resource, streamer->cachedDataType(), Resource::CacheLocally, newCachedData, compressed);
}
} else if (!resource || !resource->url().protocolIsInHTTPFamily() || code->Length() < 1024) {
v8::ScriptCompiler::Source source(code, origin);
script = v8::ScriptCompiler::Compile(isolate, &source, v8::ScriptCompiler::kNoCompileOptions);
} else {
Resource::MetadataCacheType cacheType = Resource::CacheLocally;
v8::ScriptCompiler::CompileOptions consumeOption = v8::ScriptCompiler::kConsumeParserCache;
v8::ScriptCompiler::CompileOptions produceOption = v8::ScriptCompiler::kProduceParserCache;
switch (cacheOptions) {
case V8CacheOptionsOff:
// Use default.
cacheTag = tagForParserCache();
break;
case V8CacheOptionsParse:
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::SendToPlatform);
cacheType = Resource::SendToPlatform;
consumeOption = v8::ScriptCompiler::kConsumeParserCache;
produceOption = v8::ScriptCompiler::kProduceParserCache;
break;
case V8CacheOptionsCodeCompressed:
case V8CacheOptionsCode:
cacheTag = tagForCodeCache();
script = resource->cachedMetadata(cacheTag)
? compileAndConsumeCache(isolate, code, origin, resource, v8::ScriptCompiler::kConsumeCodeCache, cacheTag)
: compileAndProduceCache(isolate, code, origin, resource, v8::ScriptCompiler::kProduceCodeCache, cacheTag, Resource::SendToPlatform);
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);
cacheType = Resource::SendToPlatform;
consumeOption = v8::ScriptCompiler::kConsumeCodeCache;
produceOption = v8::ScriptCompiler::kProduceCodeCache;
break;
}
script = resource->cachedMetadata(cacheTag)
? compileAndConsumeCache(isolate, code, origin, resource, consumeOption, cacheTag, compressed)
: compileAndProduceCache(isolate, code, origin, resource, produceOption, cacheTag, cacheType, compressed);
}
return script;
}
......
......@@ -136,6 +136,17 @@ TEST_F(V8ScriptRunnerTest, codeOptions)
EXPECT_TRUE(compileScript(V8CacheOptionsCode));
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.
// Enable EXPECT when code caching lands.
// EXPECT_TRUE(m_resource->cachedMetadata(tagForCodeCache()));
......
......@@ -90,6 +90,7 @@ source_set("prerequisites") {
"//third_party/npapi",
"//third_party/ots",
"//third_party/qcms",
"//third_party/snappy",
"//third_party/sqlite",
"//third_party/zlib",
"//url",
......
......@@ -187,6 +187,7 @@
'<(DEPTH)/third_party/libxslt/libxslt.gyp:libxslt',
'<(DEPTH)/third_party/npapi/npapi.gyp:npapi',
'<(DEPTH)/third_party/qcms/qcms.gyp:qcms',
'<(DEPTH)/third_party/snappy/snappy.gyp:snappy',
'<(DEPTH)/third_party/sqlite/sqlite.gyp:sqlite',
'<(DEPTH)/url/url.gyp:url_lib',
'<(DEPTH)/v8/tools/gyp/v8.gyp:v8',
......
......@@ -639,6 +639,7 @@ COMPILE_ASSERT_MATCHING_ENUM(WebSelectionBound::SelectionRight, CompositedSelect
COMPILE_ASSERT_MATCHING_ENUM(WebSettings::V8CacheOptionsOff, V8CacheOptionsOff);
COMPILE_ASSERT_MATCHING_ENUM(WebSettings::V8CacheOptionsParse, V8CacheOptionsParse);
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::PointerTypeCoarse, PointerTypeCoarse);
......
......@@ -55,7 +55,8 @@ public:
enum V8CacheOptions {
V8CacheOptionsOff,
V8CacheOptionsParse,
V8CacheOptionsCode
V8CacheOptionsCode,
V8CacheOptionsCodeCompressed
};
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