LCOV - code coverage report
Current view: top level - src/snapshot - deserializer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 194 224 86.6 %
Date: 2017-10-20 Functions: 43 80 53.8 %

          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

Generated by: LCOV version 1.10