Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: src/snapshot/code-serializer.cc

Issue 2205973003: [wasm] Serialization/Deserialization of compiled module (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix silly bug Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 22 matching lines...) Expand all
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 case Code::WASM_FUNCTION:
88 case Code::WASM_TO_JS_FUNCTION: 96 case Code::WASM_TO_JS_FUNCTION:
89 case Code::JS_TO_WASM_FUNCTION: 97 case Code::JS_TO_WASM_FUNCTION:
90 UNREACHABLE(); 98 SerializeGeneric(code_object, how_to_code, where_to_point);
Yang 2016/08/05 12:04:17 Would it make sense to check for code_object->has_
Yang 2016/08/05 12:05:44 Also, assuming that we will use a subclass of Code
Mircea Trofin 2016/08/05 15:01:29 We don't set that flag. Should we? It seems to be
Yang 2016/08/05 15:39:28 We don't emit reloc info for external references i
Mircea Trofin 2016/08/06 00:31:39 I see - thanks. It turns out that has_reloc_code
99 return;
91 } 100 }
92 UNREACHABLE(); 101 UNREACHABLE();
93 } 102 }
94 103
95 // Past this point we should not see any (context-specific) maps anymore. 104 // Past this point we should not see any (context-specific) maps anymore.
96 CHECK(!obj->IsMap()); 105 CHECK(!obj->IsMap());
97 // There should be no references to the global object embedded. 106 // There should be no references to the global object embedded.
98 CHECK(!obj->IsJSGlobalProxy() && !obj->IsJSGlobalObject()); 107 CHECK(!obj->IsJSGlobalProxy() && !obj->IsJSGlobalObject());
99 // There should be no hash table embedded. They would require rehashing. 108 // There should be no hash table embedded. They would require rehashing.
100 CHECK(!obj->IsHashTable()); 109 CHECK(!obj->IsHashTable());
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 PutAttachedReference(reference, how_to_code, where_to_point); 158 PutAttachedReference(reference, how_to_code, where_to_point);
150 } 159 }
151 160
152 MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( 161 MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
153 Isolate* isolate, ScriptData* cached_data, Handle<String> source) { 162 Isolate* isolate, ScriptData* cached_data, Handle<String> source) {
154 base::ElapsedTimer timer; 163 base::ElapsedTimer timer;
155 if (FLAG_profile_deserialization) timer.Start(); 164 if (FLAG_profile_deserialization) timer.Start();
156 165
157 HandleScope scope(isolate); 166 HandleScope scope(isolate);
158 167
159 std::unique_ptr<SerializedCodeData> scd( 168 SanityCheckResult sanity_check_result = CHECK_SUCCESS;
160 SerializedCodeData::FromCachedData(isolate, cached_data, *source)); 169 const SerializedCodeData scd = SerializedCodeData::FromCachedData(
161 if (!scd) { 170 isolate, cached_data, SerializedCodeData::SourceHash(source),
171 &sanity_check_result);
172 if (sanity_check_result != CHECK_SUCCESS) {
162 if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n"); 173 if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n");
163 DCHECK(cached_data->rejected()); 174 DCHECK(cached_data->rejected());
175 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(
176 sanity_check_result);
164 return MaybeHandle<SharedFunctionInfo>(); 177 return MaybeHandle<SharedFunctionInfo>();
165 } 178 }
166 179
167 Deserializer deserializer(scd.get()); 180 Deserializer deserializer(&scd);
168 deserializer.AddAttachedObject(source); 181 deserializer.AddAttachedObject(source);
169 Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys(); 182 Vector<const uint32_t> code_stub_keys = scd.CodeStubKeys();
170 for (int i = 0; i < code_stub_keys.length(); i++) { 183 for (int i = 0; i < code_stub_keys.length(); i++) {
171 deserializer.AddAttachedObject( 184 deserializer.AddAttachedObject(
172 CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked()); 185 CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked());
173 } 186 }
174 187
175 // Deserialize. 188 // Deserialize.
176 Handle<SharedFunctionInfo> result; 189 Handle<HeapObject> as_heap_object;
177 if (!deserializer.DeserializeCode(isolate).ToHandle(&result)) { 190 if (!deserializer.DeserializeObject(isolate).ToHandle(&as_heap_object)) {
178 // Deserializing may fail if the reservations cannot be fulfilled. 191 // Deserializing may fail if the reservations cannot be fulfilled.
179 if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n"); 192 if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n");
180 return MaybeHandle<SharedFunctionInfo>(); 193 return MaybeHandle<SharedFunctionInfo>();
181 } 194 }
182 195
196 Handle<SharedFunctionInfo> result =
197 Handle<SharedFunctionInfo>::cast(as_heap_object);
183 if (FLAG_profile_deserialization) { 198 if (FLAG_profile_deserialization) {
184 double ms = timer.Elapsed().InMillisecondsF(); 199 double ms = timer.Elapsed().InMillisecondsF();
185 int length = cached_data->length(); 200 int length = cached_data->length();
186 PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms); 201 PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms);
187 } 202 }
188 result->set_deserialized(true); 203 result->set_deserialized(true);
189 204
190 if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) { 205 if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) {
191 String* name = isolate->heap()->empty_string(); 206 String* name = isolate->heap()->empty_string();
192 if (result->script()->IsScript()) { 207 if (result->script()->IsScript()) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 int payload_offset = kHeaderSize + reservation_size + stub_keys_size; 268 int payload_offset = kHeaderSize + reservation_size + stub_keys_size;
254 int padded_payload_offset = POINTER_SIZE_ALIGN(payload_offset); 269 int padded_payload_offset = POINTER_SIZE_ALIGN(payload_offset);
255 int size = padded_payload_offset + payload->length(); 270 int size = padded_payload_offset + payload->length();
256 271
257 // Allocate backing store and create result data. 272 // Allocate backing store and create result data.
258 AllocateData(size); 273 AllocateData(size);
259 274
260 // Set header values. 275 // Set header values.
261 SetMagicNumber(cs->isolate()); 276 SetMagicNumber(cs->isolate());
262 SetHeaderValue(kVersionHashOffset, Version::Hash()); 277 SetHeaderValue(kVersionHashOffset, Version::Hash());
263 SetHeaderValue(kSourceHashOffset, SourceHash(cs->source())); 278 SetHeaderValue(kSourceHashOffset, cs->source_hash());
264 SetHeaderValue(kCpuFeaturesOffset, 279 SetHeaderValue(kCpuFeaturesOffset,
265 static_cast<uint32_t>(CpuFeatures::SupportedFeatures())); 280 static_cast<uint32_t>(CpuFeatures::SupportedFeatures()));
266 SetHeaderValue(kFlagHashOffset, FlagList::Hash()); 281 SetHeaderValue(kFlagHashOffset, FlagList::Hash());
267 SetHeaderValue(kNumReservationsOffset, reservations.length()); 282 SetHeaderValue(kNumReservationsOffset, reservations.length());
268 SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys); 283 SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys);
269 SetHeaderValue(kPayloadLengthOffset, payload->length()); 284 SetHeaderValue(kPayloadLengthOffset, payload->length());
270 285
271 Checksum checksum(payload->ToConstVector()); 286 Checksum checksum(payload->ToConstVector());
272 SetHeaderValue(kChecksum1Offset, checksum.a()); 287 SetHeaderValue(kChecksum1Offset, checksum.a());
273 SetHeaderValue(kChecksum2Offset, checksum.b()); 288 SetHeaderValue(kChecksum2Offset, checksum.b());
274 289
275 // Copy reservation chunk sizes. 290 // Copy reservation chunk sizes.
276 CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()), 291 CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()),
277 reservation_size); 292 reservation_size);
278 293
279 // Copy code stub keys. 294 // Copy code stub keys.
280 CopyBytes(data_ + kHeaderSize + reservation_size, 295 CopyBytes(data_ + kHeaderSize + reservation_size,
281 reinterpret_cast<byte*>(stub_keys->begin()), stub_keys_size); 296 reinterpret_cast<byte*>(stub_keys->begin()), stub_keys_size);
282 297
283 memset(data_ + payload_offset, 0, padded_payload_offset - payload_offset); 298 memset(data_ + payload_offset, 0, padded_payload_offset - payload_offset);
284 299
285 // Copy serialized data. 300 // Copy serialized data.
286 CopyBytes(data_ + padded_payload_offset, payload->begin(), 301 CopyBytes(data_ + padded_payload_offset, payload->begin(),
287 static_cast<size_t>(payload->length())); 302 static_cast<size_t>(payload->length()));
288 } 303 }
289 304
290 SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck( 305 SanityCheckResult SerializedCodeData::SanityCheck(
291 Isolate* isolate, String* source) const { 306 Isolate* isolate, uint32_t expected_source_hash) const {
292 uint32_t magic_number = GetMagicNumber(); 307 uint32_t magic_number = GetMagicNumber();
293 if (magic_number != ComputeMagicNumber(isolate)) return MAGIC_NUMBER_MISMATCH; 308 if (magic_number != ComputeMagicNumber(isolate)) return MAGIC_NUMBER_MISMATCH;
294 uint32_t version_hash = GetHeaderValue(kVersionHashOffset); 309 uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
295 uint32_t source_hash = GetHeaderValue(kSourceHashOffset); 310 uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
296 uint32_t cpu_features = GetHeaderValue(kCpuFeaturesOffset); 311 uint32_t cpu_features = GetHeaderValue(kCpuFeaturesOffset);
297 uint32_t flags_hash = GetHeaderValue(kFlagHashOffset); 312 uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
298 uint32_t c1 = GetHeaderValue(kChecksum1Offset); 313 uint32_t c1 = GetHeaderValue(kChecksum1Offset);
299 uint32_t c2 = GetHeaderValue(kChecksum2Offset); 314 uint32_t c2 = GetHeaderValue(kChecksum2Offset);
300 if (version_hash != Version::Hash()) return VERSION_MISMATCH; 315 if (version_hash != Version::Hash()) return VERSION_MISMATCH;
301 if (source_hash != SourceHash(source)) return SOURCE_MISMATCH; 316 if (source_hash != expected_source_hash) return SOURCE_MISMATCH;
302 if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) { 317 if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) {
303 return CPU_FEATURES_MISMATCH; 318 return CPU_FEATURES_MISMATCH;
304 } 319 }
305 if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH; 320 if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
306 if (!Checksum(Payload()).Check(c1, c2)) return CHECKSUM_MISMATCH; 321 if (!Checksum(Payload()).Check(c1, c2)) return CHECKSUM_MISMATCH;
307 return CHECK_SUCCESS; 322 return CHECK_SUCCESS;
308 } 323 }
309 324
310 uint32_t SerializedCodeData::SourceHash(String* source) const { 325 uint32_t SerializedCodeData::SourceHash(Handle<String> source) {
311 return source->length(); 326 return source->length();
312 } 327 }
313 328
314 // Return ScriptData object and relinquish ownership over it to the caller. 329 // Return ScriptData object and relinquish ownership over it to the caller.
315 ScriptData* SerializedCodeData::GetScriptData() { 330 ScriptData* SerializedCodeData::GetScriptData() {
316 DCHECK(owns_data_); 331 DCHECK(owns_data_);
317 ScriptData* result = new ScriptData(data_, size_); 332 ScriptData* result = new ScriptData(data_, size_);
318 result->AcquireDataOwnership(); 333 result->AcquireDataOwnership();
319 owns_data_ = false; 334 owns_data_ = false;
320 data_ = NULL; 335 data_ = NULL;
(...skipping 22 matching lines...) Expand all
343 Vector<const uint32_t> SerializedCodeData::CodeStubKeys() const { 358 Vector<const uint32_t> SerializedCodeData::CodeStubKeys() const {
344 int reservations_size = GetHeaderValue(kNumReservationsOffset) * kInt32Size; 359 int reservations_size = GetHeaderValue(kNumReservationsOffset) * kInt32Size;
345 const byte* start = data_ + kHeaderSize + reservations_size; 360 const byte* start = data_ + kHeaderSize + reservations_size;
346 return Vector<const uint32_t>(reinterpret_cast<const uint32_t*>(start), 361 return Vector<const uint32_t>(reinterpret_cast<const uint32_t*>(start),
347 GetHeaderValue(kNumCodeStubKeysOffset)); 362 GetHeaderValue(kNumCodeStubKeysOffset));
348 } 363 }
349 364
350 SerializedCodeData::SerializedCodeData(ScriptData* data) 365 SerializedCodeData::SerializedCodeData(ScriptData* data)
351 : SerializedData(const_cast<byte*>(data->data()), data->length()) {} 366 : SerializedData(const_cast<byte*>(data->data()), data->length()) {}
352 367
353 SerializedCodeData* SerializedCodeData::FromCachedData(Isolate* isolate, 368 const SerializedCodeData SerializedCodeData::FromCachedData(
354 ScriptData* cached_data, 369 Isolate* isolate, ScriptData* cached_data, uint32_t expected_source_hash,
355 String* source) { 370 SanityCheckResult* rejection_result) {
356 DisallowHeapAllocation no_gc; 371 DisallowHeapAllocation no_gc;
357 SerializedCodeData* scd = new SerializedCodeData(cached_data); 372 SerializedCodeData scd(cached_data);
358 SanityCheckResult r = scd->SanityCheck(isolate, source); 373 *rejection_result = scd.SanityCheck(isolate, expected_source_hash);
359 if (r == CHECK_SUCCESS) return scd; 374 if (*rejection_result != CHECK_SUCCESS) {
360 cached_data->Reject(); 375 cached_data->Reject();
361 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); 376 return SerializedCodeData(nullptr, 0);
362 delete scd; 377 }
363 return NULL; 378 return scd;
364 } 379 }
365 380
366 } // namespace internal 381 } // namespace internal
367 } // namespace v8 382 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698