| 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 // If we are already handling a recursion level error, we should | 55 // If we are already handling a recursion level error, we should |
| 56 // not invoke v8::Function::Call. | 56 // not invoke v8::Function::Call. |
| 57 return v8::Undefined(isolate); | 57 return v8::Undefined(isolate); |
| 58 } | 58 } |
| 59 V8PerIsolateData::from(isolate)->setIsHandlingRecursionLevelError(true); | 59 V8PerIsolateData::from(isolate)->setIsHandlingRecursionLevelError(true); |
| 60 v8::Local<v8::Value> result = v8::Function::New(isolate, throwStackOverflowE
xception)->Call(v8::Undefined(isolate), 0, 0); | 60 v8::Local<v8::Value> result = v8::Function::New(isolate, throwStackOverflowE
xception)->Call(v8::Undefined(isolate), 0, 0); |
| 61 V8PerIsolateData::from(isolate)->setIsHandlingRecursionLevelError(false); | 61 V8PerIsolateData::from(isolate)->setIsHandlingRecursionLevelError(false); |
| 62 return result; | 62 return result; |
| 63 } | 63 } |
| 64 | 64 |
| 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 |
| 65 } // namespace | 100 } // namespace |
| 66 | 101 |
| 67 v8::Local<v8::Script> V8ScriptRunner::compileScript(const ScriptSourceCode& sour
ce, v8::Isolate* isolate, AccessControlStatus corsStatus) | 102 v8::Local<v8::Script> V8ScriptRunner::compileScript(const ScriptSourceCode& sour
ce, v8::Isolate* isolate, AccessControlStatus corsStatus, V8CacheOptions cacheOp
tions) |
| 68 { | 103 { |
| 69 return compileScript(v8String(isolate, source.source()), source.url(), sourc
e.startPosition(), source.resource(), isolate, corsStatus); | 104 return compileScript(v8String(isolate, source.source()), source.url(), sourc
e.startPosition(), source.resource(), isolate, corsStatus, cacheOptions); |
| 70 } | 105 } |
| 71 | 106 |
| 72 v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code,
const String& fileName, const TextPosition& scriptStartPosition, ScriptResource
* resource, v8::Isolate* isolate, AccessControlStatus corsStatus) | 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 { | 108 { |
| 74 // A pseudo-randomly chosen ID used to store and retrieve V8 ScriptData from | |
| 75 // the ScriptResource. If the format changes, this ID should be changed too. | |
| 76 static const unsigned dataTypeID = 0xECC13BD7; | |
| 77 | |
| 78 // Very small scripts are not worth the effort to store cached data. | |
| 79 static const int minLengthForCachedData = 1024; | |
| 80 | |
| 81 TRACE_EVENT1("v8", "v8.compile", "fileName", fileName.utf8()); | 109 TRACE_EVENT1("v8", "v8.compile", "fileName", fileName.utf8()); |
| 82 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Compile"); | 110 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Compile"); |
| 83 | 111 |
| 84 // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at | 112 // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at |
| 85 // 1, whereas v8 starts at 0. | 113 // 1, whereas v8 starts at 0. |
| 86 v8::Handle<v8::String> name = v8String(isolate, fileName); | 114 v8::Handle<v8::String> name = v8String(isolate, fileName); |
| 87 v8::Handle<v8::Integer> line = v8::Integer::New(isolate, scriptStartPosition
.m_line.zeroBasedInt()); | 115 v8::Handle<v8::Integer> line = v8::Integer::New(isolate, scriptStartPosition
.m_line.zeroBasedInt()); |
| 88 v8::Handle<v8::Integer> column = v8::Integer::New(isolate, scriptStartPositi
on.m_column.zeroBasedInt()); | 116 v8::Handle<v8::Integer> column = v8::Integer::New(isolate, scriptStartPositi
on.m_column.zeroBasedInt()); |
| 89 v8::Handle<v8::Boolean> isSharedCrossOrigin = corsStatus == SharableCrossOri
gin ? v8::True(isolate) : v8::False(isolate); | 117 v8::Handle<v8::Boolean> isSharedCrossOrigin = corsStatus == SharableCrossOri
gin ? v8::True(isolate) : v8::False(isolate); |
| 90 v8::ScriptOrigin origin(name, line, column, isSharedCrossOrigin); | 118 v8::ScriptOrigin origin(name, line, column, isSharedCrossOrigin); |
| 91 | 119 |
| 92 v8::ScriptCompiler::CompileOptions options = v8::ScriptCompiler::kNoCompileO
ptions; | 120 // V8 supports several forms of caching. Decide on the cache mode and call |
| 93 OwnPtr<v8::ScriptCompiler::CachedData> cachedData; | 121 // ScriptCompiler::Compile with suitable options. |
| 94 if (resource) { | 122 unsigned dataTypeID = 0; |
| 95 CachedMetadata* cachedMetadata = resource->cachedMetadata(dataTypeID); | 123 v8::ScriptCompiler::CompileOptions compileOption = v8::ScriptCompiler::kNoCo
mpileOptions; |
| 96 if (cachedMetadata) { | 124 bool produce; |
| 97 // Ownership of the buffer is not transferred to CachedData. | 125 v8::Local<v8::Script> script; |
| 98 cachedData = adoptPtr(new v8::ScriptCompiler::CachedData(reinterpret
_cast<const uint8_t*>(cachedMetadata->data()), cachedMetadata->size())); | 126 if (CacheDecider(code, resource, cacheOptions, &dataTypeID, &compileOption,
&produce)) { |
| 99 } else if (code->Length() >= minLengthForCachedData) { | 127 if (produce) { |
| 100 options = v8::ScriptCompiler::kProduceDataToCache; | 128 // Produce new cache data: |
| 129 v8::ScriptCompiler::Source source(code, origin); |
| 130 script = v8::ScriptCompiler::Compile(isolate, &source, compileOption
); |
| 131 const v8::ScriptCompiler::CachedData* cachedData = source.GetCachedD
ata(); |
| 132 if (cachedData) { |
| 133 resource->clearCachedMetadata(); |
| 134 resource->setCachedMetadata( |
| 135 dataTypeID, |
| 136 reinterpret_cast<const char*>(cachedData->data), |
| 137 cachedData->length); |
| 138 } |
| 139 } else { |
| 140 // Consume existing cache data: |
| 141 CachedMetadata* cachedMetadata = resource->cachedMetadata(dataTypeID
); |
| 142 v8::ScriptCompiler::CachedData* cachedData = new v8::ScriptCompiler:
:CachedData( |
| 143 reinterpret_cast<const uint8_t*>(cachedMetadata->data()), |
| 144 cachedMetadata->size(), |
| 145 v8::ScriptCompiler::CachedData::BufferNotOwned); |
| 146 v8::ScriptCompiler::Source source(code, origin, cachedData); |
| 147 script = v8::ScriptCompiler::Compile(isolate, &source, compileOption
); |
| 101 } | 148 } |
| 102 } | 149 } else { |
| 103 // source takes ownership of cachedData. | 150 // No caching: |
| 104 v8::ScriptCompiler::Source source(code, origin, cachedData.leakPtr()); | 151 v8::ScriptCompiler::Source source(code, origin); |
| 105 v8::Local<v8::Script> script = v8::ScriptCompiler::Compile(isolate, &source,
options); | 152 script = v8::ScriptCompiler::Compile( |
| 106 if (options == v8::ScriptCompiler::kProduceDataToCache) { | 153 isolate, &source, v8::ScriptCompiler::kNoCompileOptions); |
| 107 const v8::ScriptCompiler::CachedData* newCachedData = source.GetCachedDa
ta(); | |
| 108 if (newCachedData) { | |
| 109 // Ownership of the buffer is not transferred; source's cachedData c
ontinues to own it. | |
| 110 resource->setCachedMetadata(dataTypeID, reinterpret_cast<const char*
>(newCachedData->data), newCachedData->length); | |
| 111 } | |
| 112 } | 154 } |
| 113 return script; | 155 return script; |
| 114 } | 156 } |
| 115 | 157 |
| 116 v8::Local<v8::Value> V8ScriptRunner::runCompiledScript(v8::Handle<v8::Script> sc
ript, ExecutionContext* context, v8::Isolate* isolate) | 158 v8::Local<v8::Value> V8ScriptRunner::runCompiledScript(v8::Handle<v8::Script> sc
ript, ExecutionContext* context, v8::Isolate* isolate) |
| 117 { | 159 { |
| 118 if (script.IsEmpty()) | 160 if (script.IsEmpty()) |
| 119 return v8::Local<v8::Value>(); | 161 return v8::Local<v8::Value>(); |
| 120 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Execution"); | 162 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Execution"); |
| 121 TRACE_EVENT1("v8", "v8.run", "fileName", TRACE_STR_COPY(*v8::String::Utf8Val
ue(script->GetUnboundScript()->GetScriptName()))); | 163 TRACE_EVENT1("v8", "v8.run", "fileName", TRACE_STR_COPY(*v8::String::Utf8Val
ue(script->GetUnboundScript()->GetScriptName()))); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 { | 258 { |
| 217 TRACE_EVENT0("v8", "v8.newInstance"); | 259 TRACE_EVENT0("v8", "v8.newInstance"); |
| 218 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Execution"); | 260 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Execution"); |
| 219 V8RecursionScope scope(isolate, context); | 261 V8RecursionScope scope(isolate, context); |
| 220 v8::Local<v8::Object> result = function->NewInstance(argc, argv); | 262 v8::Local<v8::Object> result = function->NewInstance(argc, argv); |
| 221 crashIfV8IsDead(); | 263 crashIfV8IsDead(); |
| 222 return result; | 264 return result; |
| 223 } | 265 } |
| 224 | 266 |
| 225 } // namespace blink | 267 } // namespace blink |
| OLD | NEW |