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 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 v8::ScriptCompiler::CachedData* cachedData = new v8::ScriptCompiler::CachedD
ata( | 146 v8::ScriptCompiler::CachedData* cachedData = new v8::ScriptCompiler::CachedD
ata( |
147 reinterpret_cast<const uint8_t*>(data), length, v8::ScriptCompiler::Cach
edData::BufferNotOwned); | 147 reinterpret_cast<const uint8_t*>(data), length, v8::ScriptCompiler::Cach
edData::BufferNotOwned); |
148 v8::ScriptCompiler::Source source(code, origin, cachedData); | 148 v8::ScriptCompiler::Source source(code, origin, cachedData); |
149 v8::MaybeLocal<v8::Script> script = v8::ScriptCompiler::Compile(isolate->Get
CurrentContext(), &source, compileOptions); | 149 v8::MaybeLocal<v8::Script> script = v8::ScriptCompiler::Compile(isolate->Get
CurrentContext(), &source, compileOptions); |
150 if (cachedData->rejected) | 150 if (cachedData->rejected) |
151 cacheHandler->clearCachedMetadata(CachedMetadataHandler::SendToPlatform)
; | 151 cacheHandler->clearCachedMetadata(CachedMetadataHandler::SendToPlatform)
; |
152 return script; | 152 return script; |
153 } | 153 } |
154 | 154 |
155 // Compile a script, and produce a V8 cache for future use. | 155 // Compile a script, and produce a V8 cache for future use. |
156 v8::MaybeLocal<v8::Script> compileAndProduceCache(CachedMetadataHandler* cacheHa
ndler, unsigned tag, v8::ScriptCompiler::CompileOptions compileOptions, CachedMe
tadataHandler::CacheType cacheType, v8::Isolate* isolate, v8::Local<v8::String>
code, v8::ScriptOrigin origin) | 156 v8::MaybeLocal<v8::Script> compileAndProduceCache(CachedMetadataHandler* cacheHa
ndler, uint32_t tag, v8::ScriptCompiler::CompileOptions compileOptions, CachedMe
tadataHandler::CacheType cacheType, v8::Isolate* isolate, v8::Local<v8::String>
code, v8::ScriptOrigin origin) |
157 { | 157 { |
158 V8CompileHistogram histogramScope(V8CompileHistogram::Cacheable); | 158 V8CompileHistogram histogramScope(V8CompileHistogram::Cacheable); |
159 v8::ScriptCompiler::Source source(code, origin); | 159 v8::ScriptCompiler::Source source(code, origin); |
160 v8::MaybeLocal<v8::Script> script = v8::ScriptCompiler::Compile(isolate->Get
CurrentContext(), &source, compileOptions); | 160 v8::MaybeLocal<v8::Script> script = v8::ScriptCompiler::Compile(isolate->Get
CurrentContext(), &source, compileOptions); |
161 const v8::ScriptCompiler::CachedData* cachedData = source.GetCachedData(); | 161 const v8::ScriptCompiler::CachedData* cachedData = source.GetCachedData(); |
162 if (cachedData) { | 162 if (cachedData) { |
163 const char* data = reinterpret_cast<const char*>(cachedData->data); | 163 const char* data = reinterpret_cast<const char*>(cachedData->data); |
164 int length = cachedData->length; | 164 int length = cachedData->length; |
165 if (length > 1024) { | 165 if (length > 1024) { |
166 // Omit histogram samples for small cache data to avoid outliers. | 166 // Omit histogram samples for small cache data to avoid outliers. |
167 int cacheSizeRatio = static_cast<int>(100.0 * length / code->Length(
)); | 167 int cacheSizeRatio = static_cast<int>(100.0 * length / code->Length(
)); |
168 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, codeCacheSizeH
istogram, new CustomCountHistogram("V8.CodeCacheSizeRatio", 0, 10000, 50)); | 168 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, codeCacheSizeH
istogram, new CustomCountHistogram("V8.CodeCacheSizeRatio", 0, 10000, 50)); |
169 codeCacheSizeHistogram.count(cacheSizeRatio); | 169 codeCacheSizeHistogram.count(cacheSizeRatio); |
170 } | 170 } |
171 cacheHandler->clearCachedMetadata(CachedMetadataHandler::CacheLocally); | 171 cacheHandler->clearCachedMetadata(CachedMetadataHandler::CacheLocally); |
172 cacheHandler->setCachedMetadata(tag, data, length, cacheType); | 172 cacheHandler->setCachedMetadata(tag, data, length, cacheType); |
173 } | 173 } |
174 return script; | 174 return script; |
175 } | 175 } |
176 | 176 |
177 // Compile a script, and consume or produce a V8 Cache, depending on whether the | 177 // Compile a script, and consume or produce a V8 Cache, depending on whether the |
178 // given resource already has cached data available. | 178 // given resource already has cached data available. |
179 v8::MaybeLocal<v8::Script> compileAndConsumeOrProduce(CachedMetadataHandler* cac
heHandler, unsigned tag, v8::ScriptCompiler::CompileOptions consumeOptions, v8::
ScriptCompiler::CompileOptions produceOptions, CachedMetadataHandler::CacheType
cacheType, v8::Isolate* isolate, v8::Local<v8::String> code, v8::ScriptOrigin or
igin) | 179 v8::MaybeLocal<v8::Script> compileAndConsumeOrProduce(CachedMetadataHandler* cac
heHandler, uint32_t tag, v8::ScriptCompiler::CompileOptions consumeOptions, v8::
ScriptCompiler::CompileOptions produceOptions, CachedMetadataHandler::CacheType
cacheType, v8::Isolate* isolate, v8::Local<v8::String> code, v8::ScriptOrigin or
igin) |
180 { | 180 { |
181 RefPtr<CachedMetadata> codeCache(cacheHandler->cachedMetadata(tag)); | 181 RefPtr<CachedMetadata> codeCache(cacheHandler->cachedMetadata(tag)); |
182 return codeCache.get() | 182 return codeCache.get() |
183 ? compileAndConsumeCache(cacheHandler, codeCache, consumeOptions, isolat
e, code, origin) | 183 ? compileAndConsumeCache(cacheHandler, codeCache, consumeOptions, isolat
e, code, origin) |
184 : compileAndProduceCache(cacheHandler, tag, produceOptions, cacheType, i
solate, code, origin); | 184 : compileAndProduceCache(cacheHandler, tag, produceOptions, cacheType, i
solate, code, origin); |
185 } | 185 } |
186 | 186 |
187 enum CacheTagKind { | 187 enum CacheTagKind { |
188 CacheTagParser = 0, | 188 CacheTagParser = 0, |
189 CacheTagCode = 1, | 189 CacheTagCode = 1, |
190 CacheTagTimeStamp = 3, | 190 CacheTagTimeStamp = 3, |
191 CacheTagLast | 191 CacheTagLast |
192 }; | 192 }; |
193 | 193 |
194 static const int kCacheTagKindSize = 2; | 194 static const int kCacheTagKindSize = 2; |
195 | 195 |
196 unsigned cacheTag(CacheTagKind kind, CachedMetadataHandler* cacheHandler) | 196 uint32_t cacheTag(CacheTagKind kind, CachedMetadataHandler* cacheHandler) |
197 { | 197 { |
198 static_assert((1 << kCacheTagKindSize) >= CacheTagLast, "CacheTagLast must b
e large enough"); | 198 static_assert((1 << kCacheTagKindSize) >= CacheTagLast, "CacheTagLast must b
e large enough"); |
199 | 199 |
200 static unsigned v8CacheDataVersion = v8::ScriptCompiler::CachedDataVersionTa
g() << kCacheTagKindSize; | 200 static uint32_t v8CacheDataVersion = v8::ScriptCompiler::CachedDataVersionTa
g() << kCacheTagKindSize; |
201 | 201 |
202 // A script can be (successfully) interpreted with different encodings, | 202 // A script can be (successfully) interpreted with different encodings, |
203 // depending on the page it appears in. The cache doesn't know anything | 203 // depending on the page it appears in. The cache doesn't know anything |
204 // about encodings, but the cached data is specific to one encoding. If we | 204 // about encodings, but the cached data is specific to one encoding. If we |
205 // later load the script from the cache and interpret it with a different | 205 // later load the script from the cache and interpret it with a different |
206 // encoding, the cached data is not valid for that encoding. | 206 // encoding, the cached data is not valid for that encoding. |
207 return (v8CacheDataVersion | kind) + StringHash::hash(cacheHandler->encoding
()); | 207 return (v8CacheDataVersion | kind) + StringHash::hash(cacheHandler->encoding
()); |
208 } | 208 } |
209 | 209 |
210 // Check previously stored timestamp. | 210 // Check previously stored timestamp. |
211 bool isResourceHotForCaching(CachedMetadataHandler* cacheHandler, int hotHours) | 211 bool isResourceHotForCaching(CachedMetadataHandler* cacheHandler, int hotHours) |
212 { | 212 { |
213 const double cacheWithinSeconds = hotHours * 60 * 60; | 213 const double cacheWithinSeconds = hotHours * 60 * 60; |
214 unsigned tag = cacheTag(CacheTagTimeStamp, cacheHandler); | 214 uint32_t tag = cacheTag(CacheTagTimeStamp, cacheHandler); |
215 RefPtr<CachedMetadata> cachedMetadata = cacheHandler->cachedMetadata(tag); | 215 RefPtr<CachedMetadata> cachedMetadata = cacheHandler->cachedMetadata(tag); |
216 if (!cachedMetadata) | 216 if (!cachedMetadata) |
217 return false; | 217 return false; |
218 double timeStamp; | 218 double timeStamp; |
219 const int size = sizeof(timeStamp); | 219 const int size = sizeof(timeStamp); |
220 ASSERT(cachedMetadata->size() == size); | 220 ASSERT(cachedMetadata->size() == size); |
221 memcpy(&timeStamp, cachedMetadata->data(), size); | 221 memcpy(&timeStamp, cachedMetadata->data(), size); |
222 return (WTF::currentTime() - timeStamp) < cacheWithinSeconds; | 222 return (WTF::currentTime() - timeStamp) < cacheWithinSeconds; |
223 } | 223 } |
224 | 224 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 case V8CacheOptionsCode: | 304 case V8CacheOptionsCode: |
305 case V8CacheOptionsAlways: { | 305 case V8CacheOptionsAlways: { |
306 // Use code caching for recently seen resources. | 306 // Use code caching for recently seen resources. |
307 // Use compression depending on the cache option. | 307 // Use compression depending on the cache option. |
308 if (codeCache) | 308 if (codeCache) |
309 return bind(compileAndConsumeCache, wrapPersistent(cacheHandler), co
deCache, v8::ScriptCompiler::kConsumeCodeCache); | 309 return bind(compileAndConsumeCache, wrapPersistent(cacheHandler), co
deCache, v8::ScriptCompiler::kConsumeCodeCache); |
310 if (cacheOptions != V8CacheOptionsAlways && !isResourceHotForCaching(cac
heHandler, hotHours)) { | 310 if (cacheOptions != V8CacheOptionsAlways && !isResourceHotForCaching(cac
heHandler, hotHours)) { |
311 V8ScriptRunner::setCacheTimeStamp(cacheHandler); | 311 V8ScriptRunner::setCacheTimeStamp(cacheHandler); |
312 return bind(compileWithoutOptions, V8CompileHistogram::Cacheable); | 312 return bind(compileWithoutOptions, V8CompileHistogram::Cacheable); |
313 } | 313 } |
314 unsigned codeCacheTag = cacheTag(CacheTagCode, cacheHandler); | 314 uint32_t codeCacheTag = cacheTag(CacheTagCode, cacheHandler); |
315 return bind(compileAndProduceCache, wrapPersistent(cacheHandler), codeCa
cheTag, v8::ScriptCompiler::kProduceCodeCache, CachedMetadataHandler::SendToPlat
form); | 315 return bind(compileAndProduceCache, wrapPersistent(cacheHandler), codeCa
cheTag, v8::ScriptCompiler::kProduceCodeCache, CachedMetadataHandler::SendToPlat
form); |
316 break; | 316 break; |
317 } | 317 } |
318 | 318 |
319 case V8CacheOptionsNone: | 319 case V8CacheOptionsNone: |
320 // Shouldn't happen, as this is handled above. | 320 // Shouldn't happen, as this is handled above. |
321 // Case is here so that compiler can check all cases are handled. | 321 // Case is here so that compiler can check all cases are handled. |
322 ASSERT_NOT_REACHED(); | 322 ASSERT_NOT_REACHED(); |
323 break; | 323 break; |
324 } | 324 } |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 if (ScriptForbiddenScope::isScriptForbidden()) { | 562 if (ScriptForbiddenScope::isScriptForbidden()) { |
563 throwScriptForbiddenException(isolate); | 563 throwScriptForbiddenException(isolate); |
564 return v8::MaybeLocal<v8::Object>(); | 564 return v8::MaybeLocal<v8::Object>(); |
565 } | 565 } |
566 v8::MicrotasksScope microtasksScope(isolate, v8::MicrotasksScope::kRunMicrot
asks); | 566 v8::MicrotasksScope microtasksScope(isolate, v8::MicrotasksScope::kRunMicrot
asks); |
567 v8::MaybeLocal<v8::Object> result = function->NewInstance(isolate->GetCurren
tContext(), argc, argv); | 567 v8::MaybeLocal<v8::Object> result = function->NewInstance(isolate->GetCurren
tContext(), argc, argv); |
568 crashIfIsolateIsDead(isolate); | 568 crashIfIsolateIsDead(isolate); |
569 return result; | 569 return result; |
570 } | 570 } |
571 | 571 |
572 unsigned V8ScriptRunner::tagForParserCache(CachedMetadataHandler* cacheHandler) | 572 uint32_t V8ScriptRunner::tagForParserCache(CachedMetadataHandler* cacheHandler) |
573 { | 573 { |
574 return cacheTag(CacheTagParser, cacheHandler); | 574 return cacheTag(CacheTagParser, cacheHandler); |
575 } | 575 } |
576 | 576 |
577 unsigned V8ScriptRunner::tagForCodeCache(CachedMetadataHandler* cacheHandler) | 577 uint32_t V8ScriptRunner::tagForCodeCache(CachedMetadataHandler* cacheHandler) |
578 { | 578 { |
579 return cacheTag(CacheTagCode, cacheHandler); | 579 return cacheTag(CacheTagCode, cacheHandler); |
580 } | 580 } |
581 | 581 |
582 // Store a timestamp to the cache as hint. | 582 // Store a timestamp to the cache as hint. |
583 void V8ScriptRunner::setCacheTimeStamp(CachedMetadataHandler* cacheHandler) | 583 void V8ScriptRunner::setCacheTimeStamp(CachedMetadataHandler* cacheHandler) |
584 { | 584 { |
585 double now = WTF::currentTime(); | 585 double now = WTF::currentTime(); |
586 unsigned tag = cacheTag(CacheTagTimeStamp, cacheHandler); | 586 uint32_t tag = cacheTag(CacheTagTimeStamp, cacheHandler); |
587 cacheHandler->clearCachedMetadata(CachedMetadataHandler::CacheLocally); | 587 cacheHandler->clearCachedMetadata(CachedMetadataHandler::CacheLocally); |
588 cacheHandler->setCachedMetadata(tag, reinterpret_cast<char*>(&now), sizeof(n
ow), CachedMetadataHandler::SendToPlatform); | 588 cacheHandler->setCachedMetadata(tag, reinterpret_cast<char*>(&now), sizeof(n
ow), CachedMetadataHandler::SendToPlatform); |
589 } | 589 } |
590 | 590 |
591 void V8ScriptRunner::throwException(v8::Isolate* isolate, v8::Local<v8::Value> e
xception, const v8::ScriptOrigin& origin) | 591 void V8ScriptRunner::throwException(v8::Isolate* isolate, v8::Local<v8::Value> e
xception, const v8::ScriptOrigin& origin) |
592 { | 592 { |
593 // In order for the current TryCatch to catch this exception and | 593 // In order for the current TryCatch to catch this exception and |
594 // call MessageCallback when SetVerbose(true), create a v8::Function | 594 // call MessageCallback when SetVerbose(true), create a v8::Function |
595 // that calls isolate->throwException(). | 595 // that calls isolate->throwException(). |
596 // Unlike throwStackOverflowExceptionIfNeeded(), create a temporary Script | 596 // Unlike throwStackOverflowExceptionIfNeeded(), create a temporary Script |
597 // with the specified ScriptOrigin. When the exception was created but not | 597 // with the specified ScriptOrigin. When the exception was created but not |
598 // thrown yet, the ScriptOrigin of the thrower is set to the exception. | 598 // thrown yet, the ScriptOrigin of the thrower is set to the exception. |
599 // v8::Function::New() has empty ScriptOrigin, and thus the exception will | 599 // v8::Function::New() has empty ScriptOrigin, and thus the exception will |
600 // be "muted" (sanitized in our terminology) if CORS does not allow. | 600 // be "muted" (sanitized in our terminology) if CORS does not allow. |
601 // https://html.spec.whatwg.org/multipage/webappapis.html#report-the-error | 601 // https://html.spec.whatwg.org/multipage/webappapis.html#report-the-error |
602 // Avoid compile and run scripts when API is available: crbug.com/639739 | 602 // Avoid compile and run scripts when API is available: crbug.com/639739 |
603 v8::Local<v8::Script> script = compileWithoutOptions( | 603 v8::Local<v8::Script> script = compileWithoutOptions( |
604 V8CompileHistogram::Cacheability::Noncacheable, isolate, | 604 V8CompileHistogram::Cacheability::Noncacheable, isolate, |
605 v8AtomicString(isolate, "((e) => { throw e; })"), origin) | 605 v8AtomicString(isolate, "((e) => { throw e; })"), origin) |
606 .ToLocalChecked(); | 606 .ToLocalChecked(); |
607 v8::Local<v8::Function> thrower = runCompiledInternalScript(isolate, script) | 607 v8::Local<v8::Function> thrower = runCompiledInternalScript(isolate, script) |
608 .ToLocalChecked().As<v8::Function>(); | 608 .ToLocalChecked().As<v8::Function>(); |
609 v8::Local<v8::Value> args[] = { exception }; | 609 v8::Local<v8::Value> args[] = { exception }; |
610 callInternalFunction(thrower, thrower, WTF_ARRAY_LENGTH(args), args, isolate
); | 610 callInternalFunction(thrower, thrower, WTF_ARRAY_LENGTH(args), args, isolate
); |
611 } | 611 } |
612 | 612 |
613 } // namespace blink | 613 } // namespace blink |
OLD | NEW |