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 V8CacheOptionsType cacheOptions, | |
71 unsigned* dataType, | |
72 v8::ScriptCompiler::CompileOptions* compileOption, | |
73 bool* produce) | |
74 { | |
75 if (!resource || !resource->url().protocolIsInHTTPFamily() || code->Length() < 1024) { | |
jochen (gone - plz use gerrit)
2014/08/05 16:10:01
nit. no { }
vogelheim
2014/08/05 17:02:52
Done.
| |
76 cacheOptions = V8CacheOff; | |
77 } | |
78 | |
79 bool useCache = false; | |
80 switch (cacheOptions) { | |
81 case V8CacheOff: | |
82 *compileOption = v8::ScriptCompiler::kNoCompileOptions; | |
83 useCache = false; | |
84 break; | |
85 case V8CacheParse: | |
86 *dataType = StringHash::hash(v8::V8::GetVersion()) * 2; | |
87 *produce = !resource->cachedMetadata(*dataType); | |
88 *compileOption = *produce ? v8::ScriptCompiler::kProduceParserCache : v8 ::ScriptCompiler::kConsumeParserCache; | |
89 useCache = true; | |
90 break; | |
91 case V8CacheCode: | |
92 *dataType = StringHash::hash(v8::V8::GetVersion()) * 2 + 1; | |
93 *produce = !resource->cachedMetadata(*dataType); | |
94 *compileOption = *produce ? v8::ScriptCompiler::kProduceCodeCache : v8:: ScriptCompiler::kConsumeCodeCache; | |
95 useCache = true; | |
96 break; | |
97 } | |
98 return useCache; | |
99 } | |
100 | |
65 } // namespace | 101 } // namespace |
66 | 102 |
67 v8::Local<v8::Script> V8ScriptRunner::compileScript(const ScriptSourceCode& sour ce, v8::Isolate* isolate, AccessControlStatus corsStatus) | 103 v8::Local<v8::Script> V8ScriptRunner::compileScript(const ScriptSourceCode& sour ce, v8::Isolate* isolate, AccessControlStatus corsStatus, V8CacheOptionsType cac heOptions) |
68 { | 104 { |
69 return compileScript(v8String(isolate, source.source()), source.url(), sourc e.startPosition(), source.resource(), isolate, corsStatus); | 105 return compileScript(v8String(isolate, source.source()), source.url(), sourc e.startPosition(), source.resource(), isolate, corsStatus, cacheOptions); |
70 } | 106 } |
71 | 107 |
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) | 108 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 Type cacheOptions) |
73 { | 109 { |
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()); | 110 TRACE_EVENT1("v8", "v8.compile", "fileName", fileName.utf8()); |
82 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Compile"); | 111 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Compile"); |
83 | 112 |
84 // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at | 113 // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at |
85 // 1, whereas v8 starts at 0. | 114 // 1, whereas v8 starts at 0. |
86 v8::Handle<v8::String> name = v8String(isolate, fileName); | 115 v8::Handle<v8::String> name = v8String(isolate, fileName); |
87 v8::Handle<v8::Integer> line = v8::Integer::New(isolate, scriptStartPosition .m_line.zeroBasedInt()); | 116 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()); | 117 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); | 118 v8::Handle<v8::Boolean> isSharedCrossOrigin = corsStatus == SharableCrossOri gin ? v8::True(isolate) : v8::False(isolate); |
90 v8::ScriptOrigin origin(name, line, column, isSharedCrossOrigin); | 119 v8::ScriptOrigin origin(name, line, column, isSharedCrossOrigin); |
91 | 120 |
92 v8::ScriptCompiler::CompileOptions options = v8::ScriptCompiler::kNoCompileO ptions; | 121 // V8 supports several forms of caching. Decide on the cache mode and call |
93 OwnPtr<v8::ScriptCompiler::CachedData> cachedData; | 122 // ScriptCompiler::Compile with suitable options. |
94 if (resource) { | 123 unsigned dataTypeID = 0; |
95 CachedMetadata* cachedMetadata = resource->cachedMetadata(dataTypeID); | 124 v8::ScriptCompiler::CompileOptions compileOption = v8::ScriptCompiler::kNoCo mpileOptions; |
96 if (cachedMetadata) { | 125 bool produce; |
97 // Ownership of the buffer is not transferred to CachedData. | 126 v8::Local<v8::Script> script; |
98 cachedData = adoptPtr(new v8::ScriptCompiler::CachedData(reinterpret _cast<const uint8_t*>(cachedMetadata->data()), cachedMetadata->size())); | 127 if (CacheDecider(code, resource, cacheOptions, &dataTypeID, &compileOption, &produce)) { |
99 } else if (code->Length() >= minLengthForCachedData) { | 128 if (produce) { |
100 options = v8::ScriptCompiler::kProduceDataToCache; | 129 // Produce new cache data: |
130 v8::ScriptCompiler::Source source(code, origin); | |
131 script = v8::ScriptCompiler::Compile(isolate, &source, compileOption ); | |
132 const v8::ScriptCompiler::CachedData* cachedData = source.GetCachedD ata(); | |
133 if (cachedData) { | |
134 resource->clearCachedMetadata(); | |
135 resource->setCachedMetadata( | |
136 dataTypeID, | |
137 reinterpret_cast<const char*>(cachedData->data), | |
138 cachedData->length); | |
139 } | |
140 } else { | |
141 // Consume existing cache data: | |
142 CachedMetadata* cachedMetadata = resource->cachedMetadata(dataTypeID ); | |
143 v8::ScriptCompiler::CachedData* cachedData = new v8::ScriptCompiler: :CachedData( | |
144 reinterpret_cast<const uint8_t*>(cachedMetadata->data()), | |
145 cachedMetadata->size(), | |
146 v8::ScriptCompiler::CachedData::BufferNotOwned); | |
147 v8::ScriptCompiler::Source source(code, origin, cachedData); | |
148 script = v8::ScriptCompiler::Compile(isolate, &source, compileOption ); | |
101 } | 149 } |
102 } | 150 } else { |
103 // source takes ownership of cachedData. | 151 // No caching: |
104 v8::ScriptCompiler::Source source(code, origin, cachedData.leakPtr()); | 152 v8::ScriptCompiler::Source source(code, origin); |
105 v8::Local<v8::Script> script = v8::ScriptCompiler::Compile(isolate, &source, options); | 153 script = v8::ScriptCompiler::Compile( |
106 if (options == v8::ScriptCompiler::kProduceDataToCache) { | 154 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 } | 155 } |
113 return script; | 156 return script; |
114 } | 157 } |
115 | 158 |
116 v8::Local<v8::Value> V8ScriptRunner::runCompiledScript(v8::Handle<v8::Script> sc ript, ExecutionContext* context, v8::Isolate* isolate) | 159 v8::Local<v8::Value> V8ScriptRunner::runCompiledScript(v8::Handle<v8::Script> sc ript, ExecutionContext* context, v8::Isolate* isolate) |
117 { | 160 { |
118 if (script.IsEmpty()) | 161 if (script.IsEmpty()) |
119 return v8::Local<v8::Value>(); | 162 return v8::Local<v8::Value>(); |
120 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Execution"); | 163 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Execution"); |
121 TRACE_EVENT1("v8", "v8.run", "fileName", TRACE_STR_COPY(*v8::String::Utf8Val ue(script->GetUnboundScript()->GetScriptName()))); | 164 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 { | 259 { |
217 TRACE_EVENT0("v8", "v8.newInstance"); | 260 TRACE_EVENT0("v8", "v8.newInstance"); |
218 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Execution"); | 261 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Execution"); |
219 V8RecursionScope scope(isolate, context); | 262 V8RecursionScope scope(isolate, context); |
220 v8::Local<v8::Object> result = function->NewInstance(argc, argv); | 263 v8::Local<v8::Object> result = function->NewInstance(argc, argv); |
221 crashIfV8IsDead(); | 264 crashIfV8IsDead(); |
222 return result; | 265 return result; |
223 } | 266 } |
224 | 267 |
225 } // namespace blink | 268 } // namespace blink |
OLD | NEW |