| Index: Source/bindings/core/v8/V8ScriptRunner.cpp
|
| diff --git a/Source/bindings/core/v8/V8ScriptRunner.cpp b/Source/bindings/core/v8/V8ScriptRunner.cpp
|
| index 5e600fc384b273a669664138fc90cf15530c7cf9..b52f89a3f67e34ab7dd772c7a549941be3699f72 100644
|
| --- a/Source/bindings/core/v8/V8ScriptRunner.cpp
|
| +++ b/Source/bindings/core/v8/V8ScriptRunner.cpp
|
| @@ -62,22 +62,46 @@ v8::Local<v8::Value> throwStackOverflowExceptionIfNeeded(v8::Isolate* isolate)
|
| return result;
|
| }
|
|
|
| +// Make a decision on whether we want to use V8 caching and how.
|
| +// dataType, produceOption, consumeOption are out parameters.
|
| +bool CacheDecider(
|
| + const v8::Handle<v8::String> code,
|
| + const ScriptResource* resource,
|
| + const String& cacheOptions,
|
| + unsigned* dataType,
|
| + v8::ScriptCompiler::CompileOptions* compileOption,
|
| + bool* produce)
|
| +{
|
| + *compileOption = v8::ScriptCompiler::kNoCompileOptions;
|
| + if (cacheOptions.isEmpty() || !resource || !resource->url().protocolIsInHTTPFamily() || code->Length() < 1024) {
|
| + return false;
|
| + }
|
| +
|
| + unsigned v8VersionHash = StringHash::hash(v8::V8::GetVersion());
|
| + if (cacheOptions == "parse") {
|
| + *dataType = v8VersionHash * 2;
|
| + *produce = resource->cachedMetadata(*dataType);
|
| + *compileOption = *produce ? v8::ScriptCompiler::kProduceParserCache : v8::ScriptCompiler::kConsumeParserCache;
|
| + return true;
|
| + }
|
| + if (cacheOptions == "code") {
|
| + *dataType = v8VersionHash * 2 + 1;
|
| + *produce = resource->cachedMetadata(*dataType);
|
| + *compileOption = *produce ? v8::ScriptCompiler::kProduceCodeCache : v8::ScriptCompiler::kConsumeCodeCache;
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| } // namespace
|
|
|
| -v8::Local<v8::Script> V8ScriptRunner::compileScript(const ScriptSourceCode& source, v8::Isolate* isolate, AccessControlStatus corsStatus)
|
| +v8::Local<v8::Script> V8ScriptRunner::compileScript(const ScriptSourceCode& source, v8::Isolate* isolate, AccessControlStatus corsStatus, const String& cacheOptions)
|
| {
|
| - return compileScript(v8String(isolate, source.source()), source.url(), source.startPosition(), source.resource(), isolate, corsStatus);
|
| + return compileScript(v8String(isolate, source.source()), source.url(), source.startPosition(), source.resource(), isolate, corsStatus, cacheOptions);
|
| }
|
|
|
| -v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition& scriptStartPosition, ScriptResource* resource, v8::Isolate* isolate, AccessControlStatus corsStatus)
|
| +v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition& scriptStartPosition, ScriptResource* resource, v8::Isolate* isolate, AccessControlStatus corsStatus, const String& cacheOptions)
|
| {
|
| - // A pseudo-randomly chosen ID used to store and retrieve V8 ScriptData from
|
| - // the ScriptResource. If the format changes, this ID should be changed too.
|
| - static const unsigned dataTypeID = 0xECC13BD7;
|
| -
|
| - // Very small scripts are not worth the effort to store cached data.
|
| - static const int minLengthForCachedData = 1024;
|
| -
|
| TRACE_EVENT1("v8", "v8.compile", "fileName", fileName.utf8());
|
| TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Compile");
|
|
|
| @@ -89,26 +113,40 @@ v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code,
|
| v8::Handle<v8::Boolean> isSharedCrossOrigin = corsStatus == SharableCrossOrigin ? v8::True(isolate) : v8::False(isolate);
|
| v8::ScriptOrigin origin(name, line, column, isSharedCrossOrigin);
|
|
|
| - v8::ScriptCompiler::CompileOptions options = v8::ScriptCompiler::kNoCompileOptions;
|
| - OwnPtr<v8::ScriptCompiler::CachedData> cachedData;
|
| - if (resource) {
|
| - CachedMetadata* cachedMetadata = resource->cachedMetadata(dataTypeID);
|
| - if (cachedMetadata) {
|
| - // Ownership of the buffer is not transferred to CachedData.
|
| - cachedData = adoptPtr(new v8::ScriptCompiler::CachedData(reinterpret_cast<const uint8_t*>(cachedMetadata->data()), cachedMetadata->size()));
|
| - } else if (code->Length() >= minLengthForCachedData) {
|
| - options = v8::ScriptCompiler::kProduceDataToCache;
|
| - }
|
| - }
|
| - // source takes ownership of cachedData.
|
| - v8::ScriptCompiler::Source source(code, origin, cachedData.leakPtr());
|
| - v8::Local<v8::Script> script = v8::ScriptCompiler::Compile(isolate, &source, options);
|
| - if (options == v8::ScriptCompiler::kProduceDataToCache) {
|
| - const v8::ScriptCompiler::CachedData* newCachedData = source.GetCachedData();
|
| - if (newCachedData) {
|
| - // Ownership of the buffer is not transferred; source's cachedData continues to own it.
|
| - resource->setCachedMetadata(dataTypeID, reinterpret_cast<const char*>(newCachedData->data), newCachedData->length);
|
| + // V8 supports several forms of caching. Decide on the cache mode and call
|
| + // ScriptCompiler::Compile with suitable options.
|
| + unsigned dataTypeID = 0;
|
| + v8::ScriptCompiler::CompileOptions compileOption = v8::ScriptCompiler::kNoCompileOptions;
|
| + bool produce;
|
| + v8::Local<v8::Script> script;
|
| + if (CacheDecider(code, resource, cacheOptions, &dataTypeID, &compileOption, &produce)) {
|
| + if (produce) {
|
| + // Produce new cache data:
|
| + v8::ScriptCompiler::Source source(code, origin);
|
| + script = v8::ScriptCompiler::Compile(isolate, &source, compileOption);
|
| + const v8::ScriptCompiler::CachedData* cachedData = source.GetCachedData();
|
| + if (cachedData) {
|
| + resource->clearCachedMetadata();
|
| + resource->setCachedMetadata(
|
| + dataTypeID,
|
| + reinterpret_cast<const char*>(cachedData->data),
|
| + cachedData->length);
|
| + }
|
| + } else {
|
| + // Consume existing cache data:
|
| + CachedMetadata* cachedMetadata = resource->cachedMetadata(dataTypeID);
|
| + v8::ScriptCompiler::CachedData* cachedData = new v8::ScriptCompiler::CachedData(
|
| + reinterpret_cast<const uint8_t*>(cachedMetadata->data()),
|
| + cachedMetadata->size(),
|
| + v8::ScriptCompiler::CachedData::BufferNotOwned);
|
| + v8::ScriptCompiler::Source source(code, origin, cachedData);
|
| + script = v8::ScriptCompiler::Compile(isolate, &source, compileOption);
|
| }
|
| + } else {
|
| + // No caching:
|
| + v8::ScriptCompiler::Source source(code, origin);
|
| + script = v8::ScriptCompiler::Compile(
|
| + isolate, &source, v8::ScriptCompiler::kNoCompileOptions);
|
| }
|
| return script;
|
| }
|
|
|