| Index: Source/bindings/core/v8/V8ScriptRunner.cpp
|
| diff --git a/Source/bindings/core/v8/V8ScriptRunner.cpp b/Source/bindings/core/v8/V8ScriptRunner.cpp
|
| index 84740afacae4afee9cfb014bb226455fc5850ae7..136fc57143d5a727c58631e72987f9c48d8b5889 100644
|
| --- a/Source/bindings/core/v8/V8ScriptRunner.cpp
|
| +++ b/Source/bindings/core/v8/V8ScriptRunner.cpp
|
| @@ -37,6 +37,7 @@
|
| #include "core/fetch/ScriptResource.h"
|
| #include "platform/ScriptForbiddenScope.h"
|
| #include "platform/TraceEvent.h"
|
| +#include "public/platform/Platform.h"
|
| #include "third_party/snappy/src/snappy.h"
|
| #include "wtf/CurrentTime.h"
|
|
|
| @@ -52,6 +53,30 @@ namespace {
|
|
|
| const int kMaxRecursionDepth = 22;
|
|
|
| +class V8CompileHistogram {
|
| +public:
|
| + enum Cacheability { Cacheable, Noncacheable };
|
| + explicit V8CompileHistogram(Cacheability);
|
| + ~V8CompileHistogram();
|
| +
|
| +private:
|
| + Cacheability m_cacheability;
|
| + double m_timeStamp;
|
| +};
|
| +
|
| +V8CompileHistogram::V8CompileHistogram(V8CompileHistogram::Cacheability cacheability)
|
| + : m_cacheability(cacheability)
|
| + , m_timeStamp(WTF::currentTime())
|
| +{
|
| +}
|
| +
|
| +V8CompileHistogram::~V8CompileHistogram()
|
| +{
|
| + int64_t elapsedMicroSeconds = static_cast<int64_t>((WTF::currentTime() - m_timeStamp) * 1000000);
|
| + const char* name = (m_cacheability == Cacheable) ? "V8.CompileCacheableMicroSeconds" : "V8.CompileNoncacheableMicroSeconds";
|
| + blink::Platform::current()->histogramCustomCounts(name, elapsedMicroSeconds, 0, 1000000, 50);
|
| +}
|
| +
|
| // In order to make sure all pending messages to be processed in
|
| // v8::Function::Call, we don't call handleMaxRecursionDepthExceeded
|
| // directly. Instead, we create a v8::Function of
|
| @@ -75,8 +100,9 @@ v8::Local<v8::Value> throwStackOverflowExceptionIfNeeded(v8::Isolate* isolate)
|
| }
|
|
|
| // Compile a script without any caching or compile options.
|
| -v8::Local<v8::Script> compileWithoutOptions(v8::Isolate* isolate, v8::Handle<v8::String> code, v8::ScriptOrigin origin)
|
| +v8::Local<v8::Script> compileWithoutOptions(V8CompileHistogram::Cacheability cacheability, v8::Isolate* isolate, v8::Handle<v8::String> code, v8::ScriptOrigin origin)
|
| {
|
| + V8CompileHistogram histogramScope(cacheability);
|
| v8::ScriptCompiler::Source source(code, origin);
|
| return v8::ScriptCompiler::Compile(isolate, &source, v8::ScriptCompiler::kNoCompileOptions);
|
| }
|
| @@ -84,6 +110,7 @@ v8::Local<v8::Script> compileWithoutOptions(v8::Isolate* isolate, v8::Handle<v8:
|
| // Compile a script, and consume a V8 cache that was generated previously.
|
| v8::Local<v8::Script> compileAndConsumeCache(ScriptResource* resource, unsigned tag, v8::ScriptCompiler::CompileOptions compileOptions, bool compressed, v8::Isolate* isolate, v8::Handle<v8::String> code, v8::ScriptOrigin origin)
|
| {
|
| + V8CompileHistogram histogramScope(V8CompileHistogram::Cacheable);
|
| CachedMetadata* cachedMetadata = resource->cachedMetadata(tag);
|
| const char* data = cachedMetadata->data();
|
| int length = cachedMetadata->size();
|
| @@ -99,7 +126,8 @@ v8::Local<v8::Script> compileAndConsumeCache(ScriptResource* resource, unsigned
|
| }
|
| v8::Local<v8::Script> script;
|
| if (invalidCache) {
|
| - script = compileWithoutOptions(isolate, code, origin);
|
| + v8::ScriptCompiler::Source source(code, origin);
|
| + script = v8::ScriptCompiler::Compile(isolate, &source, v8::ScriptCompiler::kNoCompileOptions);
|
| } else {
|
| v8::ScriptCompiler::CachedData* cachedData = new v8::ScriptCompiler::CachedData(
|
| reinterpret_cast<const uint8_t*>(data), length, v8::ScriptCompiler::CachedData::BufferNotOwned);
|
| @@ -115,6 +143,7 @@ v8::Local<v8::Script> compileAndConsumeCache(ScriptResource* resource, unsigned
|
| // Compile a script, and produce a V8 cache for future use.
|
| v8::Local<v8::Script> compileAndProduceCache(ScriptResource* resource, unsigned tag, v8::ScriptCompiler::CompileOptions compileOptions, bool compressed, Resource::MetadataCacheType cacheType, v8::Isolate* isolate, v8::Handle<v8::String> code, v8::ScriptOrigin origin)
|
| {
|
| + V8CompileHistogram histogramScope(V8CompileHistogram::Cacheable);
|
| v8::ScriptCompiler::Source source(code, origin);
|
| v8::Local<v8::Script> script = v8::ScriptCompiler::Compile(isolate, &source, compileOptions);
|
| const v8::ScriptCompiler::CachedData* cachedData = source.GetCachedData();
|
| @@ -169,7 +198,7 @@ unsigned cacheTag(CacheTagKind kind, Resource* resource)
|
| // Store a timestamp to the cache as hint.
|
| void setCacheTimeStamp(ScriptResource* resource)
|
| {
|
| - double now = currentTime();
|
| + double now = WTF::currentTime();
|
| unsigned tag = cacheTag(CacheTagTimeStamp, resource);
|
| resource->setCachedMetadata(tag, reinterpret_cast<char*>(&now), sizeof(now), Resource::SendToPlatform);
|
| }
|
| @@ -186,13 +215,14 @@ bool isResourceHotForCaching(ScriptResource* resource)
|
| const int size = sizeof(timeStamp);
|
| ASSERT(cachedMetadata->size() == size);
|
| memcpy(&timeStamp, cachedMetadata->data(), size);
|
| - return (currentTime() - timeStamp) < kCacheWithinSeconds;
|
| + return (WTF::currentTime() - timeStamp) < kCacheWithinSeconds;
|
| }
|
|
|
| // Final compile call for a streamed compilation. Most decisions have already
|
| // been made, but we need to write back data into the cache.
|
| v8::Local<v8::Script> postStreamCompile(ScriptResource* resource, ScriptStreamer* streamer, v8::Isolate* isolate, v8::Handle<v8::String> code, v8::ScriptOrigin origin)
|
| {
|
| + V8CompileHistogram histogramScope(V8CompileHistogram::Noncacheable);
|
| v8::Local<v8::Script> script = v8::ScriptCompiler::Compile(isolate, streamer->source(), code, origin);
|
|
|
| // Whether to produce the cached data or not is decided when the
|
| @@ -239,10 +269,14 @@ PassOwnPtr<CompileFn> selectCompileFunction(V8CacheOptions cacheOptions, ScriptR
|
|
|
| if (cacheOptions == V8CacheOptionsNone
|
| || !resource
|
| - || !resource->url().protocolIsInHTTPFamily()
|
| - || code->Length() < minimalCodeLength) {
|
| - // Never generate or use the cache in these circumstances.
|
| - return bind(compileWithoutOptions);
|
| + || !resource->url().protocolIsInHTTPFamily()) {
|
| + // Caching is not available in this case.
|
| + return bind(compileWithoutOptions, V8CompileHistogram::Noncacheable);
|
| + }
|
| +
|
| + if (code->Length() < minimalCodeLength) {
|
| + // Do not cache for small scripts, though caching is available.
|
| + return bind(compileWithoutOptions, V8CompileHistogram::Cacheable);
|
| }
|
|
|
| // The cacheOptions will guide our strategy:
|
| @@ -301,7 +335,7 @@ PassOwnPtr<CompileFn> selectCompileFunction(V8CacheOptions cacheOptions, ScriptR
|
| return bind(compileAndConsumeCache, resource, codeCacheTag, v8::ScriptCompiler::kConsumeCodeCache, false);
|
| if (!isResourceHotForCaching(resource)) {
|
| setCacheTimeStamp(resource);
|
| - return bind(compileWithoutOptions);
|
| + return bind(compileWithoutOptions, V8CompileHistogram::Cacheable);
|
| }
|
| return bind(compileAndProduceCache, resource, codeCacheTag, v8::ScriptCompiler::kProduceCodeCache, false, Resource::SendToPlatform);
|
| break;
|
| @@ -311,14 +345,14 @@ PassOwnPtr<CompileFn> selectCompileFunction(V8CacheOptions cacheOptions, ScriptR
|
| // Shouldn't happen, as this is handled above.
|
| // Case is here so that compiler can check all cases are handles.
|
| ASSERT_NOT_REACHED();
|
| - return bind(compileWithoutOptions);
|
| + return bind(compileWithoutOptions, V8CompileHistogram::Cacheable);
|
| break;
|
| }
|
|
|
| // All switch branches should return and we should never get here.
|
| // But some compilers aren't sure, hence this default.
|
| ASSERT_NOT_REACHED();
|
| - return bind(compileWithoutOptions);
|
| + return bind(compileWithoutOptions, V8CompileHistogram::Cacheable);
|
| }
|
|
|
| // Select a compile function for a streaming compile.
|
|
|