diff options
Diffstat (limited to 'chromium/v8/src/snapshot/deserializer.cc')
-rw-r--r-- | chromium/v8/src/snapshot/deserializer.cc | 152 |
1 files changed, 82 insertions, 70 deletions
diff --git a/chromium/v8/src/snapshot/deserializer.cc b/chromium/v8/src/snapshot/deserializer.cc index 33e4db43931..3c4f9503f2a 100644 --- a/chromium/v8/src/snapshot/deserializer.cc +++ b/chromium/v8/src/snapshot/deserializer.cc @@ -8,11 +8,13 @@ #include "src/codegen/assembler-inl.h" #include "src/common/external-pointer.h" #include "src/execution/isolate.h" +#include "src/execution/local-isolate-wrapper-inl.h" #include "src/heap/heap-inl.h" #include "src/heap/heap-write-barrier-inl.h" #include "src/heap/read-only-heap.h" #include "src/interpreter/interpreter.h" #include "src/logging/log.h" +#include "src/logging/off-thread-logger.h" #include "src/objects/api-callbacks.h" #include "src/objects/cell-inl.h" #include "src/objects/hash-table.h" @@ -56,22 +58,25 @@ TSlot Deserializer::WriteExternalPointer(TSlot dest, Address value) { return dest + (kExternalPointerSize / TSlot::kSlotDataSize); } -void Deserializer::Initialize(Isolate* isolate) { - DCHECK_NULL(isolate_); - DCHECK_NOT_NULL(isolate); - isolate_ = isolate; - allocator()->Initialize(isolate->heap()); +void Deserializer::Initialize(LocalIsolateWrapper local_isolate) { + DCHECK(local_isolate_.is_null()); + DCHECK(!local_isolate.is_null()); + local_isolate_ = local_isolate; + allocator()->Initialize(local_isolate->heap()); #ifdef DEBUG - // The read-only deserializer is run by read-only heap set-up before the heap - // is fully set up. External reference table relies on a few parts of this - // set-up (like old-space), so it may be uninitialized at this point. - if (isolate->isolate_data()->external_reference_table()->is_initialized()) { - // Count the number of external references registered through the API. - num_api_references_ = 0; - if (isolate_->api_external_references() != nullptr) { - while (isolate_->api_external_references()[num_api_references_] != 0) { - num_api_references_++; + num_api_references_ = 0; + if (!local_isolate.is_off_thread()) { + Isolate* isolate = local_isolate.main_thread(); + // The read-only deserializer is run by read-only heap set-up before the + // heap is fully set up. External reference table relies on a few parts of + // this set-up (like old-space), so it may be uninitialized at this point. + if (isolate->isolate_data()->external_reference_table()->is_initialized()) { + // Count the number of external references registered through the API. + if (isolate->api_external_references() != nullptr) { + while (isolate->api_external_references()[num_api_references_] != 0) { + num_api_references_++; + } } } } @@ -82,7 +87,7 @@ void Deserializer::Initialize(Isolate* isolate) { void Deserializer::Rehash() { DCHECK(can_rehash() || deserializing_user_code()); for (HeapObject item : to_rehash_) { - item.RehashBasedOnMap(ReadOnlyRoots(isolate_)); + item.RehashBasedOnMap(local_isolate()); } } @@ -142,34 +147,32 @@ void Deserializer::DeserializeDeferredObjects() { } } } -} -void Deserializer::LogNewObjectEvents() { - { - // {new_maps_} and {new_code_objects_} are vectors containing raw - // pointers, hence there should be no GC happening. - DisallowHeapAllocation no_gc; - // Issue code events for newly deserialized code objects. - LOG_CODE_EVENT(isolate_, LogCodeObjects()); + // When the deserialization of maps are deferred, they will be created + // as filler maps, and we postpone the post processing until the maps + // are also deserialized. + for (const auto& pair : fillers_to_post_process_) { + DCHECK(!pair.first.IsFiller()); + PostProcessNewObject(pair.first, pair.second); } - LOG_CODE_EVENT(isolate_, LogCompiledFunctions()); - LogNewMapEvents(); } void Deserializer::LogNewMapEvents() { DisallowHeapAllocation no_gc; - for (Map map : new_maps()) { + DCHECK(is_main_thread()); + + for (Map map : new_maps_) { DCHECK(FLAG_trace_maps); - LOG(isolate_, MapCreate(map)); - LOG(isolate_, MapDetails(map)); + LOG(isolate(), MapCreate(map)); + LOG(isolate(), MapDetails(map)); } } void Deserializer::LogScriptEvents(Script script) { DisallowHeapAllocation no_gc; - LOG(isolate_, + LOG(local_isolate(), ScriptEvent(Logger::ScriptEventType::kDeserialize, script.id())); - LOG(isolate_, ScriptDetails(script)); + LOG(local_isolate(), ScriptDetails(script)); } StringTableInsertionKey::StringTableInsertionKey(String string) @@ -213,7 +216,11 @@ HeapObject Deserializer::PostProcessNewObject(HeapObject obj, DisallowHeapAllocation no_gc; if ((FLAG_rehash_snapshot && can_rehash_) || deserializing_user_code()) { - if (obj.IsString()) { + if (obj.IsFiller()) { + DCHECK_EQ(fillers_to_post_process_.find(obj), + fillers_to_post_process_.end()); + fillers_to_post_process_.insert({obj, space}); + } else if (obj.IsString()) { // Uninitialize hash field as we need to recompute the hash. String string = String::cast(obj); string.set_hash_field(String::kEmptyHashField); @@ -231,18 +238,22 @@ HeapObject Deserializer::PostProcessNewObject(HeapObject obj, if (obj.IsString()) { String string = String::cast(obj); if (string.IsInternalizedString()) { + // Off-thread internalized strings are canonicalized during off-thread + // isolate publish, so we don't have to canonicalize them here. + if (local_isolate().is_off_thread()) return string; + // Canonicalize the internalized string. If it already exists in the // string table, set it to forward to the existing one. StringTableInsertionKey key(string); - String canonical = ForwardStringIfExists(isolate_, &key); + String canonical = ForwardStringIfExists(isolate(), &key); if (!canonical.is_null()) return canonical; - new_internalized_strings_.push_back(handle(string, isolate_)); + new_internalized_strings_.push_back(handle(string, isolate())); return string; } } else if (obj.IsScript()) { - new_scripts_.push_back(handle(Script::cast(obj), isolate_)); + new_scripts_.push_back(handle(Script::cast(obj), local_isolate())); } else if (obj.IsAllocationSite()) { // We should link new allocation sites, but we can't do this immediately // because |AllocationSite::HasWeakNext()| internally accesses @@ -278,11 +289,11 @@ HeapObject Deserializer::PostProcessNewObject(HeapObject obj, ExternalString string = ExternalString::cast(obj); uint32_t index = string.resource_as_uint32(); Address address = - static_cast<Address>(isolate_->api_external_references()[index]); - string.set_address_as_resource(isolate_, address); - isolate_->heap()->UpdateExternalString(string, 0, - string.ExternalPayloadSize()); - isolate_->heap()->RegisterExternalString(String::cast(obj)); + static_cast<Address>(isolate()->api_external_references()[index]); + string.set_address_as_resource(isolate(), address); + isolate()->heap()->UpdateExternalString(string, 0, + string.ExternalPayloadSize()); + isolate()->heap()->RegisterExternalString(String::cast(obj)); } else if (obj.IsJSDataView()) { JSDataView data_view = JSDataView::cast(obj); JSArrayBuffer buffer = JSArrayBuffer::cast(data_view.buffer()); @@ -295,7 +306,7 @@ HeapObject Deserializer::PostProcessNewObject(HeapObject obj, backing_store = backing_stores_[store_index]->buffer_start(); } data_view.set_data_pointer( - isolate_, + isolate(), reinterpret_cast<uint8_t*>(backing_store) + data_view.byte_offset()); } else if (obj.IsJSTypedArray()) { JSTypedArray typed_array = JSTypedArray::cast(obj); @@ -319,7 +330,7 @@ HeapObject Deserializer::PostProcessNewObject(HeapObject obj, JSArrayBuffer buffer = JSArrayBuffer::cast(obj); // Postpone allocation of backing store to avoid triggering the GC. if (buffer.backing_store() != nullptr) { - new_off_heap_array_buffers_.push_back(handle(buffer, isolate_)); + new_off_heap_array_buffers_.push_back(handle(buffer, local_isolate())); } } else if (obj.IsBytecodeArray()) { // TODO(mythria): Remove these once we store the default values for these @@ -352,12 +363,10 @@ HeapObject Deserializer::GetBackReferencedObject(SnapshotSpace space) { case SnapshotSpace::kReadOnlyHeap: { uint32_t chunk_index = source_.GetInt(); uint32_t chunk_offset = source_.GetInt(); - if (isolate()->heap()->deserialization_complete()) { - PagedSpace* read_only_space = isolate()->heap()->read_only_space(); - Page* page = read_only_space->first_page(); - for (uint32_t i = 0; i < chunk_index; ++i) { - page = page->next_page(); - } + if (is_off_thread() || isolate()->heap()->deserialization_complete()) { + ReadOnlySpace* read_only_space = + local_isolate()->heap()->read_only_space(); + ReadOnlyPage* page = read_only_space->pages()[chunk_index]; Address address = page->OffsetToAddress(chunk_offset); obj = HeapObject::FromAddress(address); } else { @@ -401,7 +410,7 @@ HeapObject Deserializer::ReadObject(SnapshotSpace space) { Address address = allocator()->Allocate(space, size); HeapObject obj = HeapObject::FromAddress(address); - isolate_->heap()->OnAllocationEvent(obj, size); + local_isolate()->heap()->OnAllocationEvent(obj, size); MaybeObjectSlot current(address); MaybeObjectSlot limit(address + size); @@ -449,7 +458,7 @@ void Deserializer::VisitCodeTarget(Code host, RelocInfo* rinfo) { void Deserializer::VisitEmbeddedPointer(Code host, RelocInfo* rinfo) { HeapObject object = ReadObject(); // Embedded object reference must be a strong one. - rinfo->set_target_object(isolate_->heap(), object); + rinfo->set_target_object(isolate()->heap(), object); } void Deserializer::VisitRuntimeEntry(Code host, RelocInfo* rinfo) { @@ -492,7 +501,7 @@ void Deserializer::VisitOffHeapTarget(Code host, RelocInfo* rinfo) { int builtin_index = source_.GetInt(); DCHECK(Builtins::IsBuiltinId(builtin_index)); - CHECK_NOT_NULL(isolate_->embedded_blob()); + CHECK_NOT_NULL(isolate()->embedded_blob()); EmbeddedData d = EmbeddedData::FromBlob(); Address address = d.InstructionStartOfBuiltin(builtin_index); CHECK_NE(kNullAddress, address); @@ -533,7 +542,6 @@ template <typename TSlot> bool Deserializer::ReadData(TSlot current, TSlot limit, SnapshotSpace source_space, Address current_object_address) { - Isolate* const isolate = isolate_; // Write barrier support costs around 1% in startup time. In fact there // are no new space objects in current boot snapshots, so it's not needed, // but that may change. @@ -548,9 +556,9 @@ bool Deserializer::ReadData(TSlot current, TSlot limit, case bytecode + static_cast<int>(snapshot_space): \ STATIC_ASSERT((static_cast<int>(snapshot_space) & ~kSpaceMask) == 0); -#define CASE_BODY(bytecode, space_number_if_any) \ - current = ReadDataCase<TSlot, bytecode, space_number_if_any>( \ - isolate, current, current_object_address, data, write_barrier_needed); \ +#define CASE_BODY(bytecode, space_number_if_any) \ + current = ReadDataCase<TSlot, bytecode, space_number_if_any>( \ + current, current_object_address, data, write_barrier_needed); \ break; // This generates a case and a body for the new space (which has to do extra @@ -689,11 +697,11 @@ bool Deserializer::ReadData(TSlot current, TSlot limit, } case kOffHeapBackingStore: { - AlwaysAllocateScope scope(isolate->heap()); + AlwaysAllocateScope scope(isolate()->heap()); int byte_length = source_.GetInt(); - std::unique_ptr<BackingStore> backing_store = - BackingStore::Allocate(isolate, byte_length, SharedFlag::kNotShared, - InitializedFlag::kUninitialized); + std::unique_ptr<BackingStore> backing_store = BackingStore::Allocate( + isolate(), byte_length, SharedFlag::kNotShared, + InitializedFlag::kUninitialized); CHECK_NOT_NULL(backing_store); source_.CopyRaw(backing_store->buffer_start(), byte_length); backing_stores_.push_back(std::move(backing_store)); @@ -704,12 +712,14 @@ bool Deserializer::ReadData(TSlot current, TSlot limit, case kApiReference: { uint32_t reference_id = static_cast<uint32_t>(source_.GetInt()); Address address; - if (isolate->api_external_references()) { + if (isolate()->api_external_references()) { DCHECK_WITH_MSG( reference_id < num_api_references_, "too few external references provided through the API"); address = static_cast<Address>( - isolate->api_external_references()[reference_id]); + local_isolate() + .main_thread() + ->api_external_references()[reference_id]); } else { address = reinterpret_cast<Address>(NoExternalReferencesCallback); } @@ -723,7 +733,8 @@ bool Deserializer::ReadData(TSlot current, TSlot limit, } case kClearedWeakReference: - current = Write(current, HeapObjectReference::ClearedValue(isolate_)); + current = + Write(current, HeapObjectReference::ClearedValue(local_isolate())); break; case kWeakPrefix: @@ -750,7 +761,8 @@ bool Deserializer::ReadData(TSlot current, TSlot limit, SIXTEEN_CASES(kRootArrayConstants + 16) { int id = data & kRootArrayConstantsMask; RootIndex root_index = static_cast<RootIndex>(id); - MaybeObject object = MaybeObject::FromObject(isolate->root(root_index)); + MaybeObject object = + MaybeObject(ReadOnlyRoots(local_isolate()).at(root_index)); DCHECK(!Heap::InYoungGeneration(object)); current = Write(current, object); break; @@ -819,14 +831,13 @@ bool Deserializer::ReadData(TSlot current, TSlot limit, Address Deserializer::ReadExternalReferenceCase() { uint32_t reference_id = static_cast<uint32_t>(source_.GetInt()); - return isolate_->external_reference_table()->address(reference_id); + return isolate()->external_reference_table()->address(reference_id); } template <typename TSlot, SerializerDeserializer::Bytecode bytecode, SnapshotSpace space_number_if_any> -TSlot Deserializer::ReadDataCase(Isolate* isolate, TSlot current, - Address current_object_address, byte data, - bool write_barrier_needed) { +TSlot Deserializer::ReadDataCase(TSlot current, Address current_object_address, + byte data, bool write_barrier_needed) { bool emit_write_barrier = false; SnapshotSpace space = static_cast<SnapshotSpace>( space_number_if_any == kAnyOldSpace @@ -847,19 +858,20 @@ TSlot Deserializer::ReadDataCase(Isolate* isolate, TSlot current, } else if (bytecode == kRootArray) { int id = source_.GetInt(); RootIndex root_index = static_cast<RootIndex>(id); - heap_object = HeapObject::cast(isolate->root(root_index)); + heap_object = HeapObject::cast(local_isolate()->root(root_index)); emit_write_barrier = Heap::InYoungGeneration(heap_object); hot_objects_.Add(heap_object); } else if (bytecode == kReadOnlyObjectCache) { int cache_index = source_.GetInt(); heap_object = HeapObject::cast( - isolate->read_only_heap()->cached_read_only_object(cache_index)); + local_isolate()->read_only_heap()->cached_read_only_object( + cache_index)); DCHECK(!Heap::InYoungGeneration(heap_object)); emit_write_barrier = false; } else if (bytecode == kStartupObjectCache) { int cache_index = source_.GetInt(); heap_object = - HeapObject::cast(isolate->startup_object_cache()->at(cache_index)); + HeapObject::cast(isolate()->startup_object_cache()->at(cache_index)); emit_write_barrier = Heap::InYoungGeneration(heap_object); } else { DCHECK_EQ(bytecode, kAttachedReference); @@ -876,7 +888,7 @@ TSlot Deserializer::ReadDataCase(Isolate* isolate, TSlot current, if (emit_write_barrier && write_barrier_needed) { DCHECK_IMPLIES(FLAG_disable_write_barriers, !write_barrier_needed); HeapObject host_object = HeapObject::FromAddress(current_object_address); - SLOW_DCHECK(isolate->heap()->Contains(host_object)); + SLOW_DCHECK(local_isolate()->heap()->Contains(host_object)); GenerationalBarrier(host_object, MaybeObjectSlot(current.address()), heap_object_ref); } |