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; |
} |