LCOV - code coverage report
Current view: top level - src/snapshot - deserializer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 241 271 88.9 %
Date: 2019-02-19 Functions: 31 38 81.6 %

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

Generated by: LCOV version 1.10