From e24fa913272a0fd3fa31c380128f08c4a9ff4f13 Mon Sep 17 00:00:00 2001 From: Leszek Swirski Date: Tue, 20 Jul 2021 14:51:23 +0200 Subject: [PATCH] [offthread] Template deserializer on Isolate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the deserializer class templated on Isolate/LocalIsolate. This allows the ObjectSerializer to be split into a main-thread and offthread variant, with the latter taking a LocalIsolate. Eventually, we probably want to anyway split off the code-cache de/serializer to a separate implementation (for various reasons), and this the only one that wants off-thread finalization, and at this point the deserializer can revert back to being un-templated, used only for bootstrapping. However, this is the simplest way, for now, to enable off-thread deserialization. Bug: chromium:1075999 Change-Id: I49c0d2c5409f0aa58183673785296756c3714f22 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2562254 Reviewed-by: Jakob Gruber Reviewed-by: Dominik Inführ Commit-Queue: Leszek Swirski Cr-Commit-Position: refs/heads/master@{#75834} --- src/execution/isolate.h | 1 + src/execution/local-isolate-inl.h | 5 + src/execution/local-isolate.cc | 7 + src/execution/local-isolate.h | 12 + src/heap/heap-inl.h | 13 +- src/heap/heap.h | 14 +- src/heap/local-heap-inl.h | 8 + src/heap/local-heap.h | 7 + src/logging/local-logger.cc | 5 + src/logging/local-logger.h | 3 + src/objects/heap-object.h | 3 +- src/objects/js-array-buffer.h | 1 + src/objects/name-inl.h | 9 + src/objects/name.h | 6 + src/objects/objects.cc | 9 +- src/objects/string-comparator.cc | 24 +- src/objects/string-comparator.h | 9 +- src/objects/string-table.cc | 2 + src/objects/string.cc | 77 ++++-- src/objects/string.h | 7 +- src/objects/swiss-name-dictionary.cc | 7 +- src/objects/swiss-name-dictionary.h | 3 +- src/snapshot/code-serializer.cc | 33 ++- src/snapshot/context-deserializer.h | 3 +- src/snapshot/deserializer.cc | 327 ++++++++++++++++---------- src/snapshot/deserializer.h | 36 ++- src/snapshot/object-deserializer.cc | 60 ++++- src/snapshot/object-deserializer.h | 21 +- src/snapshot/read-only-deserializer.h | 2 +- src/snapshot/startup-deserializer.cc | 2 +- src/snapshot/startup-deserializer.h | 2 +- 31 files changed, 503 insertions(+), 215 deletions(-) diff --git a/src/execution/isolate.h b/src/execution/isolate.h index 585ee491d8..f10e9ec0b4 100644 --- a/src/execution/isolate.h +++ b/src/execution/isolate.h @@ -1768,6 +1768,7 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory { return main_thread_local_isolate_.get(); } + Isolate* AsIsolate() { return this; } LocalIsolate* AsLocalIsolate() { return main_thread_local_isolate(); } LocalHeap* main_thread_local_heap(); diff --git a/src/execution/local-isolate-inl.h b/src/execution/local-isolate-inl.h index 59a7b1f5e4..ca7c119b6b 100644 --- a/src/execution/local-isolate-inl.h +++ b/src/execution/local-isolate-inl.h @@ -22,6 +22,11 @@ Object LocalIsolate::root(RootIndex index) const { return isolate_->root(index); } +Handle LocalIsolate::root_handle(RootIndex index) const { + DCHECK(RootsTable::IsImmortalImmovable(index)); + return isolate_->root_handle(index); +} + } // namespace internal } // namespace v8 diff --git a/src/execution/local-isolate.cc b/src/execution/local-isolate.cc index 20a4344cfa..c56bf5064d 100644 --- a/src/execution/local-isolate.cc +++ b/src/execution/local-isolate.cc @@ -26,6 +26,13 @@ LocalIsolate::LocalIsolate(Isolate* isolate, ThreadKind kind, LocalIsolate::~LocalIsolate() = default; +void LocalIsolate::RegisterDeserializerStarted() { + return isolate_->RegisterDeserializerStarted(); +} +void LocalIsolate::RegisterDeserializerFinished() { + return isolate_->RegisterDeserializerFinished(); +} + int LocalIsolate::GetNextScriptId() { return isolate_->GetNextScriptId(); } #if V8_SFI_HAS_UNIQUE_ID diff --git a/src/execution/local-isolate.h b/src/execution/local-isolate.h index 5392534d66..ca42d53ae5 100644 --- a/src/execution/local-isolate.h +++ b/src/execution/local-isolate.h @@ -48,11 +48,14 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory { OFFSET_OF(LocalIsolate, heap_)); } + bool is_main_thread() { return heap()->is_main_thread(); } + LocalHeap* heap() { return &heap_; } inline Address cage_base() const; inline ReadOnlyHeap* read_only_heap() const; inline Object root(RootIndex index) const; + inline Handle root_handle(RootIndex index) const; StringTable* string_table() const { return isolate_->string_table(); } base::SharedMutex* internalized_string_access() { @@ -67,6 +70,9 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory { bool has_pending_exception() const { return false; } + void RegisterDeserializerStarted(); + void RegisterDeserializerFinished(); + template Handle Throw(Handle exception) { UNREACHABLE(); @@ -89,6 +95,12 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory { bool is_main_thread() const { return heap_.is_main_thread(); } + // AsIsolate is only allowed on the main-thread. + Isolate* AsIsolate() { + DCHECK(is_main_thread()); + DCHECK_EQ(ThreadId::Current(), isolate_->thread_id()); + return isolate_; + } LocalIsolate* AsLocalIsolate() { return this; } private: diff --git a/src/heap/heap-inl.h b/src/heap/heap-inl.h index 2771635af0..9550b43c9b 100644 --- a/src/heap/heap-inl.h +++ b/src/heap/heap-inl.h @@ -335,14 +335,11 @@ HeapObject Heap::AllocateRawWith(int size, AllocationType allocation, UNREACHABLE(); } -Address Heap::DeserializerAllocate(AllocationType type, int size_in_bytes) { - if (V8_ENABLE_THIRD_PARTY_HEAP_BOOL) { - AllocationResult allocation = tp_heap_->Allocate( - size_in_bytes, type, AllocationAlignment::kDoubleAligned); - return allocation.ToObjectChecked().ptr(); - } else { - UNIMPLEMENTED(); // unimplemented - } +Address Heap::AllocateRawOrFail(int size, AllocationType allocation, + AllocationOrigin origin, + AllocationAlignment alignment) { + return AllocateRawWith(size, allocation, origin, alignment) + .address(); } void Heap::OnAllocationEvent(HeapObject object, int size_in_bytes) { diff --git a/src/heap/heap.h b/src/heap/heap.h index 701db2897b..e65d949557 100644 --- a/src/heap/heap.h +++ b/src/heap/heap.h @@ -567,11 +567,6 @@ class Heap { V8_EXPORT_PRIVATE static bool IsLargeObject(HeapObject object); - // This method supports the deserialization allocator. All allocations - // are word-aligned. The method should never fail to allocate since the - // total space requirements of the deserializer are known at build time. - inline Address DeserializerAllocate(AllocationType type, int size_in_bytes); - // Trim the given array from the left. Note that this relocates the object // start and hence is only valid if there is only a single reference to it. V8_EXPORT_PRIVATE FixedArrayBase LeftTrimFixedArray(FixedArrayBase obj, @@ -2105,6 +2100,12 @@ class Heap { AllocationOrigin origin = AllocationOrigin::kRuntime, AllocationAlignment alignment = kWordAligned); + // Call AllocateRawWith with kRetryOrFail. Matches the method in LocalHeap. + V8_WARN_UNUSED_RESULT inline Address AllocateRawOrFail( + int size, AllocationType allocation, + AllocationOrigin origin = AllocationOrigin::kRuntime, + AllocationAlignment alignment = kWordAligned); + // This method will try to perform an allocation of a given size of a given // AllocationType. If the allocation fails, a regular full garbage collection // is triggered and the allocation is retried. This is performed multiple @@ -2527,6 +2528,7 @@ class Heap { // The allocator interface. friend class Factory; + template friend class Deserializer; // The Isolate constructs us. @@ -2580,8 +2582,6 @@ class V8_NODISCARD AlwaysAllocateScope { private: friend class AlwaysAllocateScopeForTesting; - friend class Deserializer; - friend class DeserializerAllocator; friend class Evacuator; friend class Heap; friend class Isolate; diff --git a/src/heap/local-heap-inl.h b/src/heap/local-heap-inl.h index 01a869f9d4..92c8f4b845 100644 --- a/src/heap/local-heap-inl.h +++ b/src/heap/local-heap-inl.h @@ -10,6 +10,7 @@ #include "src/common/assert-scope.h" #include "src/handles/persistent-handles.h" #include "src/heap/concurrent-allocator-inl.h" +#include "src/heap/heap.h" #include "src/heap/local-heap.h" namespace v8 { @@ -53,6 +54,13 @@ Address LocalHeap::AllocateRawOrFail(int object_size, AllocationType type, alignment); } +void LocalHeap::CreateFillerObjectAt(Address addr, int size, + ClearRecordedSlots clear_slots_mode) { + DCHECK_EQ(clear_slots_mode, ClearRecordedSlots::kNo); + heap()->CreateFillerObjectAtBackground( + addr, size, ClearFreedMemoryMode::kDontClearFreedMemory); +} + } // namespace internal } // namespace v8 diff --git a/src/heap/local-heap.h b/src/heap/local-heap.h index e96b3e7aa0..4819dfd826 100644 --- a/src/heap/local-heap.h +++ b/src/heap/local-heap.h @@ -130,7 +130,14 @@ class V8_EXPORT_PRIVATE LocalHeap { AllocationOrigin origin = AllocationOrigin::kRuntime, AllocationAlignment alignment = kWordAligned); + inline void CreateFillerObjectAt(Address addr, int size, + ClearRecordedSlots clear_slots_mode); + bool is_main_thread() const { return is_main_thread_; } + bool deserialization_complete() const { + return heap_->deserialization_complete(); + } + ReadOnlySpace* read_only_space() { return heap_->read_only_space(); } // Requests GC and blocks until the collection finishes. bool TryPerformCollection(); diff --git a/src/logging/local-logger.cc b/src/logging/local-logger.cc index bd0a1598e3..1d841c9600 100644 --- a/src/logging/local-logger.cc +++ b/src/logging/local-logger.cc @@ -5,6 +5,7 @@ #include "src/logging/local-logger.h" #include "src/execution/isolate.h" +#include "src/objects/map.h" namespace v8 { namespace internal { @@ -27,5 +28,9 @@ void LocalLogger::CodeLinePosInfoRecordEvent(Address code_start, logger_->CodeLinePosInfoRecordEvent(code_start, source_position_table); } +void LocalLogger::MapCreate(Map map) { logger_->MapCreate(map); } + +void LocalLogger::MapDetails(Map map) { logger_->MapDetails(map); } + } // namespace internal } // namespace v8 diff --git a/src/logging/local-logger.h b/src/logging/local-logger.h index a727013e92..7ce5ce064f 100644 --- a/src/logging/local-logger.h +++ b/src/logging/local-logger.h @@ -25,6 +25,9 @@ class LocalLogger { void CodeLinePosInfoRecordEvent(Address code_start, ByteArray source_position_table); + void MapCreate(Map map); + void MapDetails(Map map); + private: Logger* logger_; bool is_logging_; diff --git a/src/objects/heap-object.h b/src/objects/heap-object.h index 0ee86603ce..94fdf7eeb1 100644 --- a/src/objects/heap-object.h +++ b/src/objects/heap-object.h @@ -195,7 +195,8 @@ class HeapObject : public Object { bool CanBeRehashed() const; // Rehash the object based on the layout inferred from its map. - void RehashBasedOnMap(Isolate* isolate); + template + void RehashBasedOnMap(IsolateT* isolate); // Layout description. #define HEAP_OBJECT_FIELDS(V) \ diff --git a/src/objects/js-array-buffer.h b/src/objects/js-array-buffer.h index f723380772..69378eaa99 100644 --- a/src/objects/js-array-buffer.h +++ b/src/objects/js-array-buffer.h @@ -364,6 +364,7 @@ class JSTypedArray #endif private: + template friend class Deserializer; friend class Factory; diff --git a/src/objects/name-inl.h b/src/objects/name-inl.h index 93c0cd3fa9..a1f4eb5368 100644 --- a/src/objects/name-inl.h +++ b/src/objects/name-inl.h @@ -10,6 +10,7 @@ #include "src/objects/map-inl.h" #include "src/objects/name.h" #include "src/objects/primitive-heap-object-inl.h" +#include "src/objects/string-inl.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" @@ -97,6 +98,14 @@ uint32_t Name::EnsureHash() { return String::cast(*this).ComputeAndSetHash(); } +uint32_t Name::EnsureHash(const SharedStringAccessGuardIfNeeded& access_guard) { + // Fast case: has hash code already been computed? + uint32_t field = raw_hash_field(); + if (IsHashFieldComputed(field)) return field >> kHashShift; + // Slow case: compute hash code and set it. Has to be a string. + return String::cast(*this).ComputeAndSetHash(access_guard); +} + uint32_t Name::hash() const { uint32_t field = raw_hash_field(); DCHECK(IsHashFieldComputed(field)); diff --git a/src/objects/name.h b/src/objects/name.h index 1d4981f85c..cbd7065367 100644 --- a/src/objects/name.h +++ b/src/objects/name.h @@ -18,6 +18,8 @@ namespace internal { #include "torque-generated/src/objects/name-tq.inc" +class SharedStringAccessGuardIfNeeded; + // The Name abstract class captures anything that can be used as a property // name, i.e., strings and symbols. All names store a hash value. class Name : public TorqueGeneratedName { @@ -27,7 +29,11 @@ class Name : public TorqueGeneratedName { // Returns a hash value used for the property table. Ensures that the hash // value is computed. + // + // The overload without SharedStringAccessGuardIfNeeded can only be called on + // the main thread. inline uint32_t EnsureHash(); + inline uint32_t EnsureHash(const SharedStringAccessGuardIfNeeded&); // Returns a hash value used for the property table (same as Hash()), assumes // the hash is already computed. diff --git a/src/objects/objects.cc b/src/objects/objects.cc index 6d051524b5..bff3058345 100644 --- a/src/objects/objects.cc +++ b/src/objects/objects.cc @@ -2363,7 +2363,8 @@ bool HeapObject::CanBeRehashed() const { } } -void HeapObject::RehashBasedOnMap(Isolate* isolate) { +template +void HeapObject::RehashBasedOnMap(IsolateT* isolate) { switch (map().instance_type()) { case HASH_TABLE_TYPE: UNREACHABLE(); @@ -2399,11 +2400,11 @@ void HeapObject::RehashBasedOnMap(Isolate* isolate) { case ORDERED_HASH_SET_TYPE: UNREACHABLE(); // We'll rehash from the JSMap or JSSet referencing them. case JS_MAP_TYPE: { - JSMap::cast(*this).Rehash(isolate); + JSMap::cast(*this).Rehash(isolate->AsIsolate()); break; } case JS_SET_TYPE: { - JSSet::cast(*this).Rehash(isolate); + JSSet::cast(*this).Rehash(isolate->AsIsolate()); break; } case SMALL_ORDERED_NAME_DICTIONARY_TYPE: @@ -2419,6 +2420,8 @@ void HeapObject::RehashBasedOnMap(Isolate* isolate) { UNREACHABLE(); } } +template void HeapObject::RehashBasedOnMap(Isolate* isolate); +template void HeapObject::RehashBasedOnMap(LocalIsolate* isolate); bool HeapObject::IsExternal(Isolate* isolate) const { return map().FindRootMap(isolate) == isolate->heap()->external_map(); diff --git a/src/objects/string-comparator.cc b/src/objects/string-comparator.cc index 79ec348c71..3330f772ff 100644 --- a/src/objects/string-comparator.cc +++ b/src/objects/string-comparator.cc @@ -9,17 +9,19 @@ namespace v8 { namespace internal { -void StringComparator::State::Init(String string) { - ConsString cons_string = String::VisitFlat(this, string); +void StringComparator::State::Init( + String string, const SharedStringAccessGuardIfNeeded& access_guard) { + ConsString cons_string = String::VisitFlat(this, string, 0, access_guard); iter_.Reset(cons_string); if (!cons_string.is_null()) { int offset; string = iter_.Next(&offset); - String::VisitFlat(this, string, offset); + String::VisitFlat(this, string, offset, access_guard); } } -void StringComparator::State::Advance(int consumed) { +void StringComparator::State::Advance( + int consumed, const SharedStringAccessGuardIfNeeded& access_guard) { DCHECK(consumed <= length_); // Still in buffer. if (length_ != consumed) { @@ -36,13 +38,15 @@ void StringComparator::State::Advance(int consumed) { String next = iter_.Next(&offset); DCHECK_EQ(0, offset); DCHECK(!next.is_null()); - String::VisitFlat(this, next); + String::VisitFlat(this, next, 0, access_guard); } -bool StringComparator::Equals(String string_1, String string_2) { +bool StringComparator::Equals( + String string_1, String string_2, + const SharedStringAccessGuardIfNeeded& access_guard) { int length = string_1.length(); - state_1_.Init(string_1); - state_2_.Init(string_2); + state_1_.Init(string_1, access_guard); + state_2_.Init(string_2, access_guard); while (true) { int to_check = std::min(state_1_.length_, state_2_.length_); DCHECK(to_check > 0 && to_check <= length); @@ -65,8 +69,8 @@ bool StringComparator::Equals(String string_1, String string_2) { length -= to_check; // Exit condition. Strings are equal. if (length == 0) return true; - state_1_.Advance(to_check); - state_2_.Advance(to_check); + state_1_.Advance(to_check, access_guard); + state_2_.Advance(to_check, access_guard); } } diff --git a/src/objects/string-comparator.h b/src/objects/string-comparator.h index 59acd42087..8f3420945a 100644 --- a/src/objects/string-comparator.h +++ b/src/objects/string-comparator.h @@ -20,7 +20,8 @@ class StringComparator { State(const State&) = delete; State& operator=(const State&) = delete; - void Init(String string); + void Init(String string, + const SharedStringAccessGuardIfNeeded& access_guard); inline void VisitOneByteString(const uint8_t* chars, int length) { is_one_byte_ = true; @@ -34,7 +35,8 @@ class StringComparator { length_ = length; } - void Advance(int consumed); + void Advance(int consumed, + const SharedStringAccessGuardIfNeeded& access_guard); ConsStringIterator iter_; bool is_one_byte_; @@ -57,7 +59,8 @@ class StringComparator { return CompareCharsEqual(a, b, to_check); } - bool Equals(String string_1, String string_2); + bool Equals(String string_1, String string_2, + const SharedStringAccessGuardIfNeeded& access_guard); private: State state_1_; diff --git a/src/objects/string-table.cc b/src/objects/string-table.cc index de275b8977..cff50bea79 100644 --- a/src/objects/string-table.cc +++ b/src/objects/string-table.cc @@ -510,6 +510,8 @@ template Handle StringTable::LookupKey(LocalIsolate* isolate, template Handle StringTable::LookupKey(Isolate* isolate, StringTableInsertionKey* key); +template Handle StringTable::LookupKey(LocalIsolate* isolate, + StringTableInsertionKey* key); StringTable::Data* StringTable::EnsureCapacity(PtrComprCageBase cage_base, int additional_elements) { diff --git a/src/objects/string.cc b/src/objects/string.cc index 7af83a5175..4b18ee3d05 100644 --- a/src/objects/string.cc +++ b/src/objects/string.cc @@ -10,6 +10,8 @@ #include "src/execution/thread-id.h" #include "src/handles/handles-inl.h" #include "src/heap/heap-inl.h" +#include "src/heap/local-factory-inl.h" +#include "src/heap/local-heap-inl.h" #include "src/heap/memory-chunk.h" #include "src/heap/read-only-heap.h" #include "src/numbers/conversions.h" @@ -93,26 +95,32 @@ void MigrateExternalStringResource(Isolate* isolate, ExternalString from, } } +void MigrateExternalString(Isolate* isolate, String string, + String internalized) { + if (internalized.IsExternalOneByteString()) { + MigrateExternalStringResource(isolate, ExternalString::cast(string), + ExternalOneByteString::cast(internalized)); + } else if (internalized.IsExternalTwoByteString()) { + MigrateExternalStringResource(isolate, ExternalString::cast(string), + ExternalTwoByteString::cast(internalized)); + } else { + // If the external string is duped into an existing non-external + // internalized string, free its resource (it's about to be rewritten + // into a ThinString below). + isolate->heap()->FinalizeExternalString(string); + } +} + } // namespace -void String::MakeThin(Isolate* isolate, String internalized) { +template +void String::MakeThin(IsolateT* isolate, String internalized) { DisallowGarbageCollection no_gc; DCHECK_NE(*this, internalized); DCHECK(internalized.IsInternalizedString()); if (this->IsExternalString()) { - if (internalized.IsExternalOneByteString()) { - MigrateExternalStringResource(isolate, ExternalString::cast(*this), - ExternalOneByteString::cast(internalized)); - } else if (internalized.IsExternalTwoByteString()) { - MigrateExternalStringResource(isolate, ExternalString::cast(*this), - ExternalTwoByteString::cast(internalized)); - } else { - // If the external string is duped into an existing non-external - // internalized string, free its resource (it's about to be rewritten - // into a ThinString below). - isolate->heap()->FinalizeExternalString(*this); - } + MigrateExternalString(isolate->AsIsolate(), *this, internalized); } bool has_pointers = StringShape(*this).IsIndirect(); @@ -131,9 +139,8 @@ void String::MakeThin(Isolate* isolate, String internalized) { Address thin_end = thin.address() + ThinString::kSize; int size_delta = old_size - ThinString::kSize; if (size_delta != 0) { - Heap* heap = isolate->heap(); - if (!heap->IsLargeObject(thin)) { - heap->CreateFillerObjectAt( + if (!Heap::IsLargeObject(thin)) { + isolate->heap()->CreateFillerObjectAt( thin_end, size_delta, has_pointers ? ClearRecordedSlots::kYes : ClearRecordedSlots::kNo); } else { @@ -144,6 +151,9 @@ void String::MakeThin(Isolate* isolate, String internalized) { } } +template void String::MakeThin(Isolate* isolate, String internalized); +template void String::MakeThin(LocalIsolate* isolate, String internalized); + bool String::MakeExternal(v8::String::ExternalStringResource* resource) { // Disallow garbage collection to avoid possible GC vs string access deadlock. DisallowGarbageCollection no_gc; @@ -633,6 +643,7 @@ std::unique_ptr String::ToCString(AllowNullsFlag allow_nulls, return ToCString(allow_nulls, robust_flag, 0, -1, length_return); } +// static template void String::WriteToFlat(String source, sinkchar* sink, int from, int to) { DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(source)); @@ -640,6 +651,7 @@ void String::WriteToFlat(String source, sinkchar* sink, int from, int to) { SharedStringAccessGuardIfNeeded::NotNeeded()); } +// static template void String::WriteToFlat(String source, sinkchar* sink, int from, int to, const SharedStringAccessGuardIfNeeded& access_guard) { @@ -794,6 +806,13 @@ template Handle String::CalculateLineEnds(LocalIsolate* isolate, bool include_ending_line); bool String::SlowEquals(String other) const { + DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this)); + DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(other)); + return SlowEquals(other, SharedStringAccessGuardIfNeeded::NotNeeded()); +} + +bool String::SlowEquals( + String other, const SharedStringAccessGuardIfNeeded& access_guard) const { DisallowGarbageCollection no_gc; // Fast check: negative check with lengths. int len = length(); @@ -833,16 +852,18 @@ bool String::SlowEquals(String other) const { // We know the strings are both non-empty. Compare the first chars // before we try to flatten the strings. - if (this->Get(0) != other.Get(0)) return false; + if (this->Get(0, access_guard) != other.Get(0, access_guard)) return false; if (IsSeqOneByteString() && other.IsSeqOneByteString()) { - const uint8_t* str1 = SeqOneByteString::cast(*this).GetChars(no_gc); - const uint8_t* str2 = SeqOneByteString::cast(other).GetChars(no_gc); + const uint8_t* str1 = + SeqOneByteString::cast(*this).GetChars(no_gc, access_guard); + const uint8_t* str2 = + SeqOneByteString::cast(other).GetChars(no_gc, access_guard); return CompareCharsEqual(str1, str2, len); } StringComparator comparator; - return comparator.Equals(*this, other); + return comparator.Equals(*this, other, access_guard); } // static @@ -1326,7 +1347,8 @@ bool String::HasOneBytePrefix(base::Vector str) { namespace { template -uint32_t HashString(String string, size_t start, int length, uint64_t seed) { +uint32_t HashString(String string, size_t start, int length, uint64_t seed, + const SharedStringAccessGuardIfNeeded& access_guard) { DisallowGarbageCollection no_gc; if (length > String::kMaxHashCalcLength) { @@ -1340,10 +1362,10 @@ uint32_t HashString(String string, size_t start, int length, uint64_t seed) { DCHECK_EQ(0, start); DCHECK(!string.IsFlat()); buffer.reset(new Char[length]); - String::WriteToFlat(string, buffer.get(), 0, length); + String::WriteToFlat(string, buffer.get(), 0, length, access_guard); chars = buffer.get(); } else { - chars = string.GetChars(no_gc) + start; + chars = string.GetChars(no_gc, access_guard) + start; } return StringHasher::HashSequentialString(chars, length, seed); @@ -1352,6 +1374,11 @@ uint32_t HashString(String string, size_t start, int length, uint64_t seed) { } // namespace uint32_t String::ComputeAndSetHash() { + DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this)); + return ComputeAndSetHash(SharedStringAccessGuardIfNeeded::NotNeeded()); +} +uint32_t String::ComputeAndSetHash( + const SharedStringAccessGuardIfNeeded& access_guard) { DisallowGarbageCollection no_gc; // Should only be called if hash code has not yet been computed. DCHECK(!HasHashCode()); @@ -1377,8 +1404,8 @@ uint32_t String::ComputeAndSetHash() { } uint32_t raw_hash_field = string.IsOneByteRepresentation() - ? HashString(string, start, length(), seed) - : HashString(string, start, length(), seed); + ? HashString(string, start, length(), seed, access_guard) + : HashString(string, start, length(), seed, access_guard); set_raw_hash_field(raw_hash_field); // Check the hash code is there. diff --git a/src/objects/string.h b/src/objects/string.h index a3083a4bc4..3bb3ba1d6e 100644 --- a/src/objects/string.h +++ b/src/objects/string.h @@ -172,7 +172,8 @@ class String : public TorqueGeneratedString { friend class IterableSubString; }; - void MakeThin(Isolate* isolate, String canonical); + template + void MakeThin(IsolateT* isolate, String canonical); template V8_INLINE base::Vector GetCharVector( @@ -570,6 +571,8 @@ class String : public TorqueGeneratedString { // Slow case of String::Equals. This implementation works on any strings // but it is most efficient on strings that are almost flat. V8_EXPORT_PRIVATE bool SlowEquals(String other) const; + V8_EXPORT_PRIVATE bool SlowEquals( + String other, const SharedStringAccessGuardIfNeeded&) const; V8_EXPORT_PRIVATE static bool SlowEquals(Isolate* isolate, Handle one, Handle two); @@ -580,6 +583,8 @@ class String : public TorqueGeneratedString { // Compute and set the hash code. V8_EXPORT_PRIVATE uint32_t ComputeAndSetHash(); + V8_EXPORT_PRIVATE uint32_t + ComputeAndSetHash(const SharedStringAccessGuardIfNeeded&); TQ_OBJECT_CONSTRUCTORS(String) }; diff --git a/src/objects/swiss-name-dictionary.cc b/src/objects/swiss-name-dictionary.cc index 9cf3421ca4..f464d341f9 100644 --- a/src/objects/swiss-name-dictionary.cc +++ b/src/objects/swiss-name-dictionary.cc @@ -207,7 +207,8 @@ Handle SwissNameDictionary::Shrink( // storing it somewhere in the main table or the meta table, for those // SwissNameDictionaries that we know will be in-place rehashed, most notably // those stored in the snapshot. -void SwissNameDictionary::Rehash(Isolate* isolate) { +template +void SwissNameDictionary::Rehash(IsolateT* isolate) { DisallowHeapAllocation no_gc; struct Entry { @@ -307,6 +308,10 @@ template V8_EXPORT_PRIVATE Handle SwissNameDictionary::Rehash(Isolate* isolate, Handle table, int new_capacity); +template V8_EXPORT_PRIVATE void SwissNameDictionary::Rehash( + LocalIsolate* isolate); +template V8_EXPORT_PRIVATE void SwissNameDictionary::Rehash(Isolate* isolate); + constexpr int SwissNameDictionary::kInitialCapacity; constexpr int SwissNameDictionary::kGroupWidth; diff --git a/src/objects/swiss-name-dictionary.h b/src/objects/swiss-name-dictionary.h index 620e129227..42613e619c 100644 --- a/src/objects/swiss-name-dictionary.h +++ b/src/objects/swiss-name-dictionary.h @@ -133,7 +133,8 @@ class V8_EXPORT_PRIVATE SwissNameDictionary : public HeapObject { static Handle Rehash(IsolateT* isolate, Handle table, int new_capacity); - void Rehash(Isolate* isolate); + template + void Rehash(IsolateT* isolate); inline void SetHash(int hash); inline int Hash(); diff --git a/src/snapshot/code-serializer.cc b/src/snapshot/code-serializer.cc index dc31572c14..642b0a0281 100644 --- a/src/snapshot/code-serializer.cc +++ b/src/snapshot/code-serializer.cc @@ -4,12 +4,16 @@ #include "src/snapshot/code-serializer.h" +#include + #include "src/base/platform/platform.h" #include "src/codegen/macro-assembler.h" #include "src/common/globals.h" #include "src/debug/debug.h" +#include "src/handles/persistent-handles.h" #include "src/heap/heap-inl.h" #include "src/heap/local-factory-inl.h" +#include "src/heap/parked-scope.h" #include "src/logging/counters.h" #include "src/logging/log.h" #include "src/logging/runtime-call-stats-scope.h" @@ -277,18 +281,39 @@ class StressOffThreadDeserializeThread final : public base::Thread { void Run() final { LocalIsolate local_isolate(isolate_, ThreadKind::kBackground); + UnparkedScope unparked_scope(&local_isolate); + LocalHandleScope handle_scope(&local_isolate); + MaybeHandle local_maybe_result = - ObjectDeserializer::DeserializeSharedFunctionInfoOffThread( - &local_isolate, scd_, local_isolate.factory()->empty_string()); + OffThreadObjectDeserializer::DeserializeSharedFunctionInfo( + &local_isolate, scd_, &scripts_); maybe_result_ = local_isolate.heap()->NewPersistentMaybeHandle(local_maybe_result); + + persistent_handles_ = local_isolate.heap()->DetachPersistentHandles(); + } + + void Finalize(Isolate* isolate) { + Handle list = isolate->factory()->script_list(); + for (Handle