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 20 matching lines...) Expand all Loading... | |
31 #include "bindings/core/v8/V8Binding.h" | 31 #include "bindings/core/v8/V8Binding.h" |
32 #include "bindings/core/v8/V8GCController.h" | 32 #include "bindings/core/v8/V8GCController.h" |
33 #include "bindings/core/v8/V8RecursionScope.h" | 33 #include "bindings/core/v8/V8RecursionScope.h" |
34 #include "bindings/core/v8/V8ThrowException.h" | 34 #include "bindings/core/v8/V8ThrowException.h" |
35 #include "core/dom/ExecutionContext.h" | 35 #include "core/dom/ExecutionContext.h" |
36 #include "core/fetch/CachedMetadata.h" | 36 #include "core/fetch/CachedMetadata.h" |
37 #include "core/fetch/ScriptResource.h" | 37 #include "core/fetch/ScriptResource.h" |
38 #include "platform/ScriptForbiddenScope.h" | 38 #include "platform/ScriptForbiddenScope.h" |
39 #include "platform/TraceEvent.h" | 39 #include "platform/TraceEvent.h" |
40 #include "third_party/snappy/src/snappy.h" | 40 #include "third_party/snappy/src/snappy.h" |
41 #include "wtf/CurrentTime.h" | |
41 | 42 |
42 #if defined(WTF_OS_WIN) | 43 #if defined(WTF_OS_WIN) |
43 #include <malloc.h> | 44 #include <malloc.h> |
44 #else | 45 #else |
45 #include <alloca.h> | 46 #include <alloca.h> |
46 #endif | 47 #endif |
47 | 48 |
48 namespace blink { | 49 namespace blink { |
49 | 50 |
50 namespace { | 51 namespace { |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
149 { | 150 { |
150 return resource->cachedMetadata(tag) | 151 return resource->cachedMetadata(tag) |
151 ? compileAndConsumeCache(resource, tag, consumeOptions, compressed, isol ate, code, origin) | 152 ? compileAndConsumeCache(resource, tag, consumeOptions, compressed, isol ate, code, origin) |
152 : compileAndProduceCache(resource, tag, produceOptions, compressed, cach eType, isolate, code, origin); | 153 : compileAndProduceCache(resource, tag, produceOptions, compressed, cach eType, isolate, code, origin); |
153 } | 154 } |
154 | 155 |
155 enum CacheTagKind { | 156 enum CacheTagKind { |
156 CacheTagParser = 0, | 157 CacheTagParser = 0, |
157 CacheTagCode = 1, | 158 CacheTagCode = 1, |
158 CacheTagCodeCompressed = 2, | 159 CacheTagCodeCompressed = 2, |
159 | 160 CacheTagTimeStamp = 3, |
160 CacheTagLast | 161 CacheTagLast |
161 }; | 162 }; |
162 | 163 |
163 static const int kCacheTagKindSize = 2; | 164 static const int kCacheTagKindSize = 2; |
164 | 165 |
165 unsigned cacheTag(CacheTagKind kind, Resource* resource) | 166 unsigned cacheTag(CacheTagKind kind, Resource* resource) |
166 { | 167 { |
167 static_assert((1 << kCacheTagKindSize) >= CacheTagLast, "CacheTagLast must b e large enough"); | 168 static_assert((1 << kCacheTagKindSize) >= CacheTagLast, "CacheTagLast must b e large enough"); |
168 | 169 |
169 static unsigned v8CacheDataVersion = v8::ScriptCompiler::CachedDataVersionTa g() << kCacheTagKindSize; | 170 static unsigned v8CacheDataVersion = v8::ScriptCompiler::CachedDataVersionTa g() << kCacheTagKindSize; |
170 | 171 |
171 // A script can be (successfully) interpreted with different encodings, | 172 // A script can be (successfully) interpreted with different encodings, |
172 // depending on the page it appears in. The cache doesn't know anything | 173 // depending on the page it appears in. The cache doesn't know anything |
173 // about encodings, but the cached data is specific to one encoding. If we | 174 // about encodings, but the cached data is specific to one encoding. If we |
174 // later load the script from the cache and interpret it with a different | 175 // later load the script from the cache and interpret it with a different |
175 // encoding, the cached data is not valid for that encoding. | 176 // encoding, the cached data is not valid for that encoding. |
176 return (v8CacheDataVersion | kind) + StringHash::hash(resource->encoding()); | 177 return (v8CacheDataVersion | kind) + StringHash::hash(resource->encoding()); |
177 } | 178 } |
178 | 179 |
180 // Store a timestamp to the cache as hint. | |
181 void setCacheTimeStamp(ScriptResource* resource) | |
182 { | |
183 double now = currentTime(); | |
184 unsigned tag = cacheTag(CacheTagTimeStamp, resource); | |
185 resource->setCachedMetadata(tag, reinterpret_cast<char*>(&now), sizeof(now), Resource::SendToPlatform); | |
186 } | |
187 | |
188 // Check previously stored timestamp. | |
189 bool isResourceHotForCaching(ScriptResource* resource) | |
190 { | |
191 const double kCacheWithinSeconds = 36 * 60 * 60; | |
192 unsigned tag = cacheTag(CacheTagTimeStamp, resource); | |
193 CachedMetadata* cachedMetadata = resource->cachedMetadata(tag); | |
194 if (!cachedMetadata) | |
195 return false; | |
196 double timeStamp; | |
197 const int size = sizeof(timeStamp); | |
198 ASSERT(cachedMetadata->size() == size); | |
199 memcpy(&timeStamp, cachedMetadata->data(), size); | |
200 return (currentTime() - timeStamp) < kCacheWithinSeconds; | |
201 } | |
202 | |
179 // Final compile call for a streamed compilation. Most decisions have already | 203 // Final compile call for a streamed compilation. Most decisions have already |
180 // been made, but we need to write back data into the cache. | 204 // been made, but we need to write back data into the cache. |
181 v8::Local<v8::Script> postStreamCompile(ScriptResource* resource, ScriptStreamer * streamer, v8::Isolate* isolate, v8::Handle<v8::String> code, v8::ScriptOrigin origin) | 205 v8::Local<v8::Script> postStreamCompile(ScriptResource* resource, ScriptStreamer * streamer, v8::Isolate* isolate, v8::Handle<v8::String> code, v8::ScriptOrigin origin) |
182 { | 206 { |
183 v8::Local<v8::Script> script = v8::ScriptCompiler::Compile(isolate, streamer ->source(), code, origin); | 207 v8::Local<v8::Script> script = v8::ScriptCompiler::Compile(isolate, streamer ->source(), code, origin); |
184 | 208 |
185 // Whether to produce the cached data or not is decided when the | 209 // Whether to produce the cached data or not is decided when the |
186 // streamer is started. Here we only need to get the data out. | 210 // streamer is started. Here we only need to get the data out. |
187 const v8::ScriptCompiler::CachedData* newCachedData = streamer->source()->Ge tCachedData(); | 211 const v8::ScriptCompiler::CachedData* newCachedData = streamer->source()->Ge tCachedData(); |
188 if (newCachedData) { | 212 if (newCachedData) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
249 // Always use code caching. | 273 // Always use code caching. |
250 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagCode, resource), v8::ScriptCompiler::kConsumeCodeCache, v8::ScriptCompiler::kProduceC odeCache, false, Resource::SendToPlatform); | 274 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagCode, resource), v8::ScriptCompiler::kConsumeCodeCache, v8::ScriptCompiler::kProduceC odeCache, false, Resource::SendToPlatform); |
251 break; | 275 break; |
252 | 276 |
253 case V8CacheOptionsCodeCompressed: | 277 case V8CacheOptionsCodeCompressed: |
254 // Always use code caching. Compress depending on cacheOptions. | 278 // Always use code caching. Compress depending on cacheOptions. |
255 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagCodeC ompressed, resource), v8::ScriptCompiler::kConsumeCodeCache, v8::ScriptCompiler: :kProduceCodeCache, true, Resource::SendToPlatform); | 279 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagCodeC ompressed, resource), v8::ScriptCompiler::kConsumeCodeCache, v8::ScriptCompiler: :kProduceCodeCache, true, Resource::SendToPlatform); |
256 break; | 280 break; |
257 | 281 |
258 case V8CacheOptionsHeuristics: | 282 case V8CacheOptionsHeuristics: |
259 case V8CacheOptionsHeuristicsMobile: { | 283 case V8CacheOptionsHeuristicsMobile: |
284 case V8CacheOptionsHeuristicsDefault: | |
285 case V8CacheOptionsHeuristicsDefaultMobile: { | |
260 // We expect compression to win on mobile devices, due to relatively | 286 // We expect compression to win on mobile devices, due to relatively |
261 // slow storage. | 287 // slow storage. |
262 bool compress = cacheOptions == V8CacheOptionsHeuristicsMobile; | 288 bool compress = cacheOptions == V8CacheOptionsHeuristicsMobile; |
263 CacheTagKind codeTag = compress ? CacheTagCodeCompressed : CacheTagCode; | 289 CacheTagKind codeTag = compress ? CacheTagCodeCompressed : CacheTagCode; |
264 | 290 |
265 // Either code or parser caching, depending on code size and what we | 291 // Either code or parser caching, depending on code size and what we |
266 // already have in the cache. | 292 // already have in the cache. |
267 unsigned codeCacheTag = cacheTag(codeTag, resource); | 293 unsigned codeCacheTag = cacheTag(codeTag, resource); |
268 if (resource->cachedMetadata(codeCacheTag)) | 294 if (resource->cachedMetadata(codeCacheTag)) |
269 return bind(compileAndConsumeCache, resource, codeCacheTag, v8::Scri ptCompiler::kConsumeCodeCache, compress); | 295 return bind(compileAndConsumeCache, resource, codeCacheTag, v8::Scri ptCompiler::kConsumeCodeCache, compress); |
270 if (code->Length() < mediumCodeLength) | 296 if (code->Length() < mediumCodeLength) |
271 return bind(compileAndProduceCache, resource, codeCacheTag, v8::Scri ptCompiler::kProduceCodeCache, compress, Resource::SendToPlatform); | 297 return bind(compileAndProduceCache, resource, codeCacheTag, v8::Scri ptCompiler::kProduceCodeCache, compress, Resource::SendToPlatform); |
272 unsigned parserCacheTag = cacheTag(CacheTagParser, resource); | 298 Resource::MetadataCacheType cacheType = Resource::CacheLocally; |
273 if (resource->cachedMetadata(parserCacheTag)) | 299 if (cacheOptions == V8CacheOptionsHeuristics || cacheOptions == V8CacheO ptionsHeuristicsMobile) |
274 return bind(compileAndConsumeCache, resource, parserCacheTag, v8::Sc riptCompiler::kConsumeParserCache, false); | 300 cacheType = Resource::SendToPlatform; |
275 return bind(compileAndProduceCache, resource, parserCacheTag, v8::Script Compiler::kProduceParserCache, false, Resource::SendToPlatform); | 301 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagParse r, resource), v8::ScriptCompiler::kConsumeParserCache, v8::ScriptCompiler::kProd uceParserCache, false, cacheType); |
276 break; | 302 break; |
277 } | 303 } |
278 | 304 |
305 case V8CacheOptionsRecent: | |
306 case V8CacheOptionsRecentSmall: { | |
307 if (cacheOptions == V8CacheOptionsRecentSmall && code->Length() >= mediu mCodeLength) | |
308 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagP arser, resource), v8::ScriptCompiler::kConsumeParserCache, v8::ScriptCompiler::k ProduceParserCache, false, Resource::CacheLocally); | |
309 unsigned codeCacheTag = cacheTag(CacheTagCode, resource); | |
310 CachedMetadata* codeCache = resource->cachedMetadata(codeCacheTag); | |
311 if (codeCache) | |
312 return bind(compileAndConsumeCache, resource, codeCacheTag, v8::Scri ptCompiler::kConsumeCodeCache, false); | |
313 if (!isResourceHotForCaching(resource)) { | |
marja
2015/01/20 13:14:32
So this caches the code if we have recently compil
| |
314 setCacheTimeStamp(resource); | |
315 return bind(compileWithoutOptions); | |
316 } | |
317 return bind(compileAndProduceCache, resource, codeCacheTag, v8::ScriptCo mpiler::kProduceCodeCache, false, Resource::SendToPlatform); | |
318 break; | |
319 } | |
320 | |
279 case V8CacheOptionsNone: | 321 case V8CacheOptionsNone: |
280 // Shouldn't happen, as this is handled above. | 322 // Shouldn't happen, as this is handled above. |
281 // Case is here so that compiler can check all cases are handles. | 323 // Case is here so that compiler can check all cases are handles. |
282 ASSERT_NOT_REACHED(); | 324 ASSERT_NOT_REACHED(); |
283 return bind(compileWithoutOptions); | 325 return bind(compileWithoutOptions); |
284 break; | 326 break; |
285 } | 327 } |
286 | 328 |
287 // All switch branches should return and we should never get here. | 329 // All switch branches should return and we should never get here. |
288 // But some compilers aren't sure, hence this default. | 330 // But some compilers aren't sure, hence this default. |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
457 { | 499 { |
458 return cacheTag(CacheTagParser, resource); | 500 return cacheTag(CacheTagParser, resource); |
459 } | 501 } |
460 | 502 |
461 unsigned V8ScriptRunner::tagForCodeCache(Resource* resource) | 503 unsigned V8ScriptRunner::tagForCodeCache(Resource* resource) |
462 { | 504 { |
463 return cacheTag(CacheTagCode, resource); | 505 return cacheTag(CacheTagCode, resource); |
464 } | 506 } |
465 | 507 |
466 } // namespace blink | 508 } // namespace blink |
OLD | NEW |