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 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 |