LCOV - code coverage report
Current view: top level - src/snapshot - deserializer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 239 266 89.8 %
Date: 2019-04-19 Functions: 30 37 81.1 %

          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/heap/heap-inl.h"
       9             : #include "src/heap/heap-write-barrier-inl.h"
      10             : #include "src/heap/read-only-heap.h"
      11             : #include "src/interpreter/interpreter.h"
      12             : #include "src/isolate.h"
      13             : #include "src/log.h"
      14             : #include "src/objects-body-descriptors-inl.h"
      15             : #include "src/objects/api-callbacks.h"
      16             : #include "src/objects/cell-inl.h"
      17             : #include "src/objects/hash-table.h"
      18             : #include "src/objects/js-array-buffer-inl.h"
      19             : #include "src/objects/js-array-inl.h"
      20             : #include "src/objects/maybe-object.h"
      21             : #include "src/objects/slots.h"
      22             : #include "src/objects/smi.h"
      23             : #include "src/objects/string.h"
      24             : #include "src/roots.h"
      25             : #include "src/snapshot/natives.h"
      26             : #include "src/snapshot/snapshot.h"
      27             : #include "src/tracing/trace-event.h"
      28             : #include "src/tracing/traced-value.h"
      29             : 
      30             : namespace v8 {
      31             : namespace internal {
      32             : 
      33             : template <typename TSlot>
      34             : TSlot Deserializer::Write(TSlot dest, MaybeObject value) {
      35             :   DCHECK(!allocator()->next_reference_is_weak());
      36             :   dest.store(value);
      37             :   return dest + 1;
      38             : }
      39             : 
      40             : template <typename TSlot>
      41             : TSlot Deserializer::WriteAddress(TSlot dest, Address value) {
      42             :   DCHECK(!allocator()->next_reference_is_weak());
      43             :   memcpy(dest.ToVoidPtr(), &value, kSystemPointerSize);
      44             :   STATIC_ASSERT(IsAligned(kSystemPointerSize, TSlot::kSlotDataSize));
      45             :   return dest + (kSystemPointerSize / TSlot::kSlotDataSize);
      46             : }
      47             : 
      48      216656 : void Deserializer::Initialize(Isolate* isolate) {
      49             :   DCHECK_NULL(isolate_);
      50             :   DCHECK_NOT_NULL(isolate);
      51      216656 :   isolate_ = isolate;
      52             :   allocator()->Initialize(isolate->heap());
      53             : 
      54             : #ifdef DEBUG
      55             :   // The read-only deserializer is run by read-only heap set-up before the heap
      56             :   // is fully set up. External reference table relies on a few parts of this
      57             :   // set-up (like old-space), so it may be uninitialized at this point.
      58             :   if (isolate->isolate_data()->external_reference_table()->is_initialized()) {
      59             :     // Count the number of external references registered through the API.
      60             :     num_api_references_ = 0;
      61             :     if (isolate_->api_external_references() != nullptr) {
      62             :       while (isolate_->api_external_references()[num_api_references_] != 0) {
      63             :         num_api_references_++;
      64             :       }
      65             :     }
      66             :   }
      67             : #endif  // DEBUG
      68      216656 :   CHECK_EQ(magic_number_, SerializedData::kMagicNumber);
      69      216656 : }
      70             : 
      71      216520 : void Deserializer::Rehash() {
      72             :   DCHECK(can_rehash() || deserializing_user_code());
      73    46765002 :   for (HeapObject item : to_rehash_) {
      74    93096970 :     item->RehashBasedOnMap(ReadOnlyRoots(isolate_));
      75             :   }
      76      216517 : }
      77             : 
      78      649971 : Deserializer::~Deserializer() {
      79             : #ifdef DEBUG
      80             :   // Do not perform checks if we aborted deserialization.
      81             :   if (source_.position() == 0) return;
      82             :   // Check that we only have padding bytes remaining.
      83             :   while (source_.HasMore()) DCHECK_EQ(kNop, source_.Get());
      84             :   // Check that we've fully used all reserved space.
      85             :   DCHECK(allocator()->ReservationsAreFullyUsed());
      86             : #endif  // DEBUG
      87      216657 : }
      88             : 
      89             : // This is called on the roots.  It is the driver of the deserialization
      90             : // process.  It is also called on the body of each function.
      91   203849767 : void Deserializer::VisitRootPointers(Root root, const char* description,
      92             :                                      FullObjectSlot start, FullObjectSlot end) {
      93             :   // We are reading to a location outside of JS heap, so pass NEW_SPACE to
      94             :   // avoid triggering write barriers.
      95   203849999 :   ReadData(FullMaybeObjectSlot(start), FullMaybeObjectSlot(end), NEW_SPACE,
      96   203849767 :            kNullAddress);
      97   203849999 : }
      98             : 
      99     1060562 : void Deserializer::Synchronize(VisitorSynchronization::SyncTag tag) {
     100             :   static const byte expected = kSynchronize;
     101     1060562 :   CHECK_EQ(expected, source_.Get());
     102     1060562 : }
     103             : 
     104      216656 : void Deserializer::DeserializeDeferredObjects() {
     105      406945 :   for (int code = source_.Get(); code != kSynchronize; code = source_.Get()) {
     106      190288 :     switch (code) {
     107             :       case kAlignmentPrefix:
     108             :       case kAlignmentPrefix + 1:
     109             :       case kAlignmentPrefix + 2: {
     110           0 :         int alignment = code - (SerializerDeserializer::kAlignmentPrefix - 1);
     111           0 :         allocator()->SetAlignment(static_cast<AllocationAlignment>(alignment));
     112             :         break;
     113             :       }
     114             :       default: {
     115      190288 :         int space = code & kSpaceMask;
     116             :         DCHECK_LE(space, kNumberOfSpaces);
     117             :         DCHECK_EQ(code - space, kNewObject);
     118      190288 :         HeapObject object = GetBackReferencedObject(space);
     119      190288 :         int size = source_.GetInt() << kTaggedSizeLog2;
     120             :         Address obj_address = object->address();
     121             :         // Object's map is already initialized, now read the rest.
     122      190288 :         MaybeObjectSlot start(obj_address + kTaggedSize);
     123      190288 :         MaybeObjectSlot end(obj_address + size);
     124      190288 :         bool filled = ReadData(start, end, space, obj_address);
     125      190289 :         CHECK(filled);
     126             :         DCHECK(CanBeDeferred(object));
     127      190289 :         PostProcessNewObject(object, space);
     128             :       }
     129             :     }
     130             :   }
     131      216657 : }
     132             : 
     133           0 : void Deserializer::LogNewObjectEvents() {
     134             :   {
     135             :     // {new_maps_} and {new_code_objects_} are vectors containing raw
     136             :     // pointers, hence there should be no GC happening.
     137             :     DisallowHeapAllocation no_gc;
     138             :     // Issue code events for newly deserialized code objects.
     139           0 :     LOG_CODE_EVENT(isolate_, LogCodeObjects());
     140             :   }
     141           0 :   LOG_CODE_EVENT(isolate_, LogCompiledFunctions());
     142           0 :   LogNewMapEvents();
     143           0 : }
     144             : 
     145       91885 : void Deserializer::LogNewMapEvents() {
     146             :   DisallowHeapAllocation no_gc;
     147       98110 :   for (Map map : new_maps()) {
     148             :     DCHECK(FLAG_trace_maps);
     149        6225 :     LOG(isolate_, MapCreate(map));
     150        6225 :     LOG(isolate_, MapDetails(map));
     151             :   }
     152       91885 : }
     153             : 
     154      187591 : void Deserializer::LogScriptEvents(Script script) {
     155             :   DisallowHeapAllocation no_gc;
     156      187768 :   LOG(isolate_,
     157             :       ScriptEvent(Logger::ScriptEventType::kDeserialize, script->id()));
     158      187591 :   LOG(isolate_, ScriptDetails(script));
     159      375182 :   TRACE_EVENT_OBJECT_CREATED_WITH_ID(
     160             :       TRACE_DISABLED_BY_DEFAULT("v8.compile"), "Script",
     161             :       TRACE_ID_WITH_SCOPE("v8::internal::Script", script->id()));
     162      375182 :   TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
     163             :       TRACE_DISABLED_BY_DEFAULT("v8.compile"), "Script",
     164             :       TRACE_ID_WITH_SCOPE("v8::internal::Script", script->id()),
     165             :       script->ToTracedValue());
     166      187591 : }
     167             : 
     168        9837 : StringTableInsertionKey::StringTableInsertionKey(String string)
     169        9837 :     : StringTableKey(ComputeHashField(string)), string_(string) {
     170             :   DCHECK(string->IsInternalizedString());
     171        9837 : }
     172             : 
     173        4842 : bool StringTableInsertionKey::IsMatch(Object string) {
     174             :   // We know that all entries in a hash table had their hash keys created.
     175             :   // Use that knowledge to have fast failure.
     176        4842 :   if (Hash() != String::cast(string)->Hash()) return false;
     177             :   // We want to compare the content of two internalized strings here.
     178         558 :   return string_->SlowEquals(String::cast(string));
     179             : }
     180             : 
     181        4642 : Handle<String> StringTableInsertionKey::AsHandle(Isolate* isolate) {
     182        4642 :   return handle(string_, isolate);
     183             : }
     184             : 
     185           0 : uint32_t StringTableInsertionKey::ComputeHashField(String string) {
     186             :   // Make sure hash_field() is computed.
     187        9837 :   string->Hash();
     188           0 :   return string->hash_field();
     189             : }
     190             : 
     191   441837983 : HeapObject Deserializer::PostProcessNewObject(HeapObject obj, int space) {
     192   441837983 :   if ((FLAG_rehash_snapshot && can_rehash_) || deserializing_user_code()) {
     193   441574149 :     if (obj->IsString()) {
     194             :       // Uninitialize hash field as we need to recompute the hash.
     195             :       String string = String::cast(obj);
     196             :       string->set_hash_field(String::kEmptyHashField);
     197             :       // Rehash strings before read-only space is sealed. Strings outside
     198             :       // read-only space are rehashed lazily. (e.g. when rehashing dictionaries)
     199    59711760 :       if (space == RO_SPACE) {
     200    31971774 :         to_rehash_.push_back(obj);
     201             :       }
     202   381862389 :     } else if (obj->NeedsRehashing()) {
     203    14577042 :       to_rehash_.push_back(obj);
     204             :     }
     205             :   }
     206             : 
     207   441854981 :   if (deserializing_user_code()) {
     208       16558 :     if (obj->IsString()) {
     209             :       String string = String::cast(obj);
     210        5582 :       if (string->IsInternalizedString()) {
     211             :         // Canonicalize the internalized string. If it already exists in the
     212             :         // string table, set it to forward to the existing one.
     213        5195 :         StringTableInsertionKey key(string);
     214             :         String canonical =
     215        5195 :             StringTable::ForwardStringIfExists(isolate_, &key, string);
     216             : 
     217        5195 :         if (!canonical.is_null()) return canonical;
     218             : 
     219       13926 :         new_internalized_strings_.push_back(handle(string, isolate_));
     220        4642 :         return string;
     221             :       }
     222       10976 :     } else if (obj->IsScript()) {
     223         627 :       new_scripts_.push_back(handle(Script::cast(obj), isolate_));
     224       10767 :     } else if (obj->IsAllocationSite()) {
     225             :       // We should link new allocation sites, but we can't do this immediately
     226             :       // because |AllocationSite::HasWeakNext()| internally accesses
     227             :       // |Heap::roots_| that may not have been initialized yet. So defer this to
     228             :       // |ObjectDeserializer::CommitPostProcessedObjects()|.
     229           0 :       new_allocation_sites_.push_back(AllocationSite::cast(obj));
     230             :     } else {
     231             :       DCHECK(CanBeDeferred(obj));
     232             :     }
     233             :   }
     234   441849786 :   if (obj->IsScript()) {
     235      187382 :     LogScriptEvents(Script::cast(obj));
     236   441662404 :   } else if (obj->IsCode()) {
     237             :     // We flush all code pages after deserializing the startup snapshot.
     238             :     // Hence we only remember each individual code object when deserializing
     239             :     // user code.
     240    95121649 :     if (deserializing_user_code() || space == LO_SPACE) {
     241           0 :       new_code_objects_.push_back(Code::cast(obj));
     242             :     }
     243   346635153 :   } else if (FLAG_trace_maps && obj->IsMap()) {
     244             :     // Keep track of all seen Maps to log them later since they might be only
     245             :     // partially initialized at this point.
     246       17686 :     new_maps_.push_back(Map::cast(obj));
     247   346531912 :   } else if (obj->IsAccessorInfo()) {
     248             : #ifdef USE_SIMULATOR
     249             :     accessor_infos_.push_back(AccessorInfo::cast(obj));
     250             : #endif
     251   345846176 :   } else if (obj->IsCallHandlerInfo()) {
     252             : #ifdef USE_SIMULATOR
     253             :     call_handler_infos_.push_back(CallHandlerInfo::cast(obj));
     254             : #endif
     255   345846534 :   } else if (obj->IsExternalString()) {
     256      124722 :     if (obj->map() == ReadOnlyRoots(isolate_).native_source_string_map()) {
     257       62341 :       ExternalOneByteString string = ExternalOneByteString::cast(obj);
     258             :       DCHECK(string->is_uncached());
     259       62341 :       string->SetResource(
     260       62341 :           isolate_, NativesExternalStringResource::DecodeForDeserialization(
     261       62341 :                         string->resource()));
     262             :     } else {
     263          20 :       ExternalString string = ExternalString::cast(obj);
     264             :       uint32_t index = string->resource_as_uint32();
     265             :       Address address =
     266          20 :           static_cast<Address>(isolate_->api_external_references()[index]);
     267          20 :       string->set_address_as_resource(address);
     268          20 :       isolate_->heap()->UpdateExternalString(string, 0,
     269          40 :                                              string->ExternalPayloadSize());
     270             :     }
     271       62361 :     isolate_->heap()->RegisterExternalString(String::cast(obj));
     272   345784173 :   } else if (obj->IsJSTypedArray()) {
     273             :     JSTypedArray typed_array = JSTypedArray::cast(obj);
     274          65 :     CHECK_LE(typed_array->byte_offset(), Smi::kMaxValue);
     275          65 :     int32_t byte_offset = static_cast<int32_t>(typed_array->byte_offset());
     276          65 :     if (byte_offset > 0) {
     277             :       FixedTypedArrayBase elements =
     278             :           FixedTypedArrayBase::cast(typed_array->elements());
     279             :       // Must be off-heap layout.
     280             :       DCHECK(!typed_array->is_on_heap());
     281             : 
     282             :       void* pointer_with_offset = reinterpret_cast<void*>(
     283           5 :           reinterpret_cast<intptr_t>(elements->external_pointer()) +
     284             :           byte_offset);
     285             :       elements->set_external_pointer(pointer_with_offset);
     286             :     }
     287   345784108 :   } else if (obj->IsJSArrayBuffer()) {
     288             :     JSArrayBuffer buffer = JSArrayBuffer::cast(obj);
     289             :     // Only fixup for the off-heap case.
     290          55 :     if (buffer->backing_store() != nullptr) {
     291             :       Smi store_index(reinterpret_cast<Address>(buffer->backing_store()));
     292          70 :       void* backing_store = off_heap_backing_stores_[store_index->value()];
     293             : 
     294             :       buffer->set_backing_store(backing_store);
     295          70 :       isolate_->heap()->RegisterNewArrayBuffer(buffer);
     296             :     }
     297   345784053 :   } else if (obj->IsFixedTypedArrayBase()) {
     298             :     FixedTypedArrayBase fta = FixedTypedArrayBase::cast(obj);
     299             :     // Only fixup for the off-heap case.
     300      686311 :     if (fta->base_pointer() == Smi::kZero) {
     301             :       Smi store_index(reinterpret_cast<Address>(fta->external_pointer()));
     302         100 :       void* backing_store = off_heap_backing_stores_[store_index->value()];
     303             :       fta->set_external_pointer(backing_store);
     304             :     }
     305   345097742 :   } else if (obj->IsBytecodeArray()) {
     306             :     // TODO(mythria): Remove these once we store the default values for these
     307             :     // fields in the serializer.
     308             :     BytecodeArray bytecode_array = BytecodeArray::cast(obj);
     309             :     bytecode_array->set_osr_loop_nesting_level(0);
     310             :   }
     311             : #ifdef DEBUG
     312             :   if (obj->IsDescriptorArray()) {
     313             :     DescriptorArray descriptor_array = DescriptorArray::cast(obj);
     314             :     DCHECK_EQ(0, descriptor_array->raw_number_of_marked_descriptors());
     315             :   }
     316             : #endif
     317             : 
     318             :   // Check alignment.
     319             :   DCHECK_EQ(0, Heap::GetFillToAlign(obj->address(),
     320             :                                     HeapObject::RequiredAlignment(obj->map())));
     321   441834149 :   return obj;
     322             : }
     323             : 
     324   187566519 : HeapObject Deserializer::GetBackReferencedObject(int space) {
     325   187566519 :   HeapObject obj;
     326   187566519 :   switch (space) {
     327             :     case LO_SPACE:
     328          20 :       obj = allocator()->GetLargeObject(source_.GetInt());
     329          10 :       break;
     330             :     case MAP_SPACE:
     331    24759405 :       obj = allocator()->GetMap(source_.GetInt());
     332    12379707 :       break;
     333             :     case RO_SPACE: {
     334     4367110 :       uint32_t chunk_index = source_.GetInt();
     335     4367110 :       uint32_t chunk_offset = source_.GetInt();
     336     4367111 :       if (isolate()->heap()->deserialization_complete()) {
     337             :         PagedSpace* read_only_space = isolate()->heap()->read_only_space();
     338             :         Page* page = read_only_space->first_page();
     339         157 :         for (uint32_t i = 0; i < chunk_index; ++i) {
     340             :           page = page->next_page();
     341             :         }
     342         157 :         Address address = page->OffsetToAddress(chunk_offset);
     343         157 :         obj = HeapObject::FromAddress(address);
     344             :       } else {
     345             :         obj = allocator()->GetObject(static_cast<AllocationSpace>(space),
     346     8733908 :                                      chunk_index, chunk_offset);
     347             :       }
     348             :       break;
     349             :     }
     350             :     default: {
     351   170819696 :       uint32_t chunk_index = source_.GetInt();
     352   170819769 :       uint32_t chunk_offset = source_.GetInt();
     353             :       obj = allocator()->GetObject(static_cast<AllocationSpace>(space),
     354   341639622 :                                    chunk_index, chunk_offset);
     355   170819509 :       break;
     356             :     }
     357             :   }
     358             : 
     359   187575515 :   if (deserializing_user_code() && obj->IsThinString()) {
     360         136 :     obj = ThinString::cast(obj)->actual();
     361             :   }
     362             : 
     363             :   hot_objects_.Add(obj);
     364             :   DCHECK(!HasWeakHeapObjectTag(obj->ptr()));
     365   187565755 :   return obj;
     366             : }
     367             : 
     368    87971738 : HeapObject Deserializer::ReadObject() {
     369             :   MaybeObject object;
     370             :   // We are reading to a location outside of JS heap, so pass NEW_SPACE to
     371             :   // avoid triggering write barriers.
     372             :   bool filled =
     373    87972235 :       ReadData(FullMaybeObjectSlot(&object), FullMaybeObjectSlot(&object + 1),
     374    87971738 :                NEW_SPACE, kNullAddress);
     375    87972235 :   CHECK(filled);
     376    87972235 :   return object.GetHeapObjectAssumeStrong();
     377             : }
     378             : 
     379   441820316 : HeapObject Deserializer::ReadObject(int space_number) {
     380   441820316 :   const int size = source_.GetInt() << kObjectAlignmentBits;
     381             : 
     382             :   Address address =
     383   883639334 :       allocator()->Allocate(static_cast<AllocationSpace>(space_number), size);
     384             :   HeapObject obj = HeapObject::FromAddress(address);
     385             : 
     386   883655910 :   isolate_->heap()->OnAllocationEvent(obj, size);
     387             :   MaybeObjectSlot current(address);
     388   441829158 :   MaybeObjectSlot limit(address + size);
     389             : 
     390   441829158 :   if (ReadData(current, limit, space_number, address)) {
     391             :     // Only post process if object content has not been deferred.
     392   441647184 :     obj = PostProcessNewObject(obj, space_number);
     393             :   }
     394             : 
     395             : #ifdef DEBUG
     396             :   if (obj->IsCode()) {
     397             :     DCHECK(space_number == CODE_SPACE || space_number == CODE_LO_SPACE);
     398             :   } else {
     399             :     DCHECK(space_number != CODE_SPACE && space_number != CODE_LO_SPACE);
     400             :   }
     401             : #endif  // DEBUG
     402   441837456 :   return obj;
     403             : }
     404             : 
     405    95121732 : void Deserializer::ReadCodeObjectBody(int space_number,
     406             :                                       Address code_object_address) {
     407             :   // At this point the code object is already allocated, its map field is
     408             :   // initialized and its raw data fields and code stream are also read.
     409             :   // Now we read the rest of code header's fields.
     410    95121732 :   MaybeObjectSlot current(code_object_address + HeapObject::kHeaderSize);
     411    95121732 :   MaybeObjectSlot limit(code_object_address + Code::kDataStart);
     412    95121732 :   bool filled = ReadData(current, limit, space_number, code_object_address);
     413    95119453 :   CHECK(filled);
     414             : 
     415             :   // Now iterate RelocInfos the same way it was done by the serialzier and
     416             :   // deserialize respective data into RelocInfos.
     417    95119453 :   Code code = Code::cast(HeapObject::FromAddress(code_object_address));
     418    95119453 :   RelocIterator it(code, Code::BodyDescriptor::kRelocModeMask);
     419   285874499 :   for (; !it.done(); it.next()) {
     420    95379099 :     RelocInfo rinfo = *it.rinfo();
     421    95379099 :     rinfo.Visit(this);
     422             :   }
     423    95122553 : }
     424             : 
     425      436702 : void Deserializer::VisitCodeTarget(Code host, RelocInfo* rinfo) {
     426      436702 :   HeapObject object = ReadObject();
     427      436702 :   rinfo->set_target_address(Code::cast(object)->raw_instruction_start());
     428      436702 : }
     429             : 
     430          20 : void Deserializer::VisitEmbeddedPointer(Code host, RelocInfo* rinfo) {
     431          20 :   HeapObject object = ReadObject();
     432             :   // Embedded object reference must be a strong one.
     433             :   rinfo->set_target_object(isolate_->heap(), object);
     434          20 : }
     435             : 
     436           0 : void Deserializer::VisitRuntimeEntry(Code host, RelocInfo* rinfo) {
     437             :   // We no longer serialize code that contains runtime entries.
     438           0 :   UNREACHABLE();
     439             : }
     440             : 
     441          98 : void Deserializer::VisitExternalReference(Code host, RelocInfo* rinfo) {
     442             :   byte data = source_.Get();
     443          98 :   CHECK_EQ(data, kExternalReference);
     444             : 
     445             :   Address address = ReadExternalReferenceCase();
     446             : 
     447          98 :   if (rinfo->IsCodedSpecially()) {
     448             :     Address location_of_branch_data = rinfo->pc();
     449             :     Assembler::deserialization_set_special_target_at(location_of_branch_data,
     450             :                                                      host, address);
     451             :   } else {
     452             :     WriteUnalignedValue(rinfo->target_address_address(), address);
     453             :   }
     454          98 : }
     455             : 
     456           0 : void Deserializer::VisitInternalReference(Code host, RelocInfo* rinfo) {
     457             :   byte data = source_.Get();
     458           0 :   CHECK_EQ(data, kInternalReference);
     459             : 
     460             :   // Internal reference target is encoded as an offset from code entry.
     461           0 :   int target_offset = source_.GetInt();
     462             :   DCHECK_LT(static_cast<unsigned>(target_offset),
     463             :             static_cast<unsigned>(host->raw_instruction_size()));
     464           0 :   Address target = host->entry() + target_offset;
     465             :   Assembler::deserialization_set_target_internal_reference_at(
     466             :       rinfo->pc(), target, rinfo->rmode());
     467           0 : }
     468             : 
     469    94940687 : void Deserializer::VisitOffHeapTarget(Code host, RelocInfo* rinfo) {
     470             :   DCHECK(FLAG_embedded_builtins);
     471             :   byte data = source_.Get();
     472    94940687 :   CHECK_EQ(data, kOffHeapTarget);
     473             : 
     474    94940687 :   int builtin_index = source_.GetInt();
     475             :   DCHECK(Builtins::IsBuiltinId(builtin_index));
     476             : 
     477    94939851 :   CHECK_NOT_NULL(isolate_->embedded_blob());
     478    94937269 :   EmbeddedData d = EmbeddedData::FromBlob();
     479    94937269 :   Address address = d.InstructionStartOfBuiltin(builtin_index);
     480    94936921 :   CHECK_NE(kNullAddress, address);
     481             : 
     482             :   // TODO(ishell): implement RelocInfo::set_target_off_heap_target()
     483    94936921 :   if (RelocInfo::OffHeapTargetIsCodedSpecially()) {
     484             :     Address location_of_branch_data = rinfo->pc();
     485             :     Assembler::deserialization_set_special_target_at(location_of_branch_data,
     486             :                                                      host, address);
     487             :   } else {
     488             :     WriteUnalignedValue(rinfo->target_address_address(), address);
     489             :   }
     490    94936329 : }
     491             : 
     492             : template <typename TSlot>
     493    87535019 : TSlot Deserializer::ReadRepeatedObject(TSlot current, int repeat_count) {
     494    87535019 :   CHECK_LE(2, repeat_count);
     495             : 
     496    87535019 :   HeapObject heap_object = ReadObject();
     497             :   DCHECK(!Heap::InYoungGeneration(heap_object));
     498   999818607 :   for (int i = 0; i < repeat_count; i++) {
     499             :     // Repeated values are not subject to the write barrier so we don't need
     500             :     // to trigger it.
     501             :     current = Write(current, MaybeObject::FromObject(heap_object));
     502             :   }
     503    87535497 :   return current;
     504             : }
     505             : 
     506           0 : static void NoExternalReferencesCallback() {
     507             :   // The following check will trigger if a function or object template
     508             :   // with references to native functions have been deserialized from
     509             :   // snapshot, but no actual external references were provided when the
     510             :   // isolate was created.
     511           0 :   CHECK_WITH_MSG(false, "No external references provided via API");
     512             : }
     513             : 
     514             : template <typename TSlot>
     515   828852758 : bool Deserializer::ReadData(TSlot current, TSlot limit, int source_space,
     516             :                             Address current_object_address) {
     517   828852758 :   Isolate* const isolate = isolate_;
     518             :   // Write barrier support costs around 1% in startup time.  In fact there
     519             :   // are no new space objects in current boot snapshots, so it's not needed,
     520             :   // but that may change.
     521             :   bool write_barrier_needed =
     522             :       (current_object_address != kNullAddress && source_space != NEW_SPACE &&
     523   828852758 :        source_space != CODE_SPACE);
     524  3705175439 :   while (current < limit) {
     525             :     byte data = source_.Get();
     526  2876523911 :     switch (data) {
     527             : #define CASE_STATEMENT(bytecode, space_number) \
     528             :   case bytecode + space_number:                \
     529             :     STATIC_ASSERT((space_number & ~kSpaceMask) == 0);
     530             : 
     531             : #define CASE_BODY(bytecode, space_number_if_any)                             \
     532             :   current = ReadDataCase<TSlot, bytecode, space_number_if_any>(              \
     533             :       isolate, current, current_object_address, data, write_barrier_needed); \
     534             :   break;
     535             : 
     536             : // This generates a case and a body for the new space (which has to do extra
     537             : // write barrier handling) and handles the other spaces with fall-through cases
     538             : // and one body.
     539             : #define ALL_SPACES(bytecode)           \
     540             :   CASE_STATEMENT(bytecode, NEW_SPACE)  \
     541             :   CASE_BODY(bytecode, NEW_SPACE)       \
     542             :   CASE_STATEMENT(bytecode, OLD_SPACE)  \
     543             :   V8_FALLTHROUGH;                      \
     544             :   CASE_STATEMENT(bytecode, CODE_SPACE) \
     545             :   V8_FALLTHROUGH;                      \
     546             :   CASE_STATEMENT(bytecode, MAP_SPACE)  \
     547             :   V8_FALLTHROUGH;                      \
     548             :   CASE_STATEMENT(bytecode, LO_SPACE)   \
     549             :   V8_FALLTHROUGH;                      \
     550             :   CASE_STATEMENT(bytecode, RO_SPACE)   \
     551             :   CASE_BODY(bytecode, kAnyOldSpace)
     552             : 
     553             : #define FOUR_CASES(byte_code) \
     554             :   case byte_code:             \
     555             :   case byte_code + 1:         \
     556             :   case byte_code + 2:         \
     557             :   case byte_code + 3:
     558             : 
     559             : #define SIXTEEN_CASES(byte_code) \
     560             :   FOUR_CASES(byte_code)          \
     561             :   FOUR_CASES(byte_code + 4)      \
     562             :   FOUR_CASES(byte_code + 8)      \
     563             :   FOUR_CASES(byte_code + 12)
     564             : 
     565             : #define SINGLE_CASE(bytecode, space) \
     566             :   CASE_STATEMENT(bytecode, space)    \
     567             :   CASE_BODY(bytecode, space)
     568             : 
     569             :       // Deserialize a new object and write a pointer to it to the current
     570             :       // object.
     571         760 :       ALL_SPACES(kNewObject)
     572             :       // Find a recently deserialized object using its offset from the current
     573             :       // allocation point and write a pointer to it to the current object.
     574           0 :       ALL_SPACES(kBackref)
     575             :       // Find an object in the roots array and write a pointer to it to the
     576             :       // current object.
     577   209814463 :       SINGLE_CASE(kRootArray, RO_SPACE)
     578             :       // Find an object in the partial snapshots cache and write a pointer to it
     579             :       // to the current object.
     580   152922145 :       SINGLE_CASE(kPartialSnapshotCache, RO_SPACE)
     581             :       // Find an object in the partial snapshots cache and write a pointer to it
     582             :       // to the current object.
     583    29132114 :       SINGLE_CASE(kReadOnlyObjectCache, RO_SPACE)
     584             :       // Find an object in the attached references and write a pointer to it to
     585             :       // the current object.
     586      275251 :       SINGLE_CASE(kAttachedReference, RO_SPACE)
     587             : 
     588             : #undef CASE_STATEMENT
     589             : #undef CASE_BODY
     590             : #undef ALL_SPACES
     591             : 
     592             :       // Find an external reference and write a pointer to it to the current
     593             :       // object.
     594             :       case kExternalReference: {
     595             :         Address address = ReadExternalReferenceCase();
     596             :         current = WriteAddress(current, address);
     597     2058720 :         break;
     598             :       }
     599             : 
     600             :       case kInternalReference:
     601             :       case kOffHeapTarget: {
     602             :         // These bytecodes are expected only during RelocInfo iteration.
     603           0 :         UNREACHABLE();
     604             :         break;
     605             :       }
     606             : 
     607             :       case kNop:
     608             :         break;
     609             : 
     610             :       case kNextChunk: {
     611             :         int space = source_.Get();
     612     4591530 :         allocator()->MoveToNextChunk(static_cast<AllocationSpace>(space));
     613     2295765 :         break;
     614             :       }
     615             : 
     616             :       case kDeferred: {
     617             :         // Deferred can only occur right after the heap object header.
     618             :         DCHECK_EQ(current.address(), current_object_address + kTaggedSize);
     619             :         HeapObject obj = HeapObject::FromAddress(current_object_address);
     620             :         // If the deferred object is a map, its instance type may be used
     621             :         // during deserialization. Initialize it with a temporary value.
     622      190289 :         if (obj->IsMap()) Map::cast(obj)->set_instance_type(FILLER_TYPE);
     623             :         current = limit;
     624             :         return false;
     625             :       }
     626             : 
     627             :       case kSynchronize:
     628             :         // If we get here then that indicates that you have a mismatch between
     629             :         // the number of GC roots when serializing and deserializing.
     630           0 :         UNREACHABLE();
     631             : 
     632             :       // Deserialize raw data of variable length.
     633             :       case kVariableRawData: {
     634      216687 :         int size_in_bytes = source_.GetInt();
     635             :         DCHECK(IsAligned(size_in_bytes, kTaggedSize));
     636             :         source_.CopyRaw(current.ToVoidPtr(), size_in_bytes);
     637      216687 :         current = TSlot(current.address() + size_in_bytes);
     638      216687 :         break;
     639             :       }
     640             : 
     641             :       // Deserialize raw code directly into the body of the code object.
     642             :       case kVariableRawCode: {
     643             :         // VariableRawCode can only occur right after the heap object header.
     644             :         DCHECK_EQ(current.address(), current_object_address + kTaggedSize);
     645    95119172 :         int size_in_bytes = source_.GetInt();
     646             :         DCHECK(IsAligned(size_in_bytes, kTaggedSize));
     647    95119214 :         source_.CopyRaw(
     648             :             reinterpret_cast<void*>(current_object_address + Code::kDataStart),
     649             :             size_in_bytes);
     650             :         // Deserialize tagged fields in the code object header and reloc infos.
     651    95119214 :         ReadCodeObjectBody(source_space, current_object_address);
     652             :         // Set current to the code object end.
     653    95122434 :         current = TSlot(current.address() + Code::kDataStart -
     654             :                         HeapObject::kHeaderSize + size_in_bytes);
     655    95122434 :         CHECK_EQ(current, limit);
     656             :         break;
     657             :       }
     658             : 
     659             :       case kVariableRepeat: {
     660      524664 :         int repeats = DecodeVariableRepeatCount(source_.GetInt());
     661      524664 :         current = ReadRepeatedObject(current, repeats);
     662      524664 :         break;
     663             :       }
     664             : 
     665             :       case kOffHeapBackingStore: {
     666          35 :         int byte_length = source_.GetInt();
     667             :         byte* backing_store = static_cast<byte*>(
     668          35 :             isolate->array_buffer_allocator()->AllocateUninitialized(
     669          35 :                 byte_length));
     670          35 :         CHECK_NOT_NULL(backing_store);
     671             :         source_.CopyRaw(backing_store, byte_length);
     672          35 :         off_heap_backing_stores_.push_back(backing_store);
     673             :         break;
     674             :       }
     675             : 
     676             :       case kApiReference: {
     677         120 :         uint32_t reference_id = static_cast<uint32_t>(source_.GetInt());
     678             :         Address address;
     679         120 :         if (isolate->api_external_references()) {
     680             :           DCHECK_WITH_MSG(
     681             :               reference_id < num_api_references_,
     682             :               "too few external references provided through the API");
     683         100 :           address = static_cast<Address>(
     684             :               isolate->api_external_references()[reference_id]);
     685             :         } else {
     686          20 :           address = reinterpret_cast<Address>(NoExternalReferencesCallback);
     687             :         }
     688             :         current = WriteAddress(current, address);
     689         120 :         break;
     690             :       }
     691             : 
     692             :       case kClearedWeakReference:
     693             :         current = Write(current, HeapObjectReference::ClearedValue(isolate_));
     694      342086 :         break;
     695             : 
     696             :       case kWeakPrefix:
     697             :         DCHECK(!allocator()->next_reference_is_weak());
     698             :         allocator()->set_next_reference_is_weak(true);
     699             :         break;
     700             : 
     701             :       case kAlignmentPrefix:
     702             :       case kAlignmentPrefix + 1:
     703             :       case kAlignmentPrefix + 2: {
     704           0 :         int alignment = data - (SerializerDeserializer::kAlignmentPrefix - 1);
     705           0 :         allocator()->SetAlignment(static_cast<AllocationAlignment>(alignment));
     706             :         break;
     707             :       }
     708             : 
     709             :       // First kNumberOfRootArrayConstants roots are guaranteed to be in
     710             :       // the old space.
     711             :       STATIC_ASSERT(
     712             :           static_cast<int>(RootIndex::kFirstImmortalImmovableRoot) == 0);
     713             :       STATIC_ASSERT(kNumberOfRootArrayConstants <=
     714             :                     static_cast<int>(RootIndex::kLastImmortalImmovableRoot));
     715             :       STATIC_ASSERT(kNumberOfRootArrayConstants == 32);
     716             :       SIXTEEN_CASES(kRootArrayConstants)
     717             :       SIXTEEN_CASES(kRootArrayConstants + 16) {
     718             :         int id = data & kRootArrayConstantsMask;
     719             :         RootIndex root_index = static_cast<RootIndex>(id);
     720             :         MaybeObject object = MaybeObject::FromObject(isolate->root(root_index));
     721             :         DCHECK(!Heap::InYoungGeneration(object));
     722             :         current = Write(current, object);
     723             :         break;
     724             :       }
     725             : 
     726             :       STATIC_ASSERT(kNumberOfHotObjects == 8);
     727             :       FOUR_CASES(kHotObject)
     728             :       FOUR_CASES(kHotObject + 4) {
     729   512335618 :         int index = data & kHotObjectMask;
     730             :         Object hot_object = hot_objects_.Get(index);
     731             :         MaybeObject hot_maybe_object = MaybeObject::FromObject(hot_object);
     732   512335618 :         if (allocator()->GetAndClearNextReferenceIsWeak()) {
     733             :           hot_maybe_object = MaybeObject::MakeWeak(hot_maybe_object);
     734             :         }
     735             :         // Don't update current pointer here as it may be needed for write
     736             :         // barrier.
     737             :         Write(current, hot_maybe_object);
     738   833131886 :         if (write_barrier_needed && Heap::InYoungGeneration(hot_object)) {
     739             :           HeapObject current_object =
     740           0 :               HeapObject::FromAddress(current_object_address);
     741           0 :           GenerationalBarrier(current_object,
     742             :                               MaybeObjectSlot(current.address()),
     743             :                               hot_maybe_object);
     744             :         }
     745             :         ++current;
     746             :         break;
     747             :       }
     748             : 
     749             :       // Deserialize raw data of fixed length from 1 to 32 words.
     750             :       STATIC_ASSERT(kNumberOfFixedRawData == 32);
     751             :       SIXTEEN_CASES(kFixedRawData)
     752             :       SIXTEEN_CASES(kFixedRawData + 16) {
     753   489534200 :         int size_in_tagged = data - kFixedRawDataStart;
     754   489534200 :         source_.CopyRaw(current.ToVoidPtr(), size_in_tagged * kTaggedSize);
     755             :         current += size_in_tagged;
     756             :         break;
     757             :       }
     758             : 
     759             :       STATIC_ASSERT(kNumberOfFixedRepeat == 16);
     760             :       SIXTEEN_CASES(kFixedRepeat) {
     761    87010527 :         int repeats = DecodeFixedRepeatCount(data);
     762    87010527 :         current = ReadRepeatedObject(current, repeats);
     763    87010848 :         break;
     764             :       }
     765             : 
     766             : #ifdef DEBUG
     767             : #define UNUSED_CASE(byte_code) \
     768             :   case byte_code:              \
     769             :     UNREACHABLE();
     770             :       UNUSED_SERIALIZER_BYTE_CODES(UNUSED_CASE)
     771             : #endif
     772             : #undef UNUSED_CASE
     773             : 
     774             : #undef SIXTEEN_CASES
     775             : #undef FOUR_CASES
     776             : #undef SINGLE_CASE
     777             :     }
     778             :   }
     779   828651528 :   CHECK_EQ(limit, current);
     780             :   return true;
     781             : }
     782             : 
     783             : Address Deserializer::ReadExternalReferenceCase() {
     784     2058818 :   uint32_t reference_id = static_cast<uint32_t>(source_.GetInt());
     785     2058818 :   return isolate_->external_reference_table()->address(reference_id);
     786             : }
     787             : 
     788             : template <typename TSlot, SerializerDeserializer::Bytecode bytecode,
     789             :           int space_number_if_any>
     790  1021362497 : TSlot Deserializer::ReadDataCase(Isolate* isolate, TSlot current,
     791             :                                  Address current_object_address, byte data,
     792             :                                  bool write_barrier_needed) {
     793             :   bool emit_write_barrier = false;
     794             :   int space_number = space_number_if_any == kAnyOldSpace ? (data & kSpaceMask)
     795   629217727 :                                                          : space_number_if_any;
     796             :   HeapObject heap_object;
     797             :   HeapObjectReferenceType reference_type =
     798             :       allocator()->GetAndClearNextReferenceIsWeak()
     799             :           ? HeapObjectReferenceType::WEAK
     800  1021362497 :           : HeapObjectReferenceType::STRONG;
     801             : 
     802             :   if (bytecode == kNewObject) {
     803   441840483 :     heap_object = ReadObject(space_number);
     804   441836874 :     emit_write_barrier = (space_number == NEW_SPACE);
     805             :   } else if (bytecode == kBackref) {
     806   187378004 :     heap_object = GetBackReferencedObject(space_number);
     807   187375397 :     emit_write_barrier = (space_number == NEW_SPACE);
     808             :   } else if (bytecode == kRootArray) {
     809   209814488 :     int id = source_.GetInt();
     810   209814050 :     RootIndex root_index = static_cast<RootIndex>(id);
     811             :     heap_object = HeapObject::cast(isolate->root(root_index));
     812             :     emit_write_barrier = Heap::InYoungGeneration(heap_object);
     813             :     hot_objects_.Add(heap_object);
     814             :   } else if (bytecode == kReadOnlyObjectCache) {
     815    29132117 :     int cache_index = source_.GetInt();
     816             :     heap_object = HeapObject::cast(
     817    29132069 :         isolate->heap()->read_only_heap()->read_only_object_cache()->at(
     818             :             cache_index));
     819             :     DCHECK(!Heap::InYoungGeneration(heap_object));
     820             :     emit_write_barrier = false;
     821             :   } else if (bytecode == kPartialSnapshotCache) {
     822   152922154 :     int cache_index = source_.GetInt();
     823             :     heap_object =
     824   152922013 :         HeapObject::cast(isolate->partial_snapshot_cache()->at(cache_index));
     825             :     emit_write_barrier = Heap::InYoungGeneration(heap_object);
     826             :   } else {
     827             :     DCHECK_EQ(bytecode, kAttachedReference);
     828      275251 :     int index = source_.GetInt();
     829      275251 :     heap_object = *attached_objects_[index];
     830             :     emit_write_barrier = Heap::InYoungGeneration(heap_object);
     831             :   }
     832             :   HeapObjectReference heap_object_ref =
     833             :       reference_type == HeapObjectReferenceType::STRONG
     834             :           ? HeapObjectReference::Strong(heap_object)
     835  1021356414 :           : HeapObjectReference::Weak(heap_object);
     836             :   // Don't update current pointer here as it may be needed for write barrier.
     837             :   Write(current, heap_object_ref);
     838   992224345 :   if (emit_write_barrier && write_barrier_needed) {
     839      275827 :     HeapObject host_object = HeapObject::FromAddress(current_object_address);
     840             :     SLOW_DCHECK(isolate->heap()->Contains(host_object));
     841      275827 :     GenerationalBarrier(host_object, MaybeObjectSlot(current.address()),
     842             :                         heap_object_ref);
     843             :   }
     844  1021356414 :   return current + 1;
     845             : }
     846             : 
     847             : }  // namespace internal
     848      122036 : }  // namespace v8

Generated by: LCOV version 1.10