diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/v8/src/snapshot | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/v8/src/snapshot')
-rw-r--r-- | chromium/v8/src/snapshot/code-serializer.cc | 70 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/context-deserializer.cc | 2 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/deserializer-allocator.cc | 48 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/deserializer-allocator.h | 9 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/deserializer.cc | 152 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/deserializer.h | 30 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/object-deserializer.cc | 106 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/object-deserializer.h | 6 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/read-only-deserializer.cc | 4 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/serializer-allocator.cc | 3 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/serializer.cc | 17 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/snapshot-utils.cc | 2 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/snapshot.cc | 24 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/snapshot.h | 1 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/startup-deserializer.cc | 2 |
15 files changed, 307 insertions, 169 deletions
diff --git a/chromium/v8/src/snapshot/code-serializer.cc b/chromium/v8/src/snapshot/code-serializer.cc index f9093012b27..f4cf0b07072 100644 --- a/chromium/v8/src/snapshot/code-serializer.cc +++ b/chromium/v8/src/snapshot/code-serializer.cc @@ -4,9 +4,12 @@ #include "src/snapshot/code-serializer.h" +#include "src/base/platform/platform.h" #include "src/codegen/macro-assembler.h" +#include "src/common/globals.h" #include "src/debug/debug.h" #include "src/heap/heap-inl.h" +#include "src/heap/off-thread-factory-inl.h" #include "src/logging/counters.h" #include "src/logging/log.h" #include "src/objects/objects-inl.h" @@ -104,14 +107,14 @@ bool CodeSerializer::SerializeReadOnlyObject(HeapObject obj) { // create a back reference that encodes the page number as the chunk_index and // the offset within the page as the chunk_offset. Address address = obj.address(); - Page* page = Page::FromAddress(address); + BasicMemoryChunk* chunk = BasicMemoryChunk::FromAddress(address); uint32_t chunk_index = 0; ReadOnlySpace* const read_only_space = isolate()->heap()->read_only_space(); - for (Page* p : *read_only_space) { - if (p == page) break; + for (ReadOnlyPage* page : read_only_space->pages()) { + if (chunk == page) break; ++chunk_index; } - uint32_t chunk_offset = static_cast<uint32_t>(page->Offset(address)); + uint32_t chunk_offset = static_cast<uint32_t>(chunk->Offset(address)); SerializerReference back_reference = SerializerReference::BackReference( SnapshotSpace::kReadOnlyHeap, chunk_index, chunk_offset); reference_map()->Add(reinterpret_cast<void*>(obj.ptr()), back_reference); @@ -259,6 +262,39 @@ void CreateInterpreterDataForDeserializedCode(Isolate* isolate, } #endif // V8_TARGET_ARCH_ARM +namespace { +class StressOffThreadDeserializeThread final : public base::Thread { + public: + explicit StressOffThreadDeserializeThread( + OffThreadIsolate* off_thread_isolate, const SerializedCodeData* scd) + : Thread( + base::Thread::Options("StressOffThreadDeserializeThread", 2 * MB)), + off_thread_isolate_(off_thread_isolate), + scd_(scd) {} + + MaybeHandle<SharedFunctionInfo> maybe_result() const { + return maybe_result_.ToHandle(); + } + + void Run() final { + off_thread_isolate_->PinToCurrentThread(); + + MaybeHandle<SharedFunctionInfo> off_thread_maybe_result = + ObjectDeserializer::DeserializeSharedFunctionInfoOffThread( + off_thread_isolate_, scd_, + off_thread_isolate_->factory()->empty_string()); + + maybe_result_ = + off_thread_isolate_->TransferHandle(off_thread_maybe_result); + } + + private: + OffThreadIsolate* off_thread_isolate_; + const SerializedCodeData* scd_; + OffThreadTransferMaybeHandle<SharedFunctionInfo> maybe_result_; +}; +} // namespace + MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( Isolate* isolate, ScriptData* cached_data, Handle<String> source, ScriptOriginOptions origin_options) { @@ -281,8 +317,29 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( } // Deserialize. - MaybeHandle<SharedFunctionInfo> maybe_result = - ObjectDeserializer::DeserializeSharedFunctionInfo(isolate, &scd, source); + MaybeHandle<SharedFunctionInfo> maybe_result; + if (FLAG_stress_background_compile) { + Zone zone(isolate->allocator(), "Deserialize"); + OffThreadIsolate off_thread_isolate(isolate, &zone); + + StressOffThreadDeserializeThread thread(&off_thread_isolate, &scd); + CHECK(thread.Start()); + thread.Join(); + + off_thread_isolate.FinishOffThread(); + off_thread_isolate.Publish(isolate); + + maybe_result = thread.maybe_result(); + + // Fix-up result script source. + Handle<SharedFunctionInfo> result; + if (maybe_result.ToHandle(&result)) { + Script::cast(result->script()).set_source(*source); + } + } else { + maybe_result = ObjectDeserializer::DeserializeSharedFunctionInfo( + isolate, &scd, source); + } Handle<SharedFunctionInfo> result; if (!maybe_result.ToHandle(&result)) { @@ -356,7 +413,6 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( return scope.CloseAndEscape(result); } - SerializedCodeData::SerializedCodeData(const std::vector<byte>* payload, const CodeSerializer* cs) { DisallowHeapAllocation no_gc; diff --git a/chromium/v8/src/snapshot/context-deserializer.cc b/chromium/v8/src/snapshot/context-deserializer.cc index 2a3d77646a9..b6b6da54f91 100644 --- a/chromium/v8/src/snapshot/context-deserializer.cc +++ b/chromium/v8/src/snapshot/context-deserializer.cc @@ -59,12 +59,12 @@ MaybeHandle<Object> ContextDeserializer::Deserialize( // new code, which also has to be flushed from instruction cache. CHECK_EQ(start_address, code_space->top()); - if (FLAG_rehash_snapshot && can_rehash()) Rehash(); LogNewMapEvents(); result = handle(root, isolate); } + if (FLAG_rehash_snapshot && can_rehash()) Rehash(); SetupOffHeapArrayBufferBackingStores(); return result; diff --git a/chromium/v8/src/snapshot/deserializer-allocator.cc b/chromium/v8/src/snapshot/deserializer-allocator.cc index a3d3eca7114..c1eaaed2960 100644 --- a/chromium/v8/src/snapshot/deserializer-allocator.cc +++ b/chromium/v8/src/snapshot/deserializer-allocator.cc @@ -6,10 +6,17 @@ #include "src/heap/heap-inl.h" // crbug.com/v8/8499 #include "src/heap/memory-chunk.h" +#include "src/roots/roots.h" namespace v8 { namespace internal { +void DeserializerAllocator::Initialize(LocalHeapWrapper heap) { + heap_ = heap; + roots_ = heap.is_off_thread() ? ReadOnlyRoots(heap.off_thread()) + : ReadOnlyRoots(heap.main_thread()); +} + // We know the space requirements before deserialization and can // pre-allocate that reserved space. During deserialization, all we need // to do is to bump up the pointer for each space in the reserved @@ -24,12 +31,18 @@ namespace internal { Address DeserializerAllocator::AllocateRaw(SnapshotSpace space, int size) { const int space_number = static_cast<int>(space); if (space == SnapshotSpace::kLargeObject) { - AlwaysAllocateScope scope(heap_); // Note that we currently do not support deserialization of large code // objects. - OldLargeObjectSpace* lo_space = heap_->lo_space(); - AllocationResult result = lo_space->AllocateRaw(size); - HeapObject obj = result.ToObjectChecked(); + HeapObject obj; + if (heap_.is_off_thread()) { + obj = heap_.off_thread()->lo_space_.AllocateRaw(size).ToObjectChecked(); + } else { + Heap* heap = heap_.main_thread(); + AlwaysAllocateScope scope(heap); + OldLargeObjectSpace* lo_space = heap->lo_space(); + AllocationResult result = lo_space->AllocateRaw(size); + obj = result.ToObjectChecked(); + } deserialized_large_objects_.push_back(obj); return obj.address(); } else if (space == SnapshotSpace::kMap) { @@ -82,11 +95,10 @@ Address DeserializerAllocator::Allocate(SnapshotSpace space, int size) { // If one of the following assertions fails, then we are deserializing an // aligned object when the filler maps have not been deserialized yet. // We require filler maps as padding to align the object. - DCHECK(ReadOnlyRoots(heap_).free_space_map().IsMap()); - DCHECK(ReadOnlyRoots(heap_).one_pointer_filler_map().IsMap()); - DCHECK(ReadOnlyRoots(heap_).two_pointer_filler_map().IsMap()); - obj = Heap::AlignWithFiller(ReadOnlyRoots(heap_), obj, size, reserved, - next_alignment_); + DCHECK(roots_.free_space_map().IsMap()); + DCHECK(roots_.one_pointer_filler_map().IsMap()); + DCHECK(roots_.two_pointer_filler_map().IsMap()); + obj = Heap::AlignWithFiller(roots_, obj, size, reserved, next_alignment_); address = obj.address(); next_alignment_ = kWordAligned; return address; @@ -109,6 +121,7 @@ void DeserializerAllocator::MoveToNextChunk(SnapshotSpace space) { } HeapObject DeserializerAllocator::GetMap(uint32_t index) { + DCHECK(!heap_.is_off_thread()); DCHECK_LT(index, next_map_index_); return HeapObject::FromAddress(allocated_maps_[index]); } @@ -156,10 +169,16 @@ bool DeserializerAllocator::ReserveSpace() { } #endif // DEBUG DCHECK(allocated_maps_.empty()); - // TODO(v8:7464): Allocate using the off-heap ReadOnlySpace here once - // implemented. - if (!heap_->ReserveSpace(reservations_, &allocated_maps_)) { - return false; + if (heap_.is_off_thread()) { + if (!heap_.off_thread()->ReserveSpace(reservations_)) { + return false; + } + } else { + // TODO(v8:7464): Allocate using the off-heap ReadOnlySpace here once + // implemented. + if (!heap_.main_thread()->ReserveSpace(reservations_, &allocated_maps_)) { + return false; + } } for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { high_water_[i] = reservations_[i][0].start; @@ -181,7 +200,8 @@ bool DeserializerAllocator::ReservationsAreFullyUsed() const { } void DeserializerAllocator::RegisterDeserializedObjectsForBlackAllocation() { - heap_->RegisterDeserializedObjectsForBlackAllocation( + DCHECK(!heap_.is_off_thread()); + heap_.main_thread()->RegisterDeserializedObjectsForBlackAllocation( reservations_, deserialized_large_objects_, allocated_maps_); } diff --git a/chromium/v8/src/snapshot/deserializer-allocator.h b/chromium/v8/src/snapshot/deserializer-allocator.h index 979e6ed2a8b..9381e1302bd 100644 --- a/chromium/v8/src/snapshot/deserializer-allocator.h +++ b/chromium/v8/src/snapshot/deserializer-allocator.h @@ -6,8 +6,10 @@ #define V8_SNAPSHOT_DESERIALIZER_ALLOCATOR_H_ #include "src/common/globals.h" +#include "src/execution/local-isolate-wrapper.h" #include "src/heap/heap.h" #include "src/objects/heap-object.h" +#include "src/roots/roots.h" #include "src/snapshot/references.h" #include "src/snapshot/snapshot-data.h" @@ -16,12 +18,13 @@ namespace internal { class Deserializer; class StartupDeserializer; +class OffThreadHeap; class DeserializerAllocator final { public: DeserializerAllocator() = default; - void Initialize(Heap* heap) { heap_ = heap; } + void Initialize(LocalHeapWrapper heap); // ------- Allocation Methods ------- // Methods related to memory allocation during deserialization. @@ -99,7 +102,9 @@ class DeserializerAllocator final { // back-references. std::vector<HeapObject> deserialized_large_objects_; - Heap* heap_; + // ReadOnlyRoots and heap are null until Initialize is called. + LocalHeapWrapper heap_ = LocalHeapWrapper(nullptr); + ReadOnlyRoots roots_ = ReadOnlyRoots(static_cast<Address*>(nullptr)); DISALLOW_COPY_AND_ASSIGN(DeserializerAllocator); }; 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); } diff --git a/chromium/v8/src/snapshot/deserializer.h b/chromium/v8/src/snapshot/deserializer.h index 3af3eca5910..344db431a18 100644 --- a/chromium/v8/src/snapshot/deserializer.h +++ b/chromium/v8/src/snapshot/deserializer.h @@ -8,6 +8,7 @@ #include <utility> #include <vector> +#include "src/execution/local-isolate-wrapper.h" #include "src/objects/allocation-site.h" #include "src/objects/api-callbacks.h" #include "src/objects/backing-store.h" @@ -47,7 +48,7 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { // Create a deserializer from a snapshot byte source. template <class Data> Deserializer(Data* data, bool deserializing_user_code) - : isolate_(nullptr), + : local_isolate_(nullptr), source_(data->Payload()), magic_number_(data->GetMagicNumber()), deserializing_user_code_(deserializing_user_code), @@ -58,7 +59,10 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { backing_stores_.push_back({}); } - void Initialize(Isolate* isolate); + void Initialize(Isolate* isolate) { + Initialize(LocalIsolateWrapper(isolate)); + } + void Initialize(LocalIsolateWrapper isolate); void DeserializeDeferredObjects(); // Create Log events for newly deserialized objects. @@ -80,7 +84,11 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { CHECK_EQ(new_off_heap_array_buffers().size(), 0); } - Isolate* isolate() const { return isolate_; } + LocalIsolateWrapper local_isolate() const { return local_isolate_; } + Isolate* isolate() const { return local_isolate().main_thread(); } + bool is_main_thread() const { return local_isolate().is_main_thread(); } + bool is_off_thread() const { return local_isolate().is_off_thread(); } + SnapshotByteSource* source() { return &source_; } const std::vector<AllocationSite>& new_allocation_sites() const { return new_allocation_sites_; @@ -117,9 +125,6 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { void Rehash(); - // Cached current isolate. - Isolate* isolate_; - private: void VisitRootPointers(Root root, const char* description, FullObjectSlot start, FullObjectSlot end) override; @@ -148,9 +153,8 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { // Returns the new value of {current}. template <typename TSlot, Bytecode bytecode, SnapshotSpace space_number_if_any> - inline TSlot ReadDataCase(Isolate* isolate, TSlot current, - Address current_object_address, byte data, - bool write_barrier_needed); + inline TSlot ReadDataCase(TSlot current, Address current_object_address, + byte data, bool write_barrier_needed); // A helper function for ReadData for reading external references. inline Address ReadExternalReferenceCase(); @@ -175,6 +179,9 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { // Special handling for serialized code like hooking up internalized strings. HeapObject PostProcessNewObject(HeapObject obj, SnapshotSpace space); + // Cached current isolate. + LocalIsolateWrapper local_isolate_; + // Objects from the attached object descriptions in the serialized user code. std::vector<Handle<HeapObject>> attached_objects_; @@ -197,6 +204,11 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { // TODO(6593): generalize rehashing, and remove this flag. bool can_rehash_; std::vector<HeapObject> to_rehash_; + // Store the objects whose maps are deferred and thus initialized as filler + // maps during deserialization, so that they can be processed later when the + // maps become available. + std::unordered_map<HeapObject, SnapshotSpace, Object::Hasher> + fillers_to_post_process_; #ifdef DEBUG uint32_t num_api_references_; diff --git a/chromium/v8/src/snapshot/object-deserializer.cc b/chromium/v8/src/snapshot/object-deserializer.cc index 2de08846d4c..caae792c42e 100644 --- a/chromium/v8/src/snapshot/object-deserializer.cc +++ b/chromium/v8/src/snapshot/object-deserializer.cc @@ -6,6 +6,7 @@ #include "src/codegen/assembler-inl.h" #include "src/execution/isolate.h" +#include "src/execution/local-isolate-wrapper-inl.h" #include "src/heap/heap-inl.h" #include "src/objects/allocation-site-inl.h" #include "src/objects/objects.h" @@ -26,75 +27,92 @@ ObjectDeserializer::DeserializeSharedFunctionInfo( d.AddAttachedObject(source); Handle<HeapObject> result; - return d.Deserialize(isolate).ToHandle(&result) + return d.Deserialize(LocalIsolateWrapper(isolate)).ToHandle(&result) ? Handle<SharedFunctionInfo>::cast(result) : MaybeHandle<SharedFunctionInfo>(); } -MaybeHandle<HeapObject> ObjectDeserializer::Deserialize(Isolate* isolate) { - Initialize(isolate); +MaybeHandle<SharedFunctionInfo> +ObjectDeserializer::DeserializeSharedFunctionInfoOffThread( + OffThreadIsolate* isolate, const SerializedCodeData* data, + Handle<String> source) { + DCHECK(ReadOnlyHeap::Contains(*source) || Heap::InOffThreadSpace(*source)); + + ObjectDeserializer d(data); + + d.AddAttachedObject(source); + + Handle<HeapObject> result; + return d.Deserialize(LocalIsolateWrapper(isolate)).ToHandle(&result) + ? Handle<SharedFunctionInfo>::cast(result) + : MaybeHandle<SharedFunctionInfo>(); +} + +MaybeHandle<HeapObject> ObjectDeserializer::Deserialize( + LocalIsolateWrapper local_isolate) { + Initialize(local_isolate); if (!allocator()->ReserveSpace()) return MaybeHandle<HeapObject>(); DCHECK(deserializing_user_code()); - HandleScope scope(isolate); + LocalHandleScopeWrapper scope(local_isolate); Handle<HeapObject> result; { DisallowHeapAllocation no_gc; Object root; VisitRootPointer(Root::kStartupObjectCache, nullptr, FullObjectSlot(&root)); DeserializeDeferredObjects(); - FlushICache(); - LinkAllocationSites(); - LogNewMapEvents(); - result = handle(HeapObject::cast(root), isolate); - Rehash(); - allocator()->RegisterDeserializedObjectsForBlackAllocation(); + CHECK(new_code_objects().empty()); + if (is_main_thread()) { + LinkAllocationSites(); + LogNewMapEvents(); + } + result = handle(HeapObject::cast(root), local_isolate); + if (is_main_thread()) { + allocator()->RegisterDeserializedObjectsForBlackAllocation(); + } } + + Rehash(); CommitPostProcessedObjects(); return scope.CloseAndEscape(result); } -void ObjectDeserializer::FlushICache() { - DCHECK(deserializing_user_code()); - for (Code code : new_code_objects()) { - // Record all references to embedded objects in the new code object. -#ifndef V8_DISABLE_WRITE_BARRIERS - WriteBarrierForCode(code); -#endif - FlushInstructionCache(code.raw_instruction_start(), - code.raw_instruction_size()); - } -} - void ObjectDeserializer::CommitPostProcessedObjects() { - CHECK_LE(new_internalized_strings().size(), kMaxInt); - StringTable::EnsureCapacityForDeserialization( - isolate(), static_cast<int>(new_internalized_strings().size())); - for (Handle<String> string : new_internalized_strings()) { - DisallowHeapAllocation no_gc; - StringTableInsertionKey key(*string); - StringTable::AddKeyNoResize(isolate(), &key); + if (is_main_thread()) { + CHECK_LE(new_internalized_strings().size(), kMaxInt); + StringTable::EnsureCapacityForDeserialization( + isolate(), static_cast<int>(new_internalized_strings().size())); + for (Handle<String> string : new_internalized_strings()) { + DisallowHeapAllocation no_gc; + StringTableInsertionKey key(*string); + StringTable::AddKeyNoResize(isolate(), &key); + } + + for (Handle<JSArrayBuffer> buffer : new_off_heap_array_buffers()) { + uint32_t store_index = buffer->GetBackingStoreRefForDeserialization(); + auto bs = backing_store(store_index); + SharedFlag shared = + bs && bs->is_shared() ? SharedFlag::kShared : SharedFlag::kNotShared; + buffer->Setup(shared, bs); + } + } else { + CHECK_EQ(new_internalized_strings().size(), 0); + CHECK_EQ(new_off_heap_array_buffers().size(), 0); } - Heap* heap = isolate()->heap(); - Factory* factory = isolate()->factory(); for (Handle<Script> script : new_scripts()) { // Assign a new script id to avoid collision. - script->set_id(isolate()->GetNextScriptId()); + script->set_id(local_isolate()->GetNextScriptId()); LogScriptEvents(*script); // Add script to list. - Handle<WeakArrayList> list = factory->script_list(); - list = WeakArrayList::AddToEnd(isolate(), list, - MaybeObjectHandle::Weak(script)); - heap->SetRootScriptList(*list); - } - - for (Handle<JSArrayBuffer> buffer : new_off_heap_array_buffers()) { - uint32_t store_index = buffer->GetBackingStoreRefForDeserialization(); - auto bs = backing_store(store_index); - SharedFlag shared = - bs && bs->is_shared() ? SharedFlag::kShared : SharedFlag::kNotShared; - buffer->Setup(shared, bs); + if (is_main_thread()) { + Handle<WeakArrayList> list = isolate()->factory()->script_list(); + list = WeakArrayList::AddToEnd(isolate(), list, + MaybeObjectHandle::Weak(script)); + isolate()->heap()->SetRootScriptList(*list); + } else { + local_isolate().off_thread()->heap()->AddToScriptList(script); + } } } diff --git a/chromium/v8/src/snapshot/object-deserializer.h b/chromium/v8/src/snapshot/object-deserializer.h index ad7fecb0213..5003ffe1602 100644 --- a/chromium/v8/src/snapshot/object-deserializer.h +++ b/chromium/v8/src/snapshot/object-deserializer.h @@ -18,14 +18,16 @@ class ObjectDeserializer final : public Deserializer { public: static MaybeHandle<SharedFunctionInfo> DeserializeSharedFunctionInfo( Isolate* isolate, const SerializedCodeData* data, Handle<String> source); + static MaybeHandle<SharedFunctionInfo> DeserializeSharedFunctionInfoOffThread( + OffThreadIsolate* isolate, const SerializedCodeData* data, + Handle<String> source); private: explicit ObjectDeserializer(const SerializedCodeData* data); // Deserialize an object graph. Fail gracefully. - MaybeHandle<HeapObject> Deserialize(Isolate* isolate); + MaybeHandle<HeapObject> Deserialize(LocalIsolateWrapper isolate); - void FlushICache(); void LinkAllocationSites(); void CommitPostProcessedObjects(); }; diff --git a/chromium/v8/src/snapshot/read-only-deserializer.cc b/chromium/v8/src/snapshot/read-only-deserializer.cc index c1c96666ca6..7c8c44d9ea7 100644 --- a/chromium/v8/src/snapshot/read-only-deserializer.cc +++ b/chromium/v8/src/snapshot/read-only-deserializer.cc @@ -39,7 +39,7 @@ void ReadOnlyDeserializer::DeserializeInto(Isolate* isolate) { ReadOnlyRoots roots(isolate); roots.Iterate(this); - ro_heap->read_only_space()->RepairFreeListsAfterDeserialization(); + ro_heap->read_only_space()->RepairFreeSpacesAfterDeserialization(); // Deserialize the Read-only Object Cache. for (size_t i = 0;; ++i) { @@ -55,7 +55,7 @@ void ReadOnlyDeserializer::DeserializeInto(Isolate* isolate) { } if (FLAG_rehash_snapshot && can_rehash()) { - isolate_->heap()->InitializeHashSeed(); + isolate->heap()->InitializeHashSeed(); Rehash(); } } diff --git a/chromium/v8/src/snapshot/serializer-allocator.cc b/chromium/v8/src/snapshot/serializer-allocator.cc index a709715bdda..a1bd9f43eba 100644 --- a/chromium/v8/src/snapshot/serializer-allocator.cc +++ b/chromium/v8/src/snapshot/serializer-allocator.cc @@ -142,7 +142,8 @@ void SerializerAllocator::OutputStatistics() { PrintF(" Spaces (bytes):\n"); for (int space = 0; space < kNumberOfSpaces; space++) { - PrintF("%16s", Heap::GetSpaceName(static_cast<AllocationSpace>(space))); + PrintF("%16s", + BaseSpace::GetSpaceName(static_cast<AllocationSpace>(space))); } PrintF("\n"); diff --git a/chromium/v8/src/snapshot/serializer.cc b/chromium/v8/src/snapshot/serializer.cc index d443ff67a1e..a5ab4be1c01 100644 --- a/chromium/v8/src/snapshot/serializer.cc +++ b/chromium/v8/src/snapshot/serializer.cc @@ -53,13 +53,14 @@ void Serializer::OutputStatistics(const char* name) { #ifdef OBJECT_PRINT PrintF(" Instance types (count and bytes):\n"); -#define PRINT_INSTANCE_TYPE(Name) \ - for (int space = 0; space < kNumberOfSpaces; ++space) { \ - if (instance_type_count_[space][Name]) { \ - PrintF("%10d %10zu %-10s %s\n", instance_type_count_[space][Name], \ - instance_type_size_[space][Name], \ - Heap::GetSpaceName(static_cast<AllocationSpace>(space)), #Name); \ - } \ +#define PRINT_INSTANCE_TYPE(Name) \ + for (int space = 0; space < kNumberOfSpaces; ++space) { \ + if (instance_type_count_[space][Name]) { \ + PrintF("%10d %10zu %-10s %s\n", instance_type_count_[space][Name], \ + instance_type_size_[space][Name], \ + BaseSpace::GetSpaceName(static_cast<AllocationSpace>(space)), \ + #Name); \ + } \ } INSTANCE_TYPE_LIST(PRINT_INSTANCE_TYPE) #undef PRINT_INSTANCE_TYPE @@ -540,7 +541,7 @@ void Serializer::ObjectSerializer::Serialize() { if (object_.IsScript()) { // Clear cached line ends. - Object undefined = ReadOnlyRoots(serializer_->isolate()).undefined_value(); + Oddball undefined = ReadOnlyRoots(serializer_->isolate()).undefined_value(); Script::cast(object_).set_line_ends(undefined); } diff --git a/chromium/v8/src/snapshot/snapshot-utils.cc b/chromium/v8/src/snapshot/snapshot-utils.cc index 88e8e794c2f..eb2372372c9 100644 --- a/chromium/v8/src/snapshot/snapshot-utils.cc +++ b/chromium/v8/src/snapshot/snapshot-utils.cc @@ -17,7 +17,7 @@ uint32_t Checksum(Vector<const byte> payload) { MSAN_MEMORY_IS_INITIALIZED(payload.begin(), payload.length()); #endif // MEMORY_SANITIZER // Priming the adler32 call so it can see what CPU features are available. - adler32(0, NULL, 0); + adler32(0, nullptr, 0); return static_cast<uint32_t>(adler32(0, payload.begin(), payload.length())); } diff --git a/chromium/v8/src/snapshot/snapshot.cc b/chromium/v8/src/snapshot/snapshot.cc index 6c129a846a0..fd0866619c1 100644 --- a/chromium/v8/src/snapshot/snapshot.cc +++ b/chromium/v8/src/snapshot/snapshot.cc @@ -128,6 +128,17 @@ bool Snapshot::HasContextSnapshot(Isolate* isolate, size_t index) { return index < num_contexts; } +bool Snapshot::VersionIsValid(const v8::StartupData* data) { + char version[SnapshotImpl::kVersionStringLength]; + memset(version, 0, SnapshotImpl::kVersionStringLength); + CHECK_LT( + SnapshotImpl::kVersionStringOffset + SnapshotImpl::kVersionStringLength, + static_cast<uint32_t>(data->raw_size)); + Version::GetString(Vector<char>(version, SnapshotImpl::kVersionStringLength)); + return strncmp(version, data->data + SnapshotImpl::kVersionStringOffset, + SnapshotImpl::kVersionStringLength) == 0; +} + bool Snapshot::Initialize(Isolate* isolate) { if (!isolate->snapshot_available()) return false; RuntimeCallTimerScope rcs_timer(isolate, @@ -600,13 +611,12 @@ Vector<const byte> SnapshotImpl::ExtractContextData(const v8::StartupData* data, } void SnapshotImpl::CheckVersion(const v8::StartupData* data) { - char version[kVersionStringLength]; - memset(version, 0, kVersionStringLength); - CHECK_LT(kVersionStringOffset + kVersionStringLength, - static_cast<uint32_t>(data->raw_size)); - Version::GetString(Vector<char>(version, kVersionStringLength)); - if (strncmp(version, data->data + kVersionStringOffset, - kVersionStringLength) != 0) { + if (!Snapshot::VersionIsValid(data)) { + char version[kVersionStringLength]; + memset(version, 0, kVersionStringLength); + CHECK_LT(kVersionStringOffset + kVersionStringLength, + static_cast<uint32_t>(data->raw_size)); + Version::GetString(Vector<char>(version, kVersionStringLength)); FATAL( "Version mismatch between V8 binary and snapshot.\n" "# V8 binary version: %.*s\n" diff --git a/chromium/v8/src/snapshot/snapshot.h b/chromium/v8/src/snapshot/snapshot.h index e0ea02681cc..016e51799b9 100644 --- a/chromium/v8/src/snapshot/snapshot.h +++ b/chromium/v8/src/snapshot/snapshot.h @@ -91,6 +91,7 @@ class Snapshot : public AllStatic { static bool EmbedsScript(Isolate* isolate); V8_EXPORT_PRIVATE static bool VerifyChecksum(const v8::StartupData* data); static bool ExtractRehashability(const v8::StartupData* data); + static bool VersionIsValid(const v8::StartupData* data); // To be implemented by the snapshot source. static const v8::StartupData* DefaultSnapshotBlob(); diff --git a/chromium/v8/src/snapshot/startup-deserializer.cc b/chromium/v8/src/snapshot/startup-deserializer.cc index 095009b4e84..6d19c3a399a 100644 --- a/chromium/v8/src/snapshot/startup-deserializer.cc +++ b/chromium/v8/src/snapshot/startup-deserializer.cc @@ -74,7 +74,7 @@ void StartupDeserializer::DeserializeInto(Isolate* isolate) { } void StartupDeserializer::LogNewMapEvents() { - if (FLAG_trace_maps) LOG(isolate_, LogAllMaps()); + if (FLAG_trace_maps) LOG(isolate(), LogAllMaps()); } void StartupDeserializer::FlushICache() { |