Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2009 Google Inc. All rights reserved. | 2 * Copyright (C) 2009 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 * THE POSSIBILITY OF SUCH DAMAGE. | 23 * THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "config.h" | 26 #include "config.h" |
| 27 #include "bindings/core/v8/V8ScriptRunner.h" | 27 #include "bindings/core/v8/V8ScriptRunner.h" |
| 28 | 28 |
| 29 #include "bindings/core/v8/ScriptSourceCode.h" | 29 #include "bindings/core/v8/ScriptSourceCode.h" |
| 30 #include "bindings/core/v8/V8Binding.h" | 30 #include "bindings/core/v8/V8Binding.h" |
| 31 #include "bindings/core/v8/V8GCController.h" | 31 #include "bindings/core/v8/V8GCController.h" |
| 32 #include "bindings/core/v8/V8RecursionScope.h" | 32 #include "bindings/core/v8/V8RecursionScope.h" |
| 33 #include "bindings/core/v8/V8ScriptStreamer.h" | |
| 33 #include "bindings/core/v8/V8ThrowException.h" | 34 #include "bindings/core/v8/V8ThrowException.h" |
| 34 #include "core/dom/ExecutionContext.h" | 35 #include "core/dom/ExecutionContext.h" |
| 35 #include "core/fetch/CachedMetadata.h" | 36 #include "core/fetch/CachedMetadata.h" |
| 36 #include "core/fetch/ScriptResource.h" | 37 #include "core/fetch/ScriptResource.h" |
| 37 #include "platform/TraceEvent.h" | 38 #include "platform/TraceEvent.h" |
| 38 | 39 |
| 39 namespace blink { | 40 namespace blink { |
| 40 | 41 |
| 41 namespace { | 42 namespace { |
| 42 | 43 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 55 // If we are already handling a recursion level error, we should | 56 // If we are already handling a recursion level error, we should |
| 56 // not invoke v8::Function::Call. | 57 // not invoke v8::Function::Call. |
| 57 return v8::Undefined(isolate); | 58 return v8::Undefined(isolate); |
| 58 } | 59 } |
| 59 V8PerIsolateData::from(isolate)->setIsHandlingRecursionLevelError(true); | 60 V8PerIsolateData::from(isolate)->setIsHandlingRecursionLevelError(true); |
| 60 v8::Local<v8::Value> result = v8::Function::New(isolate, throwStackOverflowE xception)->Call(v8::Undefined(isolate), 0, 0); | 61 v8::Local<v8::Value> result = v8::Function::New(isolate, throwStackOverflowE xception)->Call(v8::Undefined(isolate), 0, 0); |
| 61 V8PerIsolateData::from(isolate)->setIsHandlingRecursionLevelError(false); | 62 V8PerIsolateData::from(isolate)->setIsHandlingRecursionLevelError(false); |
| 62 return result; | 63 return result; |
| 63 } | 64 } |
| 64 | 65 |
| 65 // Make a decision on whether we want to use V8 caching and how. | |
| 66 // dataType, produceOption, consumeOption are out parameters. | |
| 67 bool CacheDecider( | |
| 68 const v8::Handle<v8::String> code, | |
| 69 const ScriptResource* resource, | |
| 70 V8CacheOptions cacheOptions, | |
| 71 unsigned* dataType, | |
| 72 v8::ScriptCompiler::CompileOptions* compileOption, | |
| 73 bool* produce) | |
| 74 { | |
| 75 if (!resource || !resource->url().protocolIsInHTTPFamily() || code->Length() < 1024) | |
| 76 cacheOptions = V8CacheOptionsOff; | |
| 77 | |
| 78 bool useCache = false; | |
| 79 switch (cacheOptions) { | |
| 80 case V8CacheOptionsOff: | |
| 81 *compileOption = v8::ScriptCompiler::kNoCompileOptions; | |
| 82 useCache = false; | |
| 83 break; | |
| 84 case V8CacheOptionsParse: | |
| 85 *dataType = StringHash::hash(v8::V8::GetVersion()) * 2; | |
| 86 *produce = !resource->cachedMetadata(*dataType); | |
| 87 *compileOption = *produce ? v8::ScriptCompiler::kProduceParserCache : v8 ::ScriptCompiler::kConsumeParserCache; | |
| 88 useCache = true; | |
| 89 break; | |
| 90 case V8CacheOptionsCode: | |
| 91 *dataType = StringHash::hash(v8::V8::GetVersion()) * 2 + 1; | |
| 92 *produce = !resource->cachedMetadata(*dataType); | |
| 93 *compileOption = *produce ? v8::ScriptCompiler::kProduceCodeCache : v8:: ScriptCompiler::kConsumeCodeCache; | |
| 94 useCache = true; | |
| 95 break; | |
| 96 } | |
| 97 return useCache; | |
| 98 } | |
| 99 | |
| 100 } // namespace | 66 } // namespace |
| 101 | 67 |
| 102 v8::Local<v8::Script> V8ScriptRunner::compileScript(const ScriptSourceCode& sour ce, v8::Isolate* isolate, AccessControlStatus corsStatus, V8CacheOptions cacheOp tions) | 68 v8::Local<v8::Script> V8ScriptRunner::compileScript(const ScriptSourceCode& sour ce, v8::Isolate* isolate, AccessControlStatus corsStatus, V8CacheOptions cacheOp tions) |
| 103 { | 69 { |
| 104 return compileScript(v8String(isolate, source.source()), source.url(), sourc e.startPosition(), source.resource(), isolate, corsStatus, cacheOptions); | 70 return compileScript(v8String(isolate, source.source()), source.url(), sourc e.startPosition(), source.resource(), source.streamer(), isolate, corsStatus, ca cheOptions); |
| 105 } | 71 } |
| 106 | 72 |
| 107 v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition& scriptStartPosition, ScriptResource * resource, v8::Isolate* isolate, AccessControlStatus corsStatus, V8CacheOptions cacheOptions) | 73 v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition& scriptStartPosition, ScriptResource * resource, V8ScriptStreamer* streamer, v8::Isolate* isolate, AccessControlStatu s corsStatus, V8CacheOptions cacheOptions) |
| 108 { | 74 { |
| 109 TRACE_EVENT1("v8", "v8.compile", "fileName", fileName.utf8()); | 75 TRACE_EVENT1("v8", "v8.compile", "fileName", fileName.utf8()); |
| 110 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Compile"); | 76 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Compile"); |
| 111 | 77 |
| 112 // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at | 78 // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at |
| 113 // 1, whereas v8 starts at 0. | 79 // 1, whereas v8 starts at 0. |
| 114 v8::Handle<v8::String> name = v8String(isolate, fileName); | 80 v8::Handle<v8::String> name = v8String(isolate, fileName); |
| 115 v8::Handle<v8::Integer> line = v8::Integer::New(isolate, scriptStartPosition .m_line.zeroBasedInt()); | 81 v8::Handle<v8::Integer> line = v8::Integer::New(isolate, scriptStartPosition .m_line.zeroBasedInt()); |
| 116 v8::Handle<v8::Integer> column = v8::Integer::New(isolate, scriptStartPositi on.m_column.zeroBasedInt()); | 82 v8::Handle<v8::Integer> column = v8::Integer::New(isolate, scriptStartPositi on.m_column.zeroBasedInt()); |
| 117 v8::Handle<v8::Boolean> isSharedCrossOrigin = corsStatus == SharableCrossOri gin ? v8::True(isolate) : v8::False(isolate); | 83 v8::Handle<v8::Boolean> isSharedCrossOrigin = corsStatus == SharableCrossOri gin ? v8::True(isolate) : v8::False(isolate); |
| 118 v8::ScriptOrigin origin(name, line, column, isSharedCrossOrigin); | 84 v8::ScriptOrigin origin(name, line, column, isSharedCrossOrigin); |
| 119 | 85 |
| 120 // V8 supports several forms of caching. Decide on the cache mode and call | 86 // V8 supports several forms of caching. Decide on the cache mode and call |
| 121 // ScriptCompiler::Compile with suitable options. | 87 // ScriptCompiler::Compile with suitable options. |
| 122 unsigned dataTypeID = 0; | 88 unsigned dataTypeID = 0; |
| 123 v8::ScriptCompiler::CompileOptions compileOption = v8::ScriptCompiler::kNoCo mpileOptions; | 89 v8::ScriptCompiler::CompileOptions compileOption = v8::ScriptCompiler::kNoCo mpileOptions; |
| 124 bool produce; | 90 bool produce; |
| 125 v8::Local<v8::Script> script; | 91 v8::Local<v8::Script> script; |
| 126 if (CacheDecider(code, resource, cacheOptions, &dataTypeID, &compileOption, &produce)) { | 92 if (streamer) { |
| 93 // We don't stream scripts which don't have a Resource. | |
| 94 ASSERT(resource); | |
| 95 // Failed resources should never get this far. | |
| 96 ASSERT(!resource->errorOccurred()); | |
| 97 script = v8::ScriptCompiler::Compile(isolate, streamer->source(), code, origin); | |
| 98 // Whether to produce the cached data or not is decided when the | |
| 99 // streamer is started. Here we only need to get the data out. | |
| 100 const v8::ScriptCompiler::CachedData* newCachedData = streamer->source() ->GetCachedData(); | |
| 101 if (newCachedData) { | |
| 102 resource->setCachedMetadata(streamer->cachedDataDataType(), reinterp ret_cast<const char*>(newCachedData->data), newCachedData->length); | |
|
haraken
2014/08/17 16:05:25
Don't you need to call resource->clearCachedMetada
marja
2014/08/20 11:45:54
Done.
| |
| 103 } | |
| 104 } else if (CacheDecider(code->Length(), resource, cacheOptions, &dataTypeID, &compileOption, &produce)) { | |
| 127 if (produce) { | 105 if (produce) { |
| 128 // Produce new cache data: | 106 // Produce new cache data: |
| 129 v8::ScriptCompiler::Source source(code, origin); | 107 v8::ScriptCompiler::Source source(code, origin); |
| 130 script = v8::ScriptCompiler::Compile(isolate, &source, compileOption ); | 108 script = v8::ScriptCompiler::Compile(isolate, &source, compileOption ); |
| 131 const v8::ScriptCompiler::CachedData* cachedData = source.GetCachedD ata(); | 109 const v8::ScriptCompiler::CachedData* cachedData = source.GetCachedD ata(); |
| 132 if (cachedData) { | 110 if (cachedData) { |
| 133 resource->clearCachedMetadata(); | 111 resource->clearCachedMetadata(); |
| 134 resource->setCachedMetadata( | 112 resource->setCachedMetadata( |
| 135 dataTypeID, | 113 dataTypeID, |
| 136 reinterpret_cast<const char*>(cachedData->data), | 114 reinterpret_cast<const char*>(cachedData->data), |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 return v8::Local<v8::Value>(); | 156 return v8::Local<v8::Value>(); |
| 179 | 157 |
| 180 crashIfV8IsDead(); | 158 crashIfV8IsDead(); |
| 181 return result; | 159 return result; |
| 182 } | 160 } |
| 183 | 161 |
| 184 v8::Local<v8::Value> V8ScriptRunner::compileAndRunInternalScript(v8::Handle<v8:: String> source, v8::Isolate* isolate, const String& fileName, const TextPosition & scriptStartPosition) | 162 v8::Local<v8::Value> V8ScriptRunner::compileAndRunInternalScript(v8::Handle<v8:: String> source, v8::Isolate* isolate, const String& fileName, const TextPosition & scriptStartPosition) |
| 185 { | 163 { |
| 186 TRACE_EVENT0("v8", "v8.run"); | 164 TRACE_EVENT0("v8", "v8.run"); |
| 187 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Execution"); | 165 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Execution"); |
| 188 v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(source, fileNa me, scriptStartPosition, 0, isolate); | 166 v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(source, fileNa me, scriptStartPosition, 0, 0, isolate); |
| 189 if (script.IsEmpty()) | 167 if (script.IsEmpty()) |
| 190 return v8::Local<v8::Value>(); | 168 return v8::Local<v8::Value>(); |
| 191 | 169 |
| 192 V8RecursionScope::MicrotaskSuppression recursionScope(isolate); | 170 V8RecursionScope::MicrotaskSuppression recursionScope(isolate); |
| 193 v8::Local<v8::Value> result = script->Run(); | 171 v8::Local<v8::Value> result = script->Run(); |
| 194 crashIfV8IsDead(); | 172 crashIfV8IsDead(); |
| 195 return result; | 173 return result; |
| 196 } | 174 } |
| 197 | 175 |
| 198 v8::Local<v8::Value> V8ScriptRunner::callFunction(v8::Handle<v8::Function> funct ion, ExecutionContext* context, v8::Handle<v8::Value> receiver, int argc, v8::Ha ndle<v8::Value> args[], v8::Isolate* isolate) | 176 v8::Local<v8::Value> V8ScriptRunner::callFunction(v8::Handle<v8::Function> funct ion, ExecutionContext* context, v8::Handle<v8::Value> receiver, int argc, v8::Ha ndle<v8::Value> args[], v8::Isolate* isolate) |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 257 v8::Local<v8::Object> V8ScriptRunner::instantiateObjectInDocument(v8::Isolate* i solate, v8::Handle<v8::Function> function, ExecutionContext* context, int argc, v8::Handle<v8::Value> argv[]) | 235 v8::Local<v8::Object> V8ScriptRunner::instantiateObjectInDocument(v8::Isolate* i solate, v8::Handle<v8::Function> function, ExecutionContext* context, int argc, v8::Handle<v8::Value> argv[]) |
| 258 { | 236 { |
| 259 TRACE_EVENT0("v8", "v8.newInstance"); | 237 TRACE_EVENT0("v8", "v8.newInstance"); |
| 260 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Execution"); | 238 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Execution"); |
| 261 V8RecursionScope scope(isolate, context); | 239 V8RecursionScope scope(isolate, context); |
| 262 v8::Local<v8::Object> result = function->NewInstance(argc, argv); | 240 v8::Local<v8::Object> result = function->NewInstance(argc, argv); |
| 263 crashIfV8IsDead(); | 241 crashIfV8IsDead(); |
| 264 return result; | 242 return result; |
| 265 } | 243 } |
| 266 | 244 |
| 245 bool V8ScriptRunner::CacheDecider( | |
| 246 unsigned codeLength, | |
| 247 const ScriptResource* resource, | |
| 248 V8CacheOptions cacheOptions, | |
| 249 unsigned* dataType, | |
| 250 v8::ScriptCompiler::CompileOptions* compileOption, | |
| 251 bool* produce) | |
| 252 { | |
| 253 // Code length 0 means that we don't know it yet; don't make decisions based on it. | |
| 254 if (!resource || !resource->url().protocolIsInHTTPFamily() || (codeLength > 0 && codeLength < 1024)) | |
| 255 cacheOptions = V8CacheOptionsOff; | |
| 256 | |
| 257 bool useCache = false; | |
| 258 switch (cacheOptions) { | |
| 259 case V8CacheOptionsOff: | |
| 260 *compileOption = v8::ScriptCompiler::kNoCompileOptions; | |
| 261 useCache = false; | |
| 262 break; | |
| 263 case V8CacheOptionsParse: | |
| 264 *dataType = StringHash::hash(v8::V8::GetVersion()) * 2; | |
| 265 *produce = !resource->cachedMetadata(*dataType); | |
| 266 *compileOption = *produce ? v8::ScriptCompiler::kProduceParserCache : v8 ::ScriptCompiler::kConsumeParserCache; | |
| 267 useCache = true; | |
| 268 break; | |
| 269 case V8CacheOptionsCode: | |
| 270 *dataType = StringHash::hash(v8::V8::GetVersion()) * 2 + 1; | |
| 271 *produce = !resource->cachedMetadata(*dataType); | |
| 272 *compileOption = *produce ? v8::ScriptCompiler::kProduceCodeCache : v8:: ScriptCompiler::kConsumeCodeCache; | |
| 273 useCache = true; | |
| 274 break; | |
| 275 } | |
| 276 return useCache; | |
| 277 } | |
| 278 | |
| 279 | |
| 267 } // namespace blink | 280 } // namespace blink |
| OLD | NEW |