OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/snapshot/code-serializer.h" | 5 #include "src/snapshot/code-serializer.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/log.h" | 10 #include "src/log.h" |
11 #include "src/macro-assembler.h" | 11 #include "src/macro-assembler.h" |
12 #include "src/snapshot/deserializer.h" | 12 #include "src/snapshot/deserializer.h" |
| 13 #include "src/snapshot/snapshot.h" |
13 #include "src/version.h" | 14 #include "src/version.h" |
14 | 15 |
15 namespace v8 { | 16 namespace v8 { |
16 namespace internal { | 17 namespace internal { |
17 | 18 |
18 ScriptData* CodeSerializer::Serialize(Isolate* isolate, | 19 ScriptData* CodeSerializer::Serialize(Isolate* isolate, |
19 Handle<SharedFunctionInfo> info, | 20 Handle<SharedFunctionInfo> info, |
20 Handle<String> source) { | 21 Handle<String> source) { |
21 base::ElapsedTimer timer; | 22 base::ElapsedTimer timer; |
22 if (FLAG_profile_deserialization) timer.Start(); | 23 if (FLAG_profile_deserialization) timer.Start(); |
23 if (FLAG_trace_serializer) { | 24 if (FLAG_trace_serializer) { |
24 PrintF("[Serializing from"); | 25 PrintF("[Serializing from"); |
25 Object* script = info->script(); | 26 Object* script = info->script(); |
26 if (script->IsScript()) Script::cast(script)->name()->ShortPrint(); | 27 if (script->IsScript()) Script::cast(script)->name()->ShortPrint(); |
27 PrintF("]\n"); | 28 PrintF("]\n"); |
28 } | 29 } |
29 | 30 |
30 // Serialize code object. | 31 // Serialize code object. |
31 CodeSerializer cs(isolate, *source); | 32 CodeSerializer cs(isolate, SerializedCodeData::SourceHash(source)); |
32 DisallowHeapAllocation no_gc; | 33 DisallowHeapAllocation no_gc; |
33 Object** location = Handle<Object>::cast(info).location(); | 34 cs.reference_map()->AddAttachedReference(*source); |
34 cs.VisitPointer(location); | 35 ScriptData* ret = cs.Serialize(info); |
35 cs.SerializeDeferredObjects(); | |
36 cs.Pad(); | |
37 | |
38 SerializedCodeData data(cs.sink()->data(), &cs); | |
39 ScriptData* script_data = data.GetScriptData(); | |
40 | 36 |
41 if (FLAG_profile_deserialization) { | 37 if (FLAG_profile_deserialization) { |
42 double ms = timer.Elapsed().InMillisecondsF(); | 38 double ms = timer.Elapsed().InMillisecondsF(); |
43 int length = script_data->length(); | 39 int length = ret->length(); |
44 PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms); | 40 PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms); |
45 } | 41 } |
46 | 42 |
47 return script_data; | 43 return ret; |
| 44 } |
| 45 |
| 46 ScriptData* CodeSerializer::Serialize(Handle<HeapObject> obj) { |
| 47 DisallowHeapAllocation no_gc; |
| 48 |
| 49 VisitPointer(Handle<Object>::cast(obj).location()); |
| 50 SerializeDeferredObjects(); |
| 51 Pad(); |
| 52 |
| 53 SerializedCodeData data(sink()->data(), this); |
| 54 |
| 55 return data.GetScriptData(); |
48 } | 56 } |
49 | 57 |
50 void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, | 58 void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, |
51 WhereToPoint where_to_point, int skip) { | 59 WhereToPoint where_to_point, int skip) { |
52 if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return; | 60 if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return; |
53 | 61 |
54 int root_index = root_index_map_.Lookup(obj); | 62 int root_index = root_index_map_.Lookup(obj); |
55 if (root_index != RootIndexMap::kInvalidRootIndex) { | 63 if (root_index != RootIndexMap::kInvalidRootIndex) { |
56 PutRoot(root_index, obj, how_to_code, where_to_point, skip); | 64 PutRoot(root_index, obj, how_to_code, where_to_point, skip); |
57 return; | 65 return; |
(...skipping 19 matching lines...) Expand all Loading... |
77 case Code::STUB: | 85 case Code::STUB: |
78 #define IC_KIND_CASE(KIND) case Code::KIND: | 86 #define IC_KIND_CASE(KIND) case Code::KIND: |
79 IC_KIND_LIST(IC_KIND_CASE) | 87 IC_KIND_LIST(IC_KIND_CASE) |
80 #undef IC_KIND_CASE | 88 #undef IC_KIND_CASE |
81 SerializeCodeStub(code_object, how_to_code, where_to_point); | 89 SerializeCodeStub(code_object, how_to_code, where_to_point); |
82 return; | 90 return; |
83 case Code::FUNCTION: | 91 case Code::FUNCTION: |
84 DCHECK(code_object->has_reloc_info_for_serialization()); | 92 DCHECK(code_object->has_reloc_info_for_serialization()); |
85 SerializeGeneric(code_object, how_to_code, where_to_point); | 93 SerializeGeneric(code_object, how_to_code, where_to_point); |
86 return; | 94 return; |
87 case Code::WASM_FUNCTION: | 95 default: |
88 case Code::WASM_TO_JS_FUNCTION: | 96 return SerializeCodeObject(code_object, how_to_code, where_to_point); |
89 case Code::JS_TO_WASM_FUNCTION: | |
90 UNREACHABLE(); | |
91 } | 97 } |
92 UNREACHABLE(); | 98 UNREACHABLE(); |
93 } | 99 } |
94 | 100 |
95 // Past this point we should not see any (context-specific) maps anymore. | 101 // Past this point we should not see any (context-specific) maps anymore. |
96 CHECK(!obj->IsMap()); | 102 CHECK(!obj->IsMap()); |
97 // There should be no references to the global object embedded. | 103 // There should be no references to the global object embedded. |
98 CHECK(!obj->IsJSGlobalProxy() && !obj->IsJSGlobalObject()); | 104 CHECK(!obj->IsJSGlobalProxy() && !obj->IsJSGlobalObject()); |
99 // There should be no hash table embedded. They would require rehashing. | 105 // There should be no hash table embedded. They would require rehashing. |
100 CHECK(!obj->IsHashTable()); | 106 CHECK(!obj->IsHashTable()); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 PutAttachedReference(reference, how_to_code, where_to_point); | 155 PutAttachedReference(reference, how_to_code, where_to_point); |
150 } | 156 } |
151 | 157 |
152 MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( | 158 MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( |
153 Isolate* isolate, ScriptData* cached_data, Handle<String> source) { | 159 Isolate* isolate, ScriptData* cached_data, Handle<String> source) { |
154 base::ElapsedTimer timer; | 160 base::ElapsedTimer timer; |
155 if (FLAG_profile_deserialization) timer.Start(); | 161 if (FLAG_profile_deserialization) timer.Start(); |
156 | 162 |
157 HandleScope scope(isolate); | 163 HandleScope scope(isolate); |
158 | 164 |
159 std::unique_ptr<SerializedCodeData> scd( | 165 SerializedCodeData::SanityCheckResult sanity_check_result = |
160 SerializedCodeData::FromCachedData(isolate, cached_data, *source)); | 166 SerializedCodeData::CHECK_SUCCESS; |
161 if (!scd) { | 167 const SerializedCodeData scd = SerializedCodeData::FromCachedData( |
| 168 isolate, cached_data, SerializedCodeData::SourceHash(source), |
| 169 &sanity_check_result); |
| 170 if (sanity_check_result != SerializedCodeData::CHECK_SUCCESS) { |
162 if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n"); | 171 if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n"); |
163 DCHECK(cached_data->rejected()); | 172 DCHECK(cached_data->rejected()); |
| 173 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample( |
| 174 sanity_check_result); |
164 return MaybeHandle<SharedFunctionInfo>(); | 175 return MaybeHandle<SharedFunctionInfo>(); |
165 } | 176 } |
166 | 177 |
167 Deserializer deserializer(scd.get()); | 178 Deserializer deserializer(&scd); |
168 deserializer.AddAttachedObject(source); | 179 deserializer.AddAttachedObject(source); |
169 Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys(); | 180 Vector<const uint32_t> code_stub_keys = scd.CodeStubKeys(); |
170 for (int i = 0; i < code_stub_keys.length(); i++) { | 181 for (int i = 0; i < code_stub_keys.length(); i++) { |
171 deserializer.AddAttachedObject( | 182 deserializer.AddAttachedObject( |
172 CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked()); | 183 CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked()); |
173 } | 184 } |
174 | 185 |
175 // Deserialize. | 186 // Deserialize. |
176 Handle<SharedFunctionInfo> result; | 187 Handle<HeapObject> as_heap_object; |
177 if (!deserializer.DeserializeCode(isolate).ToHandle(&result)) { | 188 if (!deserializer.DeserializeObject(isolate).ToHandle(&as_heap_object)) { |
178 // Deserializing may fail if the reservations cannot be fulfilled. | 189 // Deserializing may fail if the reservations cannot be fulfilled. |
179 if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n"); | 190 if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n"); |
180 return MaybeHandle<SharedFunctionInfo>(); | 191 return MaybeHandle<SharedFunctionInfo>(); |
181 } | 192 } |
182 | 193 |
| 194 Handle<SharedFunctionInfo> result = |
| 195 Handle<SharedFunctionInfo>::cast(as_heap_object); |
183 if (FLAG_profile_deserialization) { | 196 if (FLAG_profile_deserialization) { |
184 double ms = timer.Elapsed().InMillisecondsF(); | 197 double ms = timer.Elapsed().InMillisecondsF(); |
185 int length = cached_data->length(); | 198 int length = cached_data->length(); |
186 PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms); | 199 PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms); |
187 } | 200 } |
188 result->set_deserialized(true); | 201 result->set_deserialized(true); |
189 | 202 |
190 if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) { | 203 if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) { |
191 String* name = isolate->heap()->empty_string(); | 204 String* name = isolate->heap()->empty_string(); |
192 if (result->script()->IsScript()) { | 205 if (result->script()->IsScript()) { |
193 Script* script = Script::cast(result->script()); | 206 Script* script = Script::cast(result->script()); |
194 if (script->name()->IsString()) name = String::cast(script->name()); | 207 if (script->name()->IsString()) name = String::cast(script->name()); |
195 } | 208 } |
196 PROFILE(isolate, CodeCreateEvent(CodeEventListener::SCRIPT_TAG, | 209 PROFILE(isolate, CodeCreateEvent(CodeEventListener::SCRIPT_TAG, |
197 result->abstract_code(), *result, name)); | 210 result->abstract_code(), *result, name)); |
198 } | 211 } |
199 return scope.CloseAndEscape(result); | 212 return scope.CloseAndEscape(result); |
200 } | 213 } |
201 | 214 |
| 215 std::unique_ptr<ScriptData> WasmCompiledModuleSerializer::SerializeWasmModule( |
| 216 Isolate* isolate, Handle<FixedArray> compiled_module) { |
| 217 WasmCompiledModuleSerializer wasm_cs(isolate, 0); |
| 218 wasm_cs.reference_map()->AddAttachedReference(*isolate->native_context()); |
| 219 ScriptData* data = wasm_cs.Serialize(compiled_module); |
| 220 return std::unique_ptr<ScriptData>(data); |
| 221 } |
| 222 |
| 223 MaybeHandle<FixedArray> WasmCompiledModuleSerializer::DeserializeWasmModule( |
| 224 Isolate* isolate, ScriptData* data) { |
| 225 SerializedCodeData::SanityCheckResult sanity_check_result = |
| 226 SerializedCodeData::CHECK_SUCCESS; |
| 227 MaybeHandle<FixedArray> nothing; |
| 228 const SerializedCodeData scd = SerializedCodeData::FromCachedData( |
| 229 isolate, data, 0, &sanity_check_result); |
| 230 |
| 231 if (sanity_check_result != SerializedCodeData::CHECK_SUCCESS) { |
| 232 return nothing; |
| 233 } |
| 234 |
| 235 Deserializer deserializer(&scd, true); |
| 236 deserializer.AddAttachedObject(isolate->native_context()); |
| 237 |
| 238 Vector<const uint32_t> stub_keys = scd.CodeStubKeys(); |
| 239 for (int i = 0; i < stub_keys.length(); ++i) { |
| 240 deserializer.AddAttachedObject( |
| 241 CodeStub::GetCode(isolate, stub_keys[i]).ToHandleChecked()); |
| 242 } |
| 243 |
| 244 MaybeHandle<HeapObject> obj = deserializer.DeserializeObject(isolate); |
| 245 if (obj.is_null() || !obj.ToHandleChecked()->IsFixedArray()) return nothing; |
| 246 return Handle<FixedArray>::cast(obj.ToHandleChecked()); |
| 247 } |
| 248 |
202 class Checksum { | 249 class Checksum { |
203 public: | 250 public: |
204 explicit Checksum(Vector<const byte> payload) { | 251 explicit Checksum(Vector<const byte> payload) { |
205 #ifdef MEMORY_SANITIZER | 252 #ifdef MEMORY_SANITIZER |
206 // Computing the checksum includes padding bytes for objects like strings. | 253 // Computing the checksum includes padding bytes for objects like strings. |
207 // Mark every object as initialized in the code serializer. | 254 // Mark every object as initialized in the code serializer. |
208 MSAN_MEMORY_IS_INITIALIZED(payload.start(), payload.length()); | 255 MSAN_MEMORY_IS_INITIALIZED(payload.start(), payload.length()); |
209 #endif // MEMORY_SANITIZER | 256 #endif // MEMORY_SANITIZER |
210 // Fletcher's checksum. Modified to reduce 64-bit sums to 32-bit. | 257 // Fletcher's checksum. Modified to reduce 64-bit sums to 32-bit. |
211 uintptr_t a = 1; | 258 uintptr_t a = 1; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 int payload_offset = kHeaderSize + reservation_size + stub_keys_size; | 300 int payload_offset = kHeaderSize + reservation_size + stub_keys_size; |
254 int padded_payload_offset = POINTER_SIZE_ALIGN(payload_offset); | 301 int padded_payload_offset = POINTER_SIZE_ALIGN(payload_offset); |
255 int size = padded_payload_offset + payload->length(); | 302 int size = padded_payload_offset + payload->length(); |
256 | 303 |
257 // Allocate backing store and create result data. | 304 // Allocate backing store and create result data. |
258 AllocateData(size); | 305 AllocateData(size); |
259 | 306 |
260 // Set header values. | 307 // Set header values. |
261 SetMagicNumber(cs->isolate()); | 308 SetMagicNumber(cs->isolate()); |
262 SetHeaderValue(kVersionHashOffset, Version::Hash()); | 309 SetHeaderValue(kVersionHashOffset, Version::Hash()); |
263 SetHeaderValue(kSourceHashOffset, SourceHash(cs->source())); | 310 SetHeaderValue(kSourceHashOffset, cs->source_hash()); |
264 SetHeaderValue(kCpuFeaturesOffset, | 311 SetHeaderValue(kCpuFeaturesOffset, |
265 static_cast<uint32_t>(CpuFeatures::SupportedFeatures())); | 312 static_cast<uint32_t>(CpuFeatures::SupportedFeatures())); |
266 SetHeaderValue(kFlagHashOffset, FlagList::Hash()); | 313 SetHeaderValue(kFlagHashOffset, FlagList::Hash()); |
267 SetHeaderValue(kNumReservationsOffset, reservations.length()); | 314 SetHeaderValue(kNumReservationsOffset, reservations.length()); |
268 SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys); | 315 SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys); |
269 SetHeaderValue(kPayloadLengthOffset, payload->length()); | 316 SetHeaderValue(kPayloadLengthOffset, payload->length()); |
270 | 317 |
271 Checksum checksum(payload->ToConstVector()); | 318 Checksum checksum(payload->ToConstVector()); |
272 SetHeaderValue(kChecksum1Offset, checksum.a()); | 319 SetHeaderValue(kChecksum1Offset, checksum.a()); |
273 SetHeaderValue(kChecksum2Offset, checksum.b()); | 320 SetHeaderValue(kChecksum2Offset, checksum.b()); |
274 | 321 |
275 // Copy reservation chunk sizes. | 322 // Copy reservation chunk sizes. |
276 CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()), | 323 CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()), |
277 reservation_size); | 324 reservation_size); |
278 | 325 |
279 // Copy code stub keys. | 326 // Copy code stub keys. |
280 CopyBytes(data_ + kHeaderSize + reservation_size, | 327 CopyBytes(data_ + kHeaderSize + reservation_size, |
281 reinterpret_cast<byte*>(stub_keys->begin()), stub_keys_size); | 328 reinterpret_cast<byte*>(stub_keys->begin()), stub_keys_size); |
282 | 329 |
283 memset(data_ + payload_offset, 0, padded_payload_offset - payload_offset); | 330 memset(data_ + payload_offset, 0, padded_payload_offset - payload_offset); |
284 | 331 |
285 // Copy serialized data. | 332 // Copy serialized data. |
286 CopyBytes(data_ + padded_payload_offset, payload->begin(), | 333 CopyBytes(data_ + padded_payload_offset, payload->begin(), |
287 static_cast<size_t>(payload->length())); | 334 static_cast<size_t>(payload->length())); |
288 } | 335 } |
289 | 336 |
290 SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck( | 337 SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck( |
291 Isolate* isolate, String* source) const { | 338 Isolate* isolate, uint32_t expected_source_hash) const { |
292 uint32_t magic_number = GetMagicNumber(); | 339 uint32_t magic_number = GetMagicNumber(); |
293 if (magic_number != ComputeMagicNumber(isolate)) return MAGIC_NUMBER_MISMATCH; | 340 if (magic_number != ComputeMagicNumber(isolate)) return MAGIC_NUMBER_MISMATCH; |
294 uint32_t version_hash = GetHeaderValue(kVersionHashOffset); | 341 uint32_t version_hash = GetHeaderValue(kVersionHashOffset); |
295 uint32_t source_hash = GetHeaderValue(kSourceHashOffset); | 342 uint32_t source_hash = GetHeaderValue(kSourceHashOffset); |
296 uint32_t cpu_features = GetHeaderValue(kCpuFeaturesOffset); | 343 uint32_t cpu_features = GetHeaderValue(kCpuFeaturesOffset); |
297 uint32_t flags_hash = GetHeaderValue(kFlagHashOffset); | 344 uint32_t flags_hash = GetHeaderValue(kFlagHashOffset); |
298 uint32_t c1 = GetHeaderValue(kChecksum1Offset); | 345 uint32_t c1 = GetHeaderValue(kChecksum1Offset); |
299 uint32_t c2 = GetHeaderValue(kChecksum2Offset); | 346 uint32_t c2 = GetHeaderValue(kChecksum2Offset); |
300 if (version_hash != Version::Hash()) return VERSION_MISMATCH; | 347 if (version_hash != Version::Hash()) return VERSION_MISMATCH; |
301 if (source_hash != SourceHash(source)) return SOURCE_MISMATCH; | 348 if (source_hash != expected_source_hash) return SOURCE_MISMATCH; |
302 if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) { | 349 if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) { |
303 return CPU_FEATURES_MISMATCH; | 350 return CPU_FEATURES_MISMATCH; |
304 } | 351 } |
305 if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH; | 352 if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH; |
306 if (!Checksum(Payload()).Check(c1, c2)) return CHECKSUM_MISMATCH; | 353 if (!Checksum(Payload()).Check(c1, c2)) return CHECKSUM_MISMATCH; |
307 return CHECK_SUCCESS; | 354 return CHECK_SUCCESS; |
308 } | 355 } |
309 | 356 |
310 uint32_t SerializedCodeData::SourceHash(String* source) const { | 357 uint32_t SerializedCodeData::SourceHash(Handle<String> source) { |
311 return source->length(); | 358 return source->length(); |
312 } | 359 } |
313 | 360 |
314 // Return ScriptData object and relinquish ownership over it to the caller. | 361 // Return ScriptData object and relinquish ownership over it to the caller. |
315 ScriptData* SerializedCodeData::GetScriptData() { | 362 ScriptData* SerializedCodeData::GetScriptData() { |
316 DCHECK(owns_data_); | 363 DCHECK(owns_data_); |
317 ScriptData* result = new ScriptData(data_, size_); | 364 ScriptData* result = new ScriptData(data_, size_); |
318 result->AcquireDataOwnership(); | 365 result->AcquireDataOwnership(); |
319 owns_data_ = false; | 366 owns_data_ = false; |
320 data_ = NULL; | 367 data_ = NULL; |
(...skipping 22 matching lines...) Expand all Loading... |
343 Vector<const uint32_t> SerializedCodeData::CodeStubKeys() const { | 390 Vector<const uint32_t> SerializedCodeData::CodeStubKeys() const { |
344 int reservations_size = GetHeaderValue(kNumReservationsOffset) * kInt32Size; | 391 int reservations_size = GetHeaderValue(kNumReservationsOffset) * kInt32Size; |
345 const byte* start = data_ + kHeaderSize + reservations_size; | 392 const byte* start = data_ + kHeaderSize + reservations_size; |
346 return Vector<const uint32_t>(reinterpret_cast<const uint32_t*>(start), | 393 return Vector<const uint32_t>(reinterpret_cast<const uint32_t*>(start), |
347 GetHeaderValue(kNumCodeStubKeysOffset)); | 394 GetHeaderValue(kNumCodeStubKeysOffset)); |
348 } | 395 } |
349 | 396 |
350 SerializedCodeData::SerializedCodeData(ScriptData* data) | 397 SerializedCodeData::SerializedCodeData(ScriptData* data) |
351 : SerializedData(const_cast<byte*>(data->data()), data->length()) {} | 398 : SerializedData(const_cast<byte*>(data->data()), data->length()) {} |
352 | 399 |
353 SerializedCodeData* SerializedCodeData::FromCachedData(Isolate* isolate, | 400 const SerializedCodeData SerializedCodeData::FromCachedData( |
354 ScriptData* cached_data, | 401 Isolate* isolate, ScriptData* cached_data, uint32_t expected_source_hash, |
355 String* source) { | 402 SanityCheckResult* rejection_result) { |
356 DisallowHeapAllocation no_gc; | 403 DisallowHeapAllocation no_gc; |
357 SerializedCodeData* scd = new SerializedCodeData(cached_data); | 404 SerializedCodeData scd(cached_data); |
358 SanityCheckResult r = scd->SanityCheck(isolate, source); | 405 *rejection_result = scd.SanityCheck(isolate, expected_source_hash); |
359 if (r == CHECK_SUCCESS) return scd; | 406 if (*rejection_result != CHECK_SUCCESS) { |
360 cached_data->Reject(); | 407 cached_data->Reject(); |
361 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); | 408 return SerializedCodeData(nullptr, 0); |
362 delete scd; | 409 } |
363 return NULL; | 410 return scd; |
364 } | 411 } |
365 | 412 |
366 } // namespace internal | 413 } // namespace internal |
367 } // namespace v8 | 414 } // namespace v8 |
OLD | NEW |