From 7437c69093f96126a801ea0a68f73f11d9fe19fb Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Wed, 26 Jan 2022 20:04:18 -0800 Subject: [PATCH] [snapshot] Support shared string table with --stress-snapshot Bug: v8:12584, v8:12007 Change-Id: Iac3c8b1c5935142742dddc7e12293fd7640c06a3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3419736 Auto-Submit: Shu-yu Guo Reviewed-by: Leszek Swirski Commit-Queue: Leszek Swirski Cr-Commit-Position: refs/heads/main@{#78804} --- src/snapshot/read-only-serializer.cc | 2 +- src/snapshot/serializer.h | 5 +++-- src/snapshot/shared-heap-serializer.cc | 31 ++++++++++++++++++++++---- src/snapshot/shared-heap-serializer.h | 2 ++ src/snapshot/snapshot.cc | 12 ++++++++-- src/snapshot/snapshot.h | 18 ++++++++------- 6 files changed, 53 insertions(+), 17 deletions(-) diff --git a/src/snapshot/read-only-serializer.cc b/src/snapshot/read-only-serializer.cc index 029f24c300..35a62aa515 100644 --- a/src/snapshot/read-only-serializer.cc +++ b/src/snapshot/read-only-serializer.cc @@ -74,7 +74,7 @@ void ReadOnlySerializer::SerializeReadOnlyRoots() { ReadOnlyRoots(isolate()).Iterate(this); - if (reconstruct_read_only_object_cache_for_testing()) { + if (reconstruct_read_only_and_shared_object_caches_for_testing()) { ReconstructReadOnlyObjectCacheForTesting(); } } diff --git a/src/snapshot/serializer.h b/src/snapshot/serializer.h index 44c5e49eca..5cba5cdb9f 100644 --- a/src/snapshot/serializer.h +++ b/src/snapshot/serializer.h @@ -309,8 +309,9 @@ class Serializer : public SerializerDeserializer { return (flags_ & Snapshot::kAllowActiveIsolateForTesting) != 0; } - bool reconstruct_read_only_object_cache_for_testing() const { - return (flags_ & Snapshot::kReconstructReadOnlyObjectCacheForTesting) != 0; + bool reconstruct_read_only_and_shared_object_caches_for_testing() const { + return (flags_ & + Snapshot::kReconstructReadOnlyAndSharedObjectCachesForTesting) != 0; } private: diff --git a/src/snapshot/shared-heap-serializer.cc b/src/snapshot/shared-heap-serializer.cc index 512a11d34e..e12e8cf55a 100644 --- a/src/snapshot/shared-heap-serializer.cc +++ b/src/snapshot/shared-heap-serializer.cc @@ -65,10 +65,6 @@ void SharedHeapSerializer::FinalizeSerialization() { Pad(); #ifdef DEBUG - // During snapshotting there is no shared heap. - CHECK(!isolate()->is_shared()); - CHECK_NULL(isolate()->shared_isolate()); - // Check that all serialized object are in shared heap and not RO. RO objects // should be in the RO snapshot. IdentityMap::IteratableScope it_scope( @@ -90,6 +86,20 @@ bool SharedHeapSerializer::SerializeUsingSharedHeapObjectCache( SnapshotByteSink* sink, Handle obj) { if (!ShouldBeInSharedHeapObjectCache(*obj)) return false; int cache_index = SerializeInObjectCache(obj); + + // When testing deserialization of a snapshot from a live isolate, the shared + // object cache needs to be extended because the live isolate may have had new + // internalized strings that were not present in the startup snapshot to be + // serialized. + if (reconstruct_read_only_and_shared_object_caches_for_testing()) { + const size_t existing_cache_size = + isolate()->shared_heap_object_cache()->size(); + DCHECK_LE(base::checked_cast(cache_index), existing_cache_size); + if (base::checked_cast(cache_index) == existing_cache_size) { + isolate()->shared_heap_object_cache()->push_back(*obj); + } + } + sink->Put(kSharedHeapObjectCache, "SharedHeapObjectCache"); sink->PutInt(cache_index, "shared_heap_object_cache_index"); return true; @@ -170,5 +180,18 @@ void SharedHeapSerializer::SerializeObjectImpl(Handle obj) { #endif } +void SharedHeapSerializer:: + ReconstructSharedHeapObjectCacheForTestingIfNeeded() { + if (!reconstruct_read_only_and_shared_object_caches_for_testing()) return; + std::vector* cache = isolate()->shared_heap_object_cache(); + DCHECK_EQ(isolate()->shared_isolate()->shared_heap_object_cache(), cache); + for (size_t i = 0, size = cache->size(); i < size; i++) { + Handle obj(HeapObject::cast(cache->at(i)), isolate()); + int cache_index = SerializeInObjectCache(obj); + USE(cache_index); + DCHECK_EQ(cache_index, i); + } +} + } // namespace internal } // namespace v8 diff --git a/src/snapshot/shared-heap-serializer.h b/src/snapshot/shared-heap-serializer.h index 8f4c46c29c..716920e90e 100644 --- a/src/snapshot/shared-heap-serializer.h +++ b/src/snapshot/shared-heap-serializer.h @@ -43,6 +43,8 @@ class V8_EXPORT_PRIVATE SharedHeapSerializer : public RootsSerializer { bool SerializeUsingSharedHeapObjectCache(SnapshotByteSink* sink, Handle obj); + void ReconstructSharedHeapObjectCacheForTestingIfNeeded(); + static bool CanBeInSharedOldSpace(HeapObject obj); static bool ShouldBeInSharedHeapObjectCache(HeapObject obj); diff --git a/src/snapshot/snapshot.cc b/src/snapshot/snapshot.cc index 2a2828732a..99dc4a0244 100644 --- a/src/snapshot/snapshot.cc +++ b/src/snapshot/snapshot.cc @@ -313,13 +313,17 @@ void Snapshot::SerializeDeserializeAndVerifyForTesting( // Test serialization. { GlobalSafepointScope global_safepoint(isolate); + base::Optional shared_isolate_safepoint_scope; + if (Isolate* shared_isolate = isolate->shared_isolate()) { + shared_isolate_safepoint_scope.emplace(shared_isolate->heap()); + } DisallowGarbageCollection no_gc; Snapshot::SerializerFlags flags( Snapshot::kAllowUnknownExternalReferencesForTesting | Snapshot::kAllowActiveIsolateForTesting | - (ReadOnlyHeap::IsReadOnlySpaceShared() - ? Snapshot::kReconstructReadOnlyObjectCacheForTesting + ((isolate->shared_isolate() || ReadOnlyHeap::IsReadOnlySpaceShared()) + ? Snapshot::kReconstructReadOnlyAndSharedObjectCachesForTesting : 0)); serialized_data = Snapshot::Create(isolate, *default_context, global_safepoint, no_gc, flags); @@ -337,6 +341,9 @@ void Snapshot::SerializeDeserializeAndVerifyForTesting( new_isolate->set_snapshot_blob(&serialized_data); new_isolate->set_array_buffer_allocator( v8::ArrayBuffer::Allocator::NewDefaultAllocator()); + if (Isolate* shared_isolate = isolate->shared_isolate()) { + new_isolate->set_shared_isolate(shared_isolate); + } CHECK(Snapshot::Initialize(new_isolate)); HandleScope scope(new_isolate); @@ -376,6 +383,7 @@ v8::StartupData Snapshot::Create( SharedHeapSerializer shared_heap_serializer(isolate, flags, &read_only_serializer); + shared_heap_serializer.ReconstructSharedHeapObjectCacheForTestingIfNeeded(); StartupSerializer startup_serializer(isolate, flags, &read_only_serializer, &shared_heap_serializer); diff --git a/src/snapshot/snapshot.h b/src/snapshot/snapshot.h index d8caff0dc4..b25d6d227a 100644 --- a/src/snapshot/snapshot.h +++ b/src/snapshot/snapshot.h @@ -39,15 +39,17 @@ class Snapshot : public AllStatic { // after deserialization. // If unset, we assert that these previously mentioned areas are empty. kAllowActiveIsolateForTesting = 1 << 1, - // If set, the ReadOnlySerializer reconstructs the read-only object cache - // from the existing ReadOnlyHeap's read-only object cache so the same + // If set, the ReadOnlySerializer and the SharedHeapSerializer reconstructs + // their respective object caches from the existing ReadOnlyHeap's read-only + // object cache or the existing shared heap's object cache so the same // mapping is used. This mode is used for testing deserialization of a - // snapshot from a live isolate that's using a shared - // ReadOnlyHeap. Otherwise during deserialization the indices will mismatch, - // causing deserialization crashes when e.g. types mismatch. - // If unset, the read-only object cache is populated as read-only objects - // are serialized. - kReconstructReadOnlyObjectCacheForTesting = 1 << 2, + // snapshot from a live isolate that's using a shared ReadOnlyHeap or is + // attached to a shared isolate. Otherwise during deserialization the + // indices will mismatch, causing deserialization crashes when e.g. types + // mismatch. If unset, the read-only object cache is populated as read-only + // objects are serialized, and the shared heap object cache is populated as + // shared heap objects are serialized. + kReconstructReadOnlyAndSharedObjectCachesForTesting = 1 << 2, }; using SerializerFlags = base::Flags; V8_EXPORT_PRIVATE static constexpr SerializerFlags kDefaultSerializerFlags =