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 | 40 |
| 41 #include <snappy.h> |
| 42 |
41 namespace blink { | 43 namespace blink { |
42 | 44 |
43 namespace { | 45 namespace { |
44 | 46 |
45 // In order to make sure all pending messages to be processed in | 47 // In order to make sure all pending messages to be processed in |
46 // v8::Function::Call, we don't call handleMaxRecursionDepthExceeded | 48 // v8::Function::Call, we don't call handleMaxRecursionDepthExceeded |
47 // directly. Instead, we create a v8::Function of | 49 // directly. Instead, we create a v8::Function of |
48 // throwStackOverflowException and call it. | 50 // throwStackOverflowException and call it. |
49 void throwStackOverflowException(const v8::FunctionCallbackInfo<v8::Value>& info
) | 51 void throwStackOverflowException(const v8::FunctionCallbackInfo<v8::Value>& info
) |
50 { | 52 { |
51 V8ThrowException::throwRangeError(info.GetIsolate(), "Maximum call stack siz
e exceeded."); | 53 V8ThrowException::throwRangeError(info.GetIsolate(), "Maximum call stack siz
e exceeded."); |
52 } | 54 } |
53 | 55 |
54 v8::Local<v8::Value> throwStackOverflowExceptionIfNeeded(v8::Isolate* isolate) | 56 v8::Local<v8::Value> throwStackOverflowExceptionIfNeeded(v8::Isolate* isolate) |
55 { | 57 { |
56 if (V8PerIsolateData::from(isolate)->isHandlingRecursionLevelError()) { | 58 if (V8PerIsolateData::from(isolate)->isHandlingRecursionLevelError()) { |
57 // If we are already handling a recursion level error, we should | 59 // If we are already handling a recursion level error, we should |
58 // not invoke v8::Function::Call. | 60 // not invoke v8::Function::Call. |
59 return v8::Undefined(isolate); | 61 return v8::Undefined(isolate); |
60 } | 62 } |
61 V8PerIsolateData::from(isolate)->setIsHandlingRecursionLevelError(true); | 63 V8PerIsolateData::from(isolate)->setIsHandlingRecursionLevelError(true); |
62 v8::Local<v8::Value> result = v8::Function::New(isolate, throwStackOverflowE
xception)->Call(v8::Undefined(isolate), 0, 0); | 64 v8::Local<v8::Value> result = v8::Function::New(isolate, throwStackOverflowE
xception)->Call(v8::Undefined(isolate), 0, 0); |
63 V8PerIsolateData::from(isolate)->setIsHandlingRecursionLevelError(false); | 65 V8PerIsolateData::from(isolate)->setIsHandlingRecursionLevelError(false); |
64 return result; | 66 return result; |
65 } | 67 } |
66 | 68 |
67 v8::Local<v8::Script> compileAndProduceCache(v8::Isolate* isolate, v8::Handle<v8
::String> code, v8::ScriptOrigin origin, ScriptResource* resource, v8::ScriptCom
piler::CompileOptions options, unsigned cacheTag, Resource::MetadataCacheType ca
cheType) | 69 v8::Local<v8::Script> compileAndProduceCache(v8::Isolate* isolate, v8::Handle<v8
::String> code, v8::ScriptOrigin origin, ScriptResource* resource, v8::ScriptCom
piler::CompileOptions options, unsigned cacheTag, Resource::MetadataCacheType ca
cheType, bool compressed) |
68 { | 70 { |
69 v8::ScriptCompiler::Source source(code, origin); | 71 v8::ScriptCompiler::Source source(code, origin); |
70 v8::Local<v8::Script> script = v8::ScriptCompiler::Compile(isolate, &source,
options); | 72 v8::Local<v8::Script> script = v8::ScriptCompiler::Compile(isolate, &source,
options); |
71 const v8::ScriptCompiler::CachedData* cachedData = source.GetCachedData(); | 73 const v8::ScriptCompiler::CachedData* cachedData = source.GetCachedData(); |
72 if (resource && cachedData) { | 74 if (resource && cachedData) { |
| 75 const char* data = reinterpret_cast<const char*>(cachedData->data); |
| 76 int length = cachedData->length; |
| 77 std::string compressedOutput; |
| 78 if (compressed) { |
| 79 snappy::Compress(data, length, &compressedOutput); |
| 80 data = compressedOutput.data(); |
| 81 length = compressedOutput.length(); |
| 82 } |
73 resource->clearCachedMetadata(); | 83 resource->clearCachedMetadata(); |
74 resource->setCachedMetadata( | 84 resource->setCachedMetadata( |
75 cacheTag, | 85 cacheTag, |
76 reinterpret_cast<const char*>(cachedData->data), | 86 data, |
77 cachedData->length, | 87 length, |
78 cacheType); | 88 cacheType); |
79 } | 89 } |
80 return script; | 90 return script; |
81 } | 91 } |
82 | 92 |
83 v8::Local<v8::Script> compileAndConsumeCache(v8::Isolate* isolate, v8::Handle<v8
::String> code, v8::ScriptOrigin origin, ScriptResource* resource, v8::ScriptCom
piler::CompileOptions options, unsigned cacheTag) | 93 v8::Local<v8::Script> compileAndConsumeCache(v8::Isolate* isolate, v8::Handle<v8
::String> code, v8::ScriptOrigin origin, ScriptResource* resource, v8::ScriptCom
piler::CompileOptions options, unsigned cacheTag, bool compressed) |
84 { | 94 { |
85 // Consume existing cache data: | 95 // Consume existing cache data: |
86 CachedMetadata* cachedMetadata = resource->cachedMetadata(cacheTag); | 96 CachedMetadata* cachedMetadata = resource->cachedMetadata(cacheTag); |
| 97 const char* data = cachedMetadata->data(); |
| 98 int length = cachedMetadata->size(); |
| 99 std::string uncompressedOutput; |
| 100 if (compressed) { |
| 101 snappy::Uncompress(data, length, &uncompressedOutput); |
| 102 data = uncompressedOutput.data(); |
| 103 length = uncompressedOutput.length(); |
| 104 } |
87 v8::ScriptCompiler::CachedData* cachedData = new v8::ScriptCompiler::CachedD
ata( | 105 v8::ScriptCompiler::CachedData* cachedData = new v8::ScriptCompiler::CachedD
ata( |
88 reinterpret_cast<const uint8_t*>(cachedMetadata->data()), | 106 reinterpret_cast<const uint8_t*>(data), |
89 cachedMetadata->size(), | 107 length, |
90 v8::ScriptCompiler::CachedData::BufferNotOwned); | 108 v8::ScriptCompiler::CachedData::BufferNotOwned); |
91 v8::ScriptCompiler::Source source(code, origin, cachedData); | 109 v8::ScriptCompiler::Source source(code, origin, cachedData); |
92 return v8::ScriptCompiler::Compile(isolate, &source, options); | 110 return v8::ScriptCompiler::Compile(isolate, &source, options); |
93 } | 111 } |
94 | 112 |
95 } // namespace | 113 } // namespace |
96 | 114 |
97 v8::Local<v8::Script> V8ScriptRunner::compileScript(const ScriptSourceCode& sour
ce, v8::Isolate* isolate, AccessControlStatus corsStatus, V8CacheOptions cacheOp
tions) | 115 v8::Local<v8::Script> V8ScriptRunner::compileScript(const ScriptSourceCode& sour
ce, v8::Isolate* isolate, AccessControlStatus corsStatus, V8CacheOptions cacheOp
tions) |
98 { | 116 { |
99 return compileScript(v8String(isolate, source.source()), source.url(), sourc
e.startPosition(), source.resource(), source.streamer(), isolate, corsStatus, ca
cheOptions); | 117 return compileScript(v8String(isolate, source.source()), source.url(), sourc
e.startPosition(), source.resource(), source.streamer(), isolate, corsStatus, ca
cheOptions); |
(...skipping 26 matching lines...) Expand all Loading... |
126 // streamer is started. Here we only need to get the data out. | 144 // streamer is started. Here we only need to get the data out. |
127 const v8::ScriptCompiler::CachedData* newCachedData = streamer->source()
->GetCachedData(); | 145 const v8::ScriptCompiler::CachedData* newCachedData = streamer->source()
->GetCachedData(); |
128 if (newCachedData) { | 146 if (newCachedData) { |
129 resource->clearCachedMetadata(); | 147 resource->clearCachedMetadata(); |
130 resource->setCachedMetadata(streamer->cachedDataType(), reinterpret_
cast<const char*>(newCachedData->data), newCachedData->length, Resource::CacheLo
cally); | 148 resource->setCachedMetadata(streamer->cachedDataType(), reinterpret_
cast<const char*>(newCachedData->data), newCachedData->length, Resource::CacheLo
cally); |
131 } | 149 } |
132 } else if (!resource || !resource->url().protocolIsInHTTPFamily() || code->L
ength() < 1024) { | 150 } else if (!resource || !resource->url().protocolIsInHTTPFamily() || code->L
ength() < 1024) { |
133 v8::ScriptCompiler::Source source(code, origin); | 151 v8::ScriptCompiler::Source source(code, origin); |
134 script = v8::ScriptCompiler::Compile(isolate, &source, v8::ScriptCompile
r::kNoCompileOptions); | 152 script = v8::ScriptCompiler::Compile(isolate, &source, v8::ScriptCompile
r::kNoCompileOptions); |
135 } else { | 153 } else { |
| 154 bool compressed = false; |
| 155 Resource::MetadataCacheType cacheType = Resource::CacheLocally; |
| 156 v8::ScriptCompiler::CompileOptions consumeOption = v8::ScriptCompiler::k
ConsumeParserCache; |
| 157 v8::ScriptCompiler::CompileOptions produceOption = v8::ScriptCompiler::k
ProduceParserCache; |
136 switch (cacheOptions) { | 158 switch (cacheOptions) { |
| 159 case V8CacheOptionsOff: |
| 160 // Use default. |
| 161 cacheTag = tagForParserCache(); |
| 162 break; |
137 case V8CacheOptionsParse: | 163 case V8CacheOptionsParse: |
138 cacheTag = tagForParserCache(); | 164 cacheTag = tagForParserCache(); |
139 script = resource->cachedMetadata(cacheTag) | 165 cacheType = Resource::SendToPlatform; |
140 ? compileAndConsumeCache(isolate, code, origin, resource, v8::Sc
riptCompiler::kConsumeParserCache, cacheTag) | 166 consumeOption = v8::ScriptCompiler::kConsumeParserCache; |
141 : compileAndProduceCache(isolate, code, origin, resource, v8::Sc
riptCompiler::kProduceParserCache, cacheTag, Resource::SendToPlatform); | 167 produceOption = v8::ScriptCompiler::kProduceParserCache; |
142 break; | 168 break; |
| 169 case V8CacheOptionsCodeCompressed: |
| 170 compressed = true; |
| 171 // Fall through. |
143 case V8CacheOptionsCode: | 172 case V8CacheOptionsCode: |
144 cacheTag = tagForCodeCache(); | 173 cacheTag = tagForCodeCache(); |
145 script = resource->cachedMetadata(cacheTag) | 174 cacheType = Resource::SendToPlatform; |
146 ? compileAndConsumeCache(isolate, code, origin, resource, v8::Sc
riptCompiler::kConsumeCodeCache, cacheTag) | 175 consumeOption = v8::ScriptCompiler::kConsumeCodeCache; |
147 : compileAndProduceCache(isolate, code, origin, resource, v8::Sc
riptCompiler::kProduceCodeCache, cacheTag, Resource::SendToPlatform); | 176 produceOption = v8::ScriptCompiler::kProduceCodeCache; |
148 break; | |
149 case V8CacheOptionsOff: | |
150 // Previous behaviour was to always generate an in-memory parser | |
151 // cache. We emulate this here. | |
152 // FIXME: Determine whether this should get its own setting, so we | |
153 // can also have a true 'off'. | |
154 cacheTag = tagForParserCache(); | |
155 script = resource->cachedMetadata(cacheTag) | |
156 ? compileAndConsumeCache(isolate, code, origin, resource, v8::Sc
riptCompiler::kConsumeParserCache, cacheTag) | |
157 : compileAndProduceCache(isolate, code, origin, resource, v8::Sc
riptCompiler::kProduceParserCache, cacheTag, Resource::CacheLocally); | |
158 break; | 177 break; |
159 } | 178 } |
| 179 script = resource->cachedMetadata(cacheTag) |
| 180 ? compileAndConsumeCache(isolate, code, origin, resource, consumeOpt
ion, cacheTag, compressed) |
| 181 : compileAndProduceCache(isolate, code, origin, resource, produceOpt
ion, cacheTag, cacheType, compressed); |
160 } | 182 } |
161 return script; | 183 return script; |
162 } | 184 } |
163 | 185 |
164 v8::Local<v8::Value> V8ScriptRunner::runCompiledScript(v8::Isolate* isolate, v8:
:Handle<v8::Script> script, ExecutionContext* context) | 186 v8::Local<v8::Value> V8ScriptRunner::runCompiledScript(v8::Isolate* isolate, v8:
:Handle<v8::Script> script, ExecutionContext* context) |
165 { | 187 { |
166 if (script.IsEmpty()) | 188 if (script.IsEmpty()) |
167 return v8::Local<v8::Value>(); | 189 return v8::Local<v8::Value>(); |
168 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Execution"); | 190 TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Execution"); |
169 TRACE_EVENT1("v8", "v8.run", "fileName", TRACE_STR_COPY(*v8::String::Utf8Val
ue(script->GetUnboundScript()->GetScriptName()))); | 191 TRACE_EVENT1("v8", "v8.run", "fileName", TRACE_STR_COPY(*v8::String::Utf8Val
ue(script->GetUnboundScript()->GetScriptName()))); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 { | 312 { |
291 return StringHash::hash(v8::V8::GetVersion()) * 2; | 313 return StringHash::hash(v8::V8::GetVersion()) * 2; |
292 } | 314 } |
293 | 315 |
294 unsigned V8ScriptRunner::tagForCodeCache() | 316 unsigned V8ScriptRunner::tagForCodeCache() |
295 { | 317 { |
296 return StringHash::hash(v8::V8::GetVersion()) * 2 + 1; | 318 return StringHash::hash(v8::V8::GetVersion()) * 2 + 1; |
297 } | 319 } |
298 | 320 |
299 } // namespace blink | 321 } // namespace blink |
OLD | NEW |