Line data Source code
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
3 : // found in the LICENSE file.
4 :
5 : #include "src/snapshot/deserializer.h"
6 :
7 : #include "src/assembler-inl.h"
8 : #include "src/isolate.h"
9 : #include "src/objects/string.h"
10 : #include "src/snapshot/builtin-deserializer-allocator.h"
11 : #include "src/snapshot/natives.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 :
16 : template <class AllocatorT>
17 294549 : void Deserializer<AllocatorT>::Initialize(Isolate* isolate) {
18 : DCHECK_NULL(isolate_);
19 : DCHECK_NOT_NULL(isolate);
20 294549 : isolate_ = isolate;
21 : DCHECK_NULL(external_reference_table_);
22 294549 : external_reference_table_ = ExternalReferenceTable::instance(isolate);
23 : #ifdef DEBUG
24 : // Count the number of external references registered through the API.
25 : num_api_references_ = 0;
26 : if (isolate_->api_external_references() != nullptr) {
27 : while (isolate_->api_external_references()[num_api_references_] != 0) {
28 : num_api_references_++;
29 : }
30 : }
31 : #endif // DEBUG
32 294549 : CHECK_EQ(magic_number_,
33 : SerializedData::ComputeMagicNumber(external_reference_table_));
34 294549 : }
35 :
36 : template <class AllocatorT>
37 358835512 : bool Deserializer<AllocatorT>::IsLazyDeserializationEnabled() const {
38 717228867 : return FLAG_lazy_deserialization && !isolate()->serializer_enabled();
39 : }
40 :
41 : template <class AllocatorT>
42 294549 : Deserializer<AllocatorT>::~Deserializer() {
43 : #ifdef DEBUG
44 : // Do not perform checks if we aborted deserialization.
45 : if (source_.position() == 0) return;
46 : // Check that we only have padding bytes remaining.
47 : while (source_.HasMore()) DCHECK_EQ(kNop, source_.Get());
48 : // Check that we've fully used all reserved space.
49 : DCHECK(allocator()->ReservationsAreFullyUsed());
50 : #endif // DEBUG
51 589098 : }
52 :
53 : // This is called on the roots. It is the driver of the deserialization
54 : // process. It is also called on the body of each function.
55 : template <class AllocatorT>
56 162591098 : void Deserializer<AllocatorT>::VisitRootPointers(Root root, Object** start,
57 : Object** end) {
58 : // Builtins are deserialized in a separate pass by the BuiltinDeserializer.
59 325181161 : if (root == Root::kBuiltins) return;
60 :
61 : // The space must be new space. Any other space would cause ReadChunk to try
62 : // to update the remembered using nullptr as the address.
63 162536304 : ReadData(start, end, NEW_SPACE, nullptr);
64 : }
65 :
66 : template <class AllocatorT>
67 989424 : void Deserializer<AllocatorT>::Synchronize(
68 : VisitorSynchronization::SyncTag tag) {
69 : static const byte expected = kSynchronize;
70 989424 : CHECK_EQ(expected, source_.Get());
71 989424 : }
72 :
73 : template <class AllocatorT>
74 138819 : void Deserializer<AllocatorT>::DeserializeDeferredObjects() {
75 306860 : for (int code = source_.Get(); code != kSynchronize; code = source_.Get()) {
76 168041 : switch (code) {
77 : case kAlignmentPrefix:
78 : case kAlignmentPrefix + 1:
79 : case kAlignmentPrefix + 2: {
80 0 : int alignment = code - (SerializerDeserializer::kAlignmentPrefix - 1);
81 0 : allocator()->SetAlignment(static_cast<AllocationAlignment>(alignment));
82 : break;
83 : }
84 : default: {
85 168041 : int space = code & kSpaceMask;
86 : DCHECK_LE(space, kNumberOfSpaces);
87 : DCHECK_EQ(code - space, kNewObject);
88 168041 : HeapObject* object = GetBackReferencedObject(space);
89 168041 : int size = source_.GetInt() << kPointerSizeLog2;
90 168041 : Address obj_address = object->address();
91 168041 : Object** start = reinterpret_cast<Object**>(obj_address + kPointerSize);
92 168041 : Object** end = reinterpret_cast<Object**>(obj_address + size);
93 168041 : bool filled = ReadData(start, end, space, obj_address);
94 168041 : CHECK(filled);
95 : DCHECK(CanBeDeferred(object));
96 168041 : PostProcessNewObject(object, space);
97 : }
98 : }
99 : }
100 138819 : }
101 :
102 6315 : StringTableInsertionKey::StringTableInsertionKey(String* string)
103 15050 : : StringTableKey(ComputeHashField(string)), string_(string) {
104 : DCHECK(string->IsInternalizedString());
105 6315 : }
106 :
107 6643 : bool StringTableInsertionKey::IsMatch(Object* string) {
108 : // We know that all entries in a hash table had their hash keys created.
109 : // Use that knowledge to have fast failure.
110 13286 : if (Hash() != String::cast(string)->Hash()) return false;
111 : // We want to compare the content of two internalized strings here.
112 2425 : return string_->SlowEquals(String::cast(string));
113 : }
114 :
115 6315 : Handle<String> StringTableInsertionKey::AsHandle(Isolate* isolate) {
116 12630 : return handle(string_, isolate);
117 : }
118 :
119 0 : uint32_t StringTableInsertionKey::ComputeHashField(String* string) {
120 : // Make sure hash_field() is computed.
121 15050 : string->Hash();
122 0 : return string->hash_field();
123 : }
124 :
125 : template <class AllocatorT>
126 468086961 : HeapObject* Deserializer<AllocatorT>::PostProcessNewObject(HeapObject* obj,
127 : int space) {
128 468086961 : if (deserializing_user_code()) {
129 38470 : if (obj->IsString()) {
130 : String* string = String::cast(obj);
131 : // Uninitialize hash field as the hash seed may have changed.
132 : string->set_hash_field(String::kEmptyHashField);
133 9790 : if (string->IsInternalizedString()) {
134 : // Canonicalize the internalized string. If it already exists in the
135 : // string table, set it to forward to the existing one.
136 : StringTableInsertionKey key(string);
137 3910038 : String* canonical = StringTable::LookupKeyIfExists(isolate_, &key);
138 8735 : if (canonical == nullptr) {
139 12630 : new_internalized_strings_.push_back(handle(string));
140 6315 : return string;
141 : } else {
142 : string->SetForwardedInternalizedString(canonical);
143 2420 : return canonical;
144 : }
145 : }
146 28680 : } else if (obj->IsScript()) {
147 600 : new_scripts_.push_back(handle(Script::cast(obj)));
148 : } else {
149 : DCHECK(CanBeDeferred(obj));
150 : }
151 : }
152 468077855 : if (obj->IsAllocationSite()) {
153 : // Allocation sites are present in the snapshot, and must be linked into
154 : // a list at deserialization time.
155 : AllocationSite* site = AllocationSite::cast(obj);
156 : // TODO(mvstanton): consider treating the heap()->allocation_sites_list()
157 : // as a (weak) root. If this root is relocated correctly, this becomes
158 : // unnecessary.
159 0 : if (isolate_->heap()->allocation_sites_list() == Smi::kZero) {
160 0 : site->set_weak_next(isolate_->heap()->undefined_value());
161 : } else {
162 0 : site->set_weak_next(isolate_->heap()->allocation_sites_list());
163 : }
164 0 : isolate_->heap()->set_allocation_sites_list(site);
165 468077432 : } else if (obj->IsCode()) {
166 : // We flush all code pages after deserializing the startup snapshot. In that
167 : // case, we only need to remember code objects in the large object space.
168 : // When deserializing user code, remember each individual code object.
169 52800878 : if (deserializing_user_code() || space == LO_SPACE) {
170 420 : new_code_objects_.push_back(Code::cast(obj));
171 : }
172 415273820 : } else if (obj->IsAccessorInfo()) {
173 7802606 : if (isolate_->external_reference_redirector()) {
174 0 : accessor_infos_.push_back(AccessorInfo::cast(obj));
175 : }
176 411371036 : } else if (obj->IsExternalOneByteString()) {
177 : DCHECK(obj->map() == isolate_->heap()->native_source_string_map());
178 : ExternalOneByteString* string = ExternalOneByteString::cast(obj);
179 : DCHECK(string->is_short());
180 : string->set_resource(
181 : NativesExternalStringResource::DecodeForDeserialization(
182 549479 : string->resource()));
183 549478 : isolate_->heap()->RegisterExternalString(string);
184 410819390 : } else if (obj->IsJSArrayBuffer()) {
185 : JSArrayBuffer* buffer = JSArrayBuffer::cast(obj);
186 : // Only fixup for the off-heap case.
187 45 : if (buffer->backing_store() != nullptr) {
188 : Smi* store_index = reinterpret_cast<Smi*>(buffer->backing_store());
189 100 : void* backing_store = off_heap_backing_stores_[store_index->value()];
190 :
191 : buffer->set_backing_store(backing_store);
192 : buffer->set_allocation_base(backing_store);
193 30 : isolate_->heap()->RegisterNewArrayBuffer(buffer);
194 : }
195 410816945 : } else if (obj->IsFixedTypedArrayBase()) {
196 : FixedTypedArrayBase* fta = FixedTypedArrayBase::cast(obj);
197 : // Only fixup for the off-heap case.
198 494755 : if (fta->base_pointer() == nullptr) {
199 : Smi* store_index = reinterpret_cast<Smi*>(fta->external_pointer());
200 80 : void* backing_store = off_heap_backing_stores_[store_index->value()];
201 :
202 : fta->set_external_pointer(backing_store);
203 : }
204 : }
205 910684180 : if (FLAG_rehash_snapshot && can_rehash_ && !deserializing_user_code()) {
206 442629093 : if (obj->IsString()) {
207 : // Uninitialize hash field as we are going to reinitialize the hash seed.
208 : String* string = String::cast(obj);
209 : string->set_hash_field(String::kEmptyHashField);
210 377273853 : } else if (obj->IsTransitionArray() &&
211 : TransitionArray::cast(obj)->number_of_entries() > 1) {
212 0 : transition_arrays_.push_back(TransitionArray::cast(obj));
213 : }
214 : }
215 : // Check alignment.
216 : DCHECK_EQ(0, Heap::GetFillToAlign(obj->address(), obj->RequiredAlignment()));
217 468066260 : return obj;
218 : }
219 :
220 : template <class AllocatorT>
221 243351039 : int Deserializer<AllocatorT>::MaybeReplaceWithDeserializeLazy(int builtin_id) {
222 : DCHECK(Builtins::IsBuiltinId(builtin_id));
223 485940182 : return IsLazyDeserializationEnabled() && Builtins::IsLazy(builtin_id)
224 : ? Builtins::kDeserializeLazy
225 485940103 : : builtin_id;
226 : }
227 :
228 : template <class AllocatorT>
229 261755381 : HeapObject* Deserializer<AllocatorT>::GetBackReferencedObject(int space) {
230 : HeapObject* obj;
231 : SerializerReference back_reference =
232 261755381 : SerializerReference::FromBitfield(source_.GetInt());
233 :
234 261756047 : switch (space) {
235 : case LO_SPACE:
236 5 : obj = allocator()->GetLargeObject(back_reference.large_object_index());
237 5 : break;
238 : case MAP_SPACE:
239 18272642 : obj = allocator()->GetMap(back_reference.map_index());
240 18272642 : break;
241 : default:
242 243483400 : obj = allocator()->GetObject(static_cast<AllocationSpace>(space),
243 : back_reference.chunk_index(),
244 : back_reference.chunk_offset());
245 243483578 : break;
246 : }
247 :
248 261773010 : if (deserializing_user_code() && obj->IsInternalizedString()) {
249 : obj = String::cast(obj)->GetForwardedInternalizedString();
250 : }
251 :
252 : hot_objects_.Add(obj);
253 261756225 : return obj;
254 : }
255 :
256 : template <class AllocatorT>
257 138405 : void Deserializer<AllocatorT>::SortMapDescriptors() {
258 29473693 : for (const auto& address : allocator()->GetAllocatedMaps()) {
259 29196884 : Map* map = Map::cast(HeapObject::FromAddress(address));
260 29196884 : if (map->instance_descriptors()->number_of_descriptors() > 1) {
261 12774913 : map->instance_descriptors()->Sort();
262 : }
263 : }
264 138404 : }
265 :
266 : // This routine writes the new object into the pointer provided and then
267 : // returns true if the new object was in young space and false otherwise.
268 : // The reason for this strange interface is that otherwise the object is
269 : // written very late, which means the FreeSpace map is not set up by the
270 : // time we need to use it to mark the space at the end of a page free.
271 : template <class AllocatorT>
272 468084156 : void Deserializer<AllocatorT>::ReadObject(int space_number,
273 : Object** write_back) {
274 468084156 : const int size = source_.GetInt() << kObjectAlignmentBits;
275 :
276 : Address address =
277 468084297 : allocator()->Allocate(static_cast<AllocationSpace>(space_number), size);
278 468087462 : HeapObject* obj = HeapObject::FromAddress(address);
279 :
280 468087462 : isolate_->heap()->OnAllocationEvent(obj, size);
281 : Object** current = reinterpret_cast<Object**>(address);
282 468086777 : Object** limit = current + (size >> kPointerSizeLog2);
283 :
284 468086777 : if (ReadData(current, limit, space_number, address)) {
285 : // Only post process if object content has not been deferred.
286 467917624 : obj = PostProcessNewObject(obj, space_number);
287 : }
288 :
289 468074398 : Object* write_back_obj = obj;
290 : UnalignedCopy(write_back, &write_back_obj);
291 : #ifdef DEBUG
292 : if (obj->IsCode()) {
293 : DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE);
294 : } else {
295 : DCHECK(space_number != CODE_SPACE);
296 : }
297 : #endif // DEBUG
298 468074398 : }
299 :
300 : template <class AllocatorT>
301 25042012 : Object* Deserializer<AllocatorT>::ReadDataSingle() {
302 : Object* o;
303 : Object** start = &o;
304 : Object** end = start + 1;
305 : int source_space = NEW_SPACE;
306 : Address current_object = nullptr;
307 :
308 25042012 : CHECK(ReadData(start, end, source_space, current_object));
309 :
310 25042039 : return o;
311 : }
312 :
313 : template <class AllocatorT>
314 655690879 : bool Deserializer<AllocatorT>::ReadData(Object** current, Object** limit,
315 : int source_space,
316 : Address current_object_address) {
317 655690974 : Isolate* const isolate = isolate_;
318 : // Write barrier support costs around 1% in startup time. In fact there
319 : // are no new space objects in current boot snapshots, so it's not needed,
320 : // but that may change.
321 : bool write_barrier_needed =
322 : (current_object_address != nullptr && source_space != NEW_SPACE &&
323 655690879 : source_space != CODE_SPACE);
324 5191470237 : while (current < limit) {
325 : byte data = source_.Get();
326 3880130060 : switch (data) {
327 : #define CASE_STATEMENT(where, how, within, space_number) \
328 : case where + how + within + space_number: \
329 : STATIC_ASSERT((where & ~kWhereMask) == 0); \
330 : STATIC_ASSERT((how & ~kHowToCodeMask) == 0); \
331 : STATIC_ASSERT((within & ~kWhereToPointMask) == 0); \
332 : STATIC_ASSERT((space_number & ~kSpaceMask) == 0);
333 :
334 : #define CASE_BODY(where, how, within, space_number_if_any) \
335 : current = ReadDataCase<where, how, within, space_number_if_any>( \
336 : isolate, current, current_object_address, data, write_barrier_needed); \
337 : break;
338 :
339 : // This generates a case and a body for the new space (which has to do extra
340 : // write barrier handling) and handles the other spaces with fall-through cases
341 : // and one body.
342 : #define ALL_SPACES(where, how, within) \
343 : CASE_STATEMENT(where, how, within, NEW_SPACE) \
344 : CASE_BODY(where, how, within, NEW_SPACE) \
345 : CASE_STATEMENT(where, how, within, OLD_SPACE) \
346 : CASE_STATEMENT(where, how, within, CODE_SPACE) \
347 : CASE_STATEMENT(where, how, within, MAP_SPACE) \
348 : CASE_STATEMENT(where, how, within, LO_SPACE) \
349 : CASE_BODY(where, how, within, kAnyOldSpace)
350 :
351 : #define FOUR_CASES(byte_code) \
352 : case byte_code: \
353 : case byte_code + 1: \
354 : case byte_code + 2: \
355 : case byte_code + 3:
356 :
357 : #define SIXTEEN_CASES(byte_code) \
358 : FOUR_CASES(byte_code) \
359 : FOUR_CASES(byte_code + 4) \
360 : FOUR_CASES(byte_code + 8) \
361 : FOUR_CASES(byte_code + 12)
362 :
363 : #define SINGLE_CASE(where, how, within, space) \
364 : CASE_STATEMENT(where, how, within, space) \
365 : CASE_BODY(where, how, within, space)
366 :
367 : // Deserialize a new object and write a pointer to it to the current
368 : // object.
369 1357 : ALL_SPACES(kNewObject, kPlain, kStartOfObject)
370 : // Deserialize a new code object and write a pointer to its first
371 : // instruction to the current code object.
372 0 : ALL_SPACES(kNewObject, kFromCode, kInnerPointer)
373 : // Find a recently deserialized object using its offset from the current
374 : // allocation point and write a pointer to it to the current object.
375 0 : ALL_SPACES(kBackref, kPlain, kStartOfObject)
376 0 : ALL_SPACES(kBackrefWithSkip, kPlain, kStartOfObject)
377 : #if V8_CODE_EMBEDS_OBJECT_POINTER
378 : // Deserialize a new object from pointer found in code and write
379 : // a pointer to it to the current object. Required only for MIPS, PPC, ARM
380 : // or S390 with embedded constant pool, and omitted on the other
381 : // architectures because it is fully unrolled and would cause bloat.
382 : ALL_SPACES(kNewObject, kFromCode, kStartOfObject)
383 : // Find a recently deserialized code object using its offset from the
384 : // current allocation point and write a pointer to it to the current
385 : // object. Required only for MIPS, PPC, ARM or S390 with embedded
386 : // constant pool.
387 : ALL_SPACES(kBackref, kFromCode, kStartOfObject)
388 : ALL_SPACES(kBackrefWithSkip, kFromCode, kStartOfObject)
389 : #endif
390 : // Find a recently deserialized code object using its offset from the
391 : // current allocation point and write a pointer to its first instruction
392 : // to the current code object or the instruction pointer in a function
393 : // object.
394 0 : ALL_SPACES(kBackref, kFromCode, kInnerPointer)
395 0 : ALL_SPACES(kBackrefWithSkip, kFromCode, kInnerPointer)
396 : // Find an object in the roots array and write a pointer to it to the
397 : // current object.
398 134386626 : SINGLE_CASE(kRootArray, kPlain, kStartOfObject, 0)
399 : #if V8_CODE_EMBEDS_OBJECT_POINTER
400 : // Find an object in the roots array and write a pointer to it to in code.
401 : SINGLE_CASE(kRootArray, kFromCode, kStartOfObject, 0)
402 : #endif
403 : // Find an object in the partial snapshots cache and write a pointer to it
404 : // to the current object.
405 157115633 : SINGLE_CASE(kPartialSnapshotCache, kPlain, kStartOfObject, 0)
406 0 : SINGLE_CASE(kPartialSnapshotCache, kFromCode, kStartOfObject, 0)
407 50217287 : SINGLE_CASE(kPartialSnapshotCache, kFromCode, kInnerPointer, 0)
408 : // Find an external reference and write a pointer to it to the current
409 : // object.
410 184522470 : SINGLE_CASE(kExternalReference, kPlain, kStartOfObject, 0)
411 : // Find an external reference and write a pointer to it in the current
412 : // code object.
413 0 : SINGLE_CASE(kExternalReference, kFromCode, kStartOfObject, 0)
414 : // Find an object in the attached references and write a pointer to it to
415 : // the current object.
416 251053 : SINGLE_CASE(kAttachedReference, kPlain, kStartOfObject, 0)
417 0 : SINGLE_CASE(kAttachedReference, kFromCode, kStartOfObject, 0)
418 60 : SINGLE_CASE(kAttachedReference, kFromCode, kInnerPointer, 0)
419 : // Find a builtin and write a pointer to it to the current object.
420 152605724 : SINGLE_CASE(kBuiltin, kPlain, kStartOfObject, 0)
421 0 : SINGLE_CASE(kBuiltin, kFromCode, kStartOfObject, 0)
422 90746897 : SINGLE_CASE(kBuiltin, kFromCode, kInnerPointer, 0)
423 :
424 : #undef CASE_STATEMENT
425 : #undef CASE_BODY
426 : #undef ALL_SPACES
427 :
428 : case kSkip: {
429 198332003 : int size = source_.GetInt();
430 198331942 : current = reinterpret_cast<Object**>(
431 : reinterpret_cast<intptr_t>(current) + size);
432 198331942 : break;
433 : }
434 :
435 : case kInternalReferenceEncoded:
436 : case kInternalReference: {
437 : // Internal reference address is not encoded via skip, but by offset
438 : // from code entry.
439 35924338 : int pc_offset = source_.GetInt();
440 35924339 : int target_offset = source_.GetInt();
441 : Code* code =
442 : Code::cast(HeapObject::FromAddress(current_object_address));
443 : DCHECK(0 <= pc_offset && pc_offset <= code->instruction_size());
444 : DCHECK(0 <= target_offset && target_offset <= code->instruction_size());
445 35924336 : Address pc = code->entry() + pc_offset;
446 35924336 : Address target = code->entry() + target_offset;
447 : Assembler::deserialization_set_target_internal_reference_at(
448 : isolate, pc, target, data == kInternalReference
449 : ? RelocInfo::INTERNAL_REFERENCE
450 : : RelocInfo::INTERNAL_REFERENCE_ENCODED);
451 : break;
452 : }
453 :
454 : case kNop:
455 : break;
456 :
457 : case kNextChunk: {
458 : int space = source_.Get();
459 55 : allocator()->MoveToNextChunk(static_cast<AllocationSpace>(space));
460 55 : break;
461 : }
462 :
463 : case kDeferred: {
464 : // Deferred can only occur right after the heap object header.
465 : DCHECK(current == reinterpret_cast<Object**>(current_object_address +
466 : kPointerSize));
467 168041 : HeapObject* obj = HeapObject::FromAddress(current_object_address);
468 : // If the deferred object is a map, its instance type may be used
469 : // during deserialization. Initialize it with a temporary value.
470 168041 : if (obj->IsMap()) Map::cast(obj)->set_instance_type(FILLER_TYPE);
471 : current = limit;
472 : return false;
473 : }
474 :
475 : case kSynchronize:
476 : // If we get here then that indicates that you have a mismatch between
477 : // the number of GC roots when serializing and deserializing.
478 0 : CHECK(false);
479 : break;
480 :
481 : // Deserialize raw data of variable length.
482 : case kVariableRawData: {
483 1099664 : int size_in_bytes = source_.GetInt();
484 : byte* raw_data_out = reinterpret_cast<byte*>(current);
485 : source_.CopyRaw(raw_data_out, size_in_bytes);
486 1099663 : current = reinterpret_cast<Object**>(
487 : reinterpret_cast<intptr_t>(current) + size_in_bytes);
488 1099663 : break;
489 : }
490 :
491 : // Deserialize raw code directly into the body of the code object.
492 : // Do not move current.
493 : case kVariableRawCode: {
494 52800885 : int size_in_bytes = source_.GetInt();
495 : source_.CopyRaw(current_object_address + Code::kDataStart,
496 52800623 : size_in_bytes);
497 : break;
498 : }
499 :
500 : case kVariableRepeat: {
501 1296716 : int repeats = source_.GetInt();
502 1296717 : Object* object = current[-1];
503 : DCHECK(!isolate->heap()->InNewSpace(object));
504 233817304 : for (int i = 0; i < repeats; i++) UnalignedCopy(current++, &object);
505 : break;
506 : }
507 :
508 : case kOffHeapBackingStore: {
509 30 : int byte_length = source_.GetInt();
510 : byte* backing_store = static_cast<byte*>(
511 : isolate->array_buffer_allocator()->AllocateUninitialized(
512 30 : byte_length));
513 30 : CHECK_NOT_NULL(backing_store);
514 : source_.CopyRaw(backing_store, byte_length);
515 30 : off_heap_backing_stores_.push_back(backing_store);
516 : break;
517 : }
518 :
519 : case kApiReference: {
520 65 : int skip = source_.GetInt();
521 65 : current = reinterpret_cast<Object**>(
522 : reinterpret_cast<Address>(current) + skip);
523 65 : uint32_t reference_id = static_cast<uint32_t>(source_.GetInt());
524 : DCHECK_WITH_MSG(reference_id < num_api_references_,
525 : "too few external references provided through the API");
526 : Address address = reinterpret_cast<Address>(
527 65 : isolate->api_external_references()[reference_id]);
528 : memcpy(current, &address, kPointerSize);
529 65 : current++;
530 : break;
531 : }
532 :
533 : case kAlignmentPrefix:
534 : case kAlignmentPrefix + 1:
535 : case kAlignmentPrefix + 2: {
536 0 : int alignment = data - (SerializerDeserializer::kAlignmentPrefix - 1);
537 0 : allocator()->SetAlignment(static_cast<AllocationAlignment>(alignment));
538 : break;
539 : }
540 :
541 : STATIC_ASSERT(kNumberOfRootArrayConstants == Heap::kOldSpaceRoots);
542 : STATIC_ASSERT(kNumberOfRootArrayConstants == 32);
543 : SIXTEEN_CASES(kRootArrayConstantsWithSkip)
544 : SIXTEEN_CASES(kRootArrayConstantsWithSkip + 16) {
545 54968 : int skip = source_.GetInt();
546 54968 : current = reinterpret_cast<Object**>(
547 : reinterpret_cast<intptr_t>(current) + skip);
548 : // Fall through.
549 : }
550 :
551 : SIXTEEN_CASES(kRootArrayConstants)
552 : SIXTEEN_CASES(kRootArrayConstants + 16) {
553 952134438 : int id = data & kRootArrayConstantsMask;
554 : Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(id);
555 952134438 : Object* object = isolate->heap()->root(root_index);
556 : DCHECK(!isolate->heap()->InNewSpace(object));
557 952134438 : UnalignedCopy(current++, &object);
558 : break;
559 : }
560 :
561 : STATIC_ASSERT(kNumberOfHotObjects == 8);
562 : FOUR_CASES(kHotObjectWithSkip)
563 : FOUR_CASES(kHotObjectWithSkip + 4) {
564 0 : int skip = source_.GetInt();
565 0 : current = reinterpret_cast<Object**>(
566 : reinterpret_cast<Address>(current) + skip);
567 : // Fall through.
568 : }
569 :
570 : FOUR_CASES(kHotObject)
571 : FOUR_CASES(kHotObject + 4) {
572 365508062 : int index = data & kHotObjectMask;
573 365508062 : Object* hot_object = hot_objects_.Get(index);
574 : UnalignedCopy(current, &hot_object);
575 691632048 : if (write_barrier_needed && isolate->heap()->InNewSpace(hot_object)) {
576 : Address current_address = reinterpret_cast<Address>(current);
577 0 : isolate->heap()->RecordWrite(
578 0 : HeapObject::FromAddress(current_object_address),
579 0 : reinterpret_cast<Object**>(current_address), hot_object);
580 : }
581 366030641 : current++;
582 : break;
583 : }
584 :
585 : // Deserialize raw data of fixed length from 1 to 32 words.
586 : STATIC_ASSERT(kNumberOfFixedRawData == 32);
587 : SIXTEEN_CASES(kFixedRawData)
588 : SIXTEEN_CASES(kFixedRawData + 16) {
589 : byte* raw_data_out = reinterpret_cast<byte*>(current);
590 573113013 : int size_in_bytes = (data - kFixedRawDataStart) << kPointerSizeLog2;
591 : source_.CopyRaw(raw_data_out, size_in_bytes);
592 573113013 : current = reinterpret_cast<Object**>(raw_data_out + size_in_bytes);
593 573113013 : break;
594 : }
595 :
596 : STATIC_ASSERT(kNumberOfFixedRepeat == 16);
597 : SIXTEEN_CASES(kFixedRepeat) {
598 200031592 : int repeats = data - kFixedRepeatStart;
599 : Object* object;
600 200031592 : UnalignedCopy(&object, current - 1);
601 : DCHECK(!isolate->heap()->InNewSpace(object));
602 504386313 : for (int i = 0; i < repeats; i++) UnalignedCopy(current++, &object);
603 : break;
604 : }
605 :
606 : #undef SIXTEEN_CASES
607 : #undef FOUR_CASES
608 : #undef SINGLE_CASE
609 :
610 : default:
611 0 : CHECK(false);
612 : }
613 : }
614 655649298 : CHECK_EQ(limit, current);
615 : return true;
616 : }
617 :
618 : template <class AllocatorT>
619 : template <int where, int how, int within, int space_number_if_any>
620 1499517773 : Object** Deserializer<AllocatorT>::ReadDataCase(Isolate* isolate,
621 : Object** current,
622 : Address current_object_address,
623 : byte data,
624 : bool write_barrier_needed) {
625 : bool emit_write_barrier = false;
626 : bool current_was_incremented = false;
627 : int space_number = space_number_if_any == kAnyOldSpace ? (data & kSpaceMask)
628 729670631 : : space_number_if_any;
629 : if (where == kNewObject && how == kPlain && within == kStartOfObject) {
630 468028426 : ReadObject(space_number, current);
631 468018129 : emit_write_barrier = (space_number == NEW_SPACE);
632 : } else {
633 848749729 : Object* new_object = nullptr; /* May not be a real Object pointer. */
634 : if (where == kNewObject) {
635 54988 : ReadObject(space_number, &new_object);
636 : } else if (where == kBackref) {
637 219318496 : emit_write_barrier = (space_number == NEW_SPACE);
638 219318496 : new_object = GetBackReferencedObject(data & kSpaceMask);
639 : } else if (where == kBackrefWithSkip) {
640 42270078 : int skip = source_.GetInt();
641 42270066 : current =
642 : reinterpret_cast<Object**>(reinterpret_cast<Address>(current) + skip);
643 42270066 : emit_write_barrier = (space_number == NEW_SPACE);
644 42270066 : new_object = GetBackReferencedObject(data & kSpaceMask);
645 : } else if (where == kRootArray) {
646 134386625 : int id = source_.GetInt();
647 : Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(id);
648 134386628 : new_object = isolate->heap()->root(root_index);
649 : emit_write_barrier = isolate->heap()->InNewSpace(new_object);
650 : hot_objects_.Add(HeapObject::cast(new_object));
651 : } else if (where == kPartialSnapshotCache) {
652 207332941 : int cache_index = source_.GetInt();
653 414665828 : new_object = isolate->partial_snapshot_cache()->at(cache_index);
654 : emit_write_barrier = isolate->heap()->InNewSpace(new_object);
655 : } else if (where == kExternalReference) {
656 184522493 : int skip = source_.GetInt();
657 184522327 : current =
658 : reinterpret_cast<Object**>(reinterpret_cast<Address>(current) + skip);
659 184522327 : uint32_t reference_id = static_cast<uint32_t>(source_.GetInt());
660 184522267 : Address address = external_reference_table_->address(reference_id);
661 184522267 : new_object = reinterpret_cast<Object*>(address);
662 : } else if (where == kAttachedReference) {
663 251113 : int index = source_.GetInt();
664 502166 : new_object = *attached_objects_[index];
665 : emit_write_barrier = isolate->heap()->InNewSpace(new_object);
666 : } else {
667 : DCHECK_EQ(where, kBuiltin);
668 243352613 : int builtin_id = MaybeReplaceWithDeserializeLazy(source_.GetInt());
669 152605415 : new_object = isolate->builtins()->builtin(builtin_id);
670 : emit_write_barrier = false;
671 : }
672 : if (within == kInnerPointer) {
673 : DCHECK_EQ(how, kFromCode);
674 : if (where == kBuiltin) {
675 : // At this point, new_object may still be uninitialized, thus the
676 : // unchecked Code cast.
677 : new_object = reinterpret_cast<Object*>(
678 : reinterpret_cast<Code*>(new_object)->instruction_start());
679 92102726 : } else if (new_object->IsCode()) {
680 92047738 : new_object = reinterpret_cast<Object*>(
681 54988 : Code::cast(new_object)->instruction_start());
682 : } else {
683 0 : Cell* cell = Cell::cast(new_object);
684 0 : new_object = reinterpret_cast<Object*>(cell->ValueAddress());
685 : }
686 : }
687 : if (how == kFromCode) {
688 : Address location_of_branch_data = reinterpret_cast<Address>(current);
689 : Assembler::deserialization_set_special_target_at(
690 : isolate, location_of_branch_data,
691 : Code::cast(HeapObject::FromAddress(current_object_address)),
692 90801854 : reinterpret_cast<Address>(new_object));
693 : location_of_branch_data += Assembler::kSpecialTargetSize;
694 91992769 : current = reinterpret_cast<Object**>(location_of_branch_data);
695 : current_was_incremented = true;
696 : } else {
697 : UnalignedCopy(current, &new_object);
698 : }
699 : }
700 1071579020 : if (emit_write_barrier && write_barrier_needed) {
701 : Address current_address = reinterpret_cast<Address>(current);
702 : SLOW_DCHECK(isolate->heap()->ContainsSlow(current_object_address));
703 251770 : isolate->heap()->RecordWrite(
704 251770 : HeapObject::FromAddress(current_object_address),
705 : reinterpret_cast<Object**>(current_address),
706 503540 : *reinterpret_cast<Object**>(current_address));
707 : }
708 : if (!current_was_incremented) {
709 : current++;
710 : }
711 :
712 1499508571 : return current;
713 : }
714 :
715 : // Explicit instantiation.
716 : template class Deserializer<BuiltinDeserializerAllocator>;
717 : template class Deserializer<DefaultDeserializerAllocator>;
718 :
719 : } // namespace internal
720 : } // namespace v8
|