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 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 const v8::ScriptCompiler::CachedData* cachedData = source.GetCachedData(); | 149 const v8::ScriptCompiler::CachedData* cachedData = source.GetCachedData(); |
150 if (cachedData) { | 150 if (cachedData) { |
151 const char* data = reinterpret_cast<const char*>(cachedData->data); | 151 const char* data = reinterpret_cast<const char*>(cachedData->data); |
152 int length = cachedData->length; | 152 int length = cachedData->length; |
153 std::string compressedOutput; | 153 std::string compressedOutput; |
154 if (compressed) { | 154 if (compressed) { |
155 snappy::Compress(data, length, &compressedOutput); | 155 snappy::Compress(data, length, &compressedOutput); |
156 data = compressedOutput.data(); | 156 data = compressedOutput.data(); |
157 length = compressedOutput.length(); | 157 length = compressedOutput.length(); |
158 } | 158 } |
| 159 if (length > 1024) { |
| 160 // Omit histogram samples for small cache data to avoid outliers. |
| 161 int cacheSizeRatio = static_cast<int>(100.0 * length / code->Length(
)); |
| 162 blink::Platform::current()->histogramCustomCounts("V8.CodeCacheSizeR
atio", cacheSizeRatio, 0, 10000, 50); |
| 163 } |
159 resource->clearCachedMetadata(); | 164 resource->clearCachedMetadata(); |
160 resource->setCachedMetadata(tag, data, length, cacheType); | 165 resource->setCachedMetadata(tag, data, length, cacheType); |
161 } | 166 } |
162 return script; | 167 return script; |
163 } | 168 } |
164 | 169 |
165 // Compile a script, and consume or produce a V8 Cache, depending on whether the | 170 // Compile a script, and consume or produce a V8 Cache, depending on whether the |
166 // given resource already has cached data available. | 171 // given resource already has cached data available. |
167 v8::Local<v8::Script> compileAndConsumeOrProduce(ScriptResource* resource, unsig
ned tag, v8::ScriptCompiler::CompileOptions consumeOptions, v8::ScriptCompiler::
CompileOptions produceOptions, bool compressed, Resource::MetadataCacheType cach
eType, v8::Isolate* isolate, v8::Handle<v8::String> code, v8::ScriptOrigin origi
n) | 172 v8::Local<v8::Script> compileAndConsumeOrProduce(ScriptResource* resource, unsig
ned tag, v8::ScriptCompiler::CompileOptions consumeOptions, v8::ScriptCompiler::
CompileOptions produceOptions, bool compressed, Resource::MetadataCacheType cach
eType, v8::Isolate* isolate, v8::Handle<v8::String> code, v8::ScriptOrigin origi
n) |
168 { | 173 { |
(...skipping 28 matching lines...) Expand all Loading... |
197 | 202 |
198 // Store a timestamp to the cache as hint. | 203 // Store a timestamp to the cache as hint. |
199 void setCacheTimeStamp(ScriptResource* resource) | 204 void setCacheTimeStamp(ScriptResource* resource) |
200 { | 205 { |
201 double now = WTF::currentTime(); | 206 double now = WTF::currentTime(); |
202 unsigned tag = cacheTag(CacheTagTimeStamp, resource); | 207 unsigned tag = cacheTag(CacheTagTimeStamp, resource); |
203 resource->setCachedMetadata(tag, reinterpret_cast<char*>(&now), sizeof(now),
Resource::SendToPlatform); | 208 resource->setCachedMetadata(tag, reinterpret_cast<char*>(&now), sizeof(now),
Resource::SendToPlatform); |
204 } | 209 } |
205 | 210 |
206 // Check previously stored timestamp. | 211 // Check previously stored timestamp. |
207 bool isResourceHotForCaching(ScriptResource* resource) | 212 bool isResourceHotForCaching(ScriptResource* resource, int hotHours) |
208 { | 213 { |
209 const double kCacheWithinSeconds = 36 * 60 * 60; | 214 const double kCacheWithinSeconds = hotHours * 60 * 60; |
210 unsigned tag = cacheTag(CacheTagTimeStamp, resource); | 215 unsigned tag = cacheTag(CacheTagTimeStamp, resource); |
211 CachedMetadata* cachedMetadata = resource->cachedMetadata(tag); | 216 CachedMetadata* cachedMetadata = resource->cachedMetadata(tag); |
212 if (!cachedMetadata) | 217 if (!cachedMetadata) |
213 return false; | 218 return false; |
214 double timeStamp; | 219 double timeStamp; |
215 const int size = sizeof(timeStamp); | 220 const int size = sizeof(timeStamp); |
216 ASSERT(cachedMetadata->size() == size); | 221 ASSERT(cachedMetadata->size() == size); |
217 memcpy(&timeStamp, cachedMetadata->data(), size); | 222 memcpy(&timeStamp, cachedMetadata->data(), size); |
218 return (WTF::currentTime() - timeStamp) < kCacheWithinSeconds; | 223 return (WTF::currentTime() - timeStamp) < kCacheWithinSeconds; |
219 } | 224 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 PassOwnPtr<CompileFn> bind(const A&... args) | 263 PassOwnPtr<CompileFn> bind(const A&... args) |
259 { | 264 { |
260 return WTF::bind<v8::Isolate*, v8::Handle<v8::String>, v8::ScriptOrigin>(arg
s...); | 265 return WTF::bind<v8::Isolate*, v8::Handle<v8::String>, v8::ScriptOrigin>(arg
s...); |
261 } | 266 } |
262 | 267 |
263 // Select a compile function from any of the above, mainly depending on | 268 // Select a compile function from any of the above, mainly depending on |
264 // cacheOptions. | 269 // cacheOptions. |
265 PassOwnPtr<CompileFn> selectCompileFunction(V8CacheOptions cacheOptions, ScriptR
esource* resource, v8::Handle<v8::String> code) | 270 PassOwnPtr<CompileFn> selectCompileFunction(V8CacheOptions cacheOptions, ScriptR
esource* resource, v8::Handle<v8::String> code) |
266 { | 271 { |
267 static const int minimalCodeLength = 1024; | 272 static const int minimalCodeLength = 1024; |
268 static const int mediumCodeLength = 300000; | |
269 | 273 |
270 if (cacheOptions == V8CacheOptionsNone | 274 if (!resource || !resource->url().protocolIsInHTTPFamily()) |
271 || !resource | |
272 || !resource->url().protocolIsInHTTPFamily()) { | |
273 // Caching is not available in this case. | 275 // Caching is not available in this case. |
274 return bind(compileWithoutOptions, V8CompileHistogram::Noncacheable); | 276 return bind(compileWithoutOptions, V8CompileHistogram::Noncacheable); |
275 } | |
276 | 277 |
277 if (code->Length() < minimalCodeLength) { | 278 if (cacheOptions == V8CacheOptionsNone) |
278 // Do not cache for small scripts, though caching is available. | |
279 return bind(compileWithoutOptions, V8CompileHistogram::Cacheable); | 279 return bind(compileWithoutOptions, V8CompileHistogram::Cacheable); |
280 } | |
281 | 280 |
282 // The cacheOptions will guide our strategy: | 281 // The cacheOptions will guide our strategy: |
| 282 // FIXME: Clean up code caching options. crbug.com/455187. |
283 switch (cacheOptions) { | 283 switch (cacheOptions) { |
284 case V8CacheOptionsDefault: | 284 case V8CacheOptionsDefault: |
285 case V8CacheOptionsParseMemory: | 285 case V8CacheOptionsParseMemory: |
| 286 if (code->Length() < minimalCodeLength) { |
| 287 // Do not cache for small scripts, though caching is available. |
| 288 return bind(compileWithoutOptions, V8CompileHistogram::Cacheable); |
| 289 } |
286 // Use parser-cache; in-memory only. | 290 // Use parser-cache; in-memory only. |
287 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagParse
r, resource), v8::ScriptCompiler::kConsumeParserCache, v8::ScriptCompiler::kProd
uceParserCache, false, Resource::CacheLocally); | 291 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagParse
r, resource), v8::ScriptCompiler::kConsumeParserCache, v8::ScriptCompiler::kProd
uceParserCache, false, Resource::CacheLocally); |
288 break; | 292 break; |
289 | 293 |
290 case V8CacheOptionsParse: | 294 case V8CacheOptionsParse: |
291 // Use parser-cache. | 295 // Use parser-cache. |
292 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagParse
r, resource), v8::ScriptCompiler::kConsumeParserCache, v8::ScriptCompiler::kProd
uceParserCache, false, Resource::SendToPlatform); | 296 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagParse
r, resource), v8::ScriptCompiler::kConsumeParserCache, v8::ScriptCompiler::kProd
uceParserCache, false, Resource::SendToPlatform); |
293 break; | 297 break; |
294 | 298 |
| 299 case V8CacheOptionsHeuristicsDefault: |
295 case V8CacheOptionsCode: | 300 case V8CacheOptionsCode: |
296 // Always use code caching. | 301 // Always use code caching. |
297 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagCode,
resource), v8::ScriptCompiler::kConsumeCodeCache, v8::ScriptCompiler::kProduceC
odeCache, false, Resource::SendToPlatform); | 302 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagCode,
resource), v8::ScriptCompiler::kConsumeCodeCache, v8::ScriptCompiler::kProduceC
odeCache, false, Resource::SendToPlatform); |
298 break; | 303 break; |
299 | 304 |
| 305 case V8CacheOptionsHeuristicsDefaultMobile: |
300 case V8CacheOptionsCodeCompressed: | 306 case V8CacheOptionsCodeCompressed: |
301 // Always use code caching. Compress depending on cacheOptions. | 307 // Always use code caching. Compress depending on cacheOptions. |
302 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagCodeC
ompressed, resource), v8::ScriptCompiler::kConsumeCodeCache, v8::ScriptCompiler:
:kProduceCodeCache, true, Resource::SendToPlatform); | 308 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagCodeC
ompressed, resource), v8::ScriptCompiler::kConsumeCodeCache, v8::ScriptCompiler:
:kProduceCodeCache, true, Resource::SendToPlatform); |
303 break; | 309 break; |
304 | 310 |
305 case V8CacheOptionsHeuristics: | 311 case V8CacheOptionsHeuristics: |
306 case V8CacheOptionsHeuristicsMobile: | 312 case V8CacheOptionsHeuristicsMobile: |
307 case V8CacheOptionsHeuristicsDefault: | |
308 case V8CacheOptionsHeuristicsDefaultMobile: { | |
309 // We expect compression to win on mobile devices, due to relatively | |
310 // slow storage. | |
311 bool compress = (cacheOptions == V8CacheOptionsHeuristicsMobile || cache
Options == V8CacheOptionsHeuristicsDefaultMobile); | |
312 CacheTagKind codeTag = compress ? CacheTagCodeCompressed : CacheTagCode; | |
313 | |
314 // Either code or parser caching, depending on code size and what we | |
315 // already have in the cache. | |
316 unsigned codeCacheTag = cacheTag(codeTag, resource); | |
317 if (resource->cachedMetadata(codeCacheTag)) | |
318 return bind(compileAndConsumeCache, resource, codeCacheTag, v8::Scri
ptCompiler::kConsumeCodeCache, compress); | |
319 if (code->Length() < mediumCodeLength) | |
320 return bind(compileAndProduceCache, resource, codeCacheTag, v8::Scri
ptCompiler::kProduceCodeCache, compress, Resource::SendToPlatform); | |
321 Resource::MetadataCacheType cacheType = Resource::CacheLocally; | |
322 if (cacheOptions == V8CacheOptionsHeuristics || cacheOptions == V8CacheO
ptionsHeuristicsMobile) | |
323 cacheType = Resource::SendToPlatform; | |
324 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagParse
r, resource), v8::ScriptCompiler::kConsumeParserCache, v8::ScriptCompiler::kProd
uceParserCache, false, cacheType); | |
325 break; | |
326 } | |
327 | |
328 case V8CacheOptionsRecent: | 313 case V8CacheOptionsRecent: |
329 case V8CacheOptionsRecentSmall: { | 314 case V8CacheOptionsRecentSmall: { |
330 if (cacheOptions == V8CacheOptionsRecentSmall && code->Length() >= mediu
mCodeLength) | 315 bool compress = (cacheOptions == V8CacheOptionsRecentSmall || cacheOptio
ns == V8CacheOptionsHeuristicsMobile); |
331 return bind(compileAndConsumeOrProduce, resource, cacheTag(CacheTagP
arser, resource), v8::ScriptCompiler::kConsumeParserCache, v8::ScriptCompiler::k
ProduceParserCache, false, Resource::CacheLocally); | 316 unsigned codeCacheTag = cacheTag(compress ? CacheTagCodeCompressed : Cac
heTagCode, resource); |
332 unsigned codeCacheTag = cacheTag(CacheTagCode, resource); | |
333 CachedMetadata* codeCache = resource->cachedMetadata(codeCacheTag); | 317 CachedMetadata* codeCache = resource->cachedMetadata(codeCacheTag); |
334 if (codeCache) | 318 if (codeCache) |
335 return bind(compileAndConsumeCache, resource, codeCacheTag, v8::Scri
ptCompiler::kConsumeCodeCache, false); | 319 return bind(compileAndConsumeCache, resource, codeCacheTag, v8::Scri
ptCompiler::kConsumeCodeCache, compress); |
336 if (!isResourceHotForCaching(resource)) { | 320 int hotHours = (cacheOptions == V8CacheOptionsRecent || cacheOptions ==
V8CacheOptionsRecentSmall) ? 36 : 72; |
| 321 if (!isResourceHotForCaching(resource, hotHours)) { |
337 setCacheTimeStamp(resource); | 322 setCacheTimeStamp(resource); |
338 return bind(compileWithoutOptions, V8CompileHistogram::Cacheable); | 323 return bind(compileWithoutOptions, V8CompileHistogram::Cacheable); |
339 } | 324 } |
340 return bind(compileAndProduceCache, resource, codeCacheTag, v8::ScriptCo
mpiler::kProduceCodeCache, false, Resource::SendToPlatform); | 325 return bind(compileAndProduceCache, resource, codeCacheTag, v8::ScriptCo
mpiler::kProduceCodeCache, compress, Resource::SendToPlatform); |
341 break; | 326 break; |
342 } | 327 } |
343 | 328 |
344 case V8CacheOptionsNone: | 329 case V8CacheOptionsNone: |
345 // Shouldn't happen, as this is handled above. | 330 // Shouldn't happen, as this is handled above. |
346 // Case is here so that compiler can check all cases are handles. | 331 // Case is here so that compiler can check all cases are handled. |
347 ASSERT_NOT_REACHED(); | 332 ASSERT_NOT_REACHED(); |
348 return bind(compileWithoutOptions, V8CompileHistogram::Cacheable); | |
349 break; | 333 break; |
350 } | 334 } |
351 | 335 |
352 // All switch branches should return and we should never get here. | 336 // All switch branches should return and we should never get here. |
353 // But some compilers aren't sure, hence this default. | 337 // But some compilers aren't sure, hence this default. |
354 ASSERT_NOT_REACHED(); | 338 ASSERT_NOT_REACHED(); |
355 return bind(compileWithoutOptions, V8CompileHistogram::Cacheable); | 339 return bind(compileWithoutOptions, V8CompileHistogram::Cacheable); |
356 } | 340 } |
357 | 341 |
358 // Select a compile function for a streaming compile. | 342 // Select a compile function for a streaming compile. |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 { | 504 { |
521 return cacheTag(CacheTagParser, resource); | 505 return cacheTag(CacheTagParser, resource); |
522 } | 506 } |
523 | 507 |
524 unsigned V8ScriptRunner::tagForCodeCache(Resource* resource) | 508 unsigned V8ScriptRunner::tagForCodeCache(Resource* resource) |
525 { | 509 { |
526 return cacheTag(CacheTagCode, resource); | 510 return cacheTag(CacheTagCode, resource); |
527 } | 511 } |
528 | 512 |
529 } // namespace blink | 513 } // namespace blink |
OLD | NEW |