[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 <syg@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/main@{#78804}
This commit is contained in:
parent
3b233c9f25
commit
7437c69093
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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<int, base::DefaultAllocationPolicy>::IteratableScope it_scope(
|
||||
@ -90,6 +86,20 @@ bool SharedHeapSerializer::SerializeUsingSharedHeapObjectCache(
|
||||
SnapshotByteSink* sink, Handle<HeapObject> 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<size_t>(cache_index), existing_cache_size);
|
||||
if (base::checked_cast<size_t>(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<HeapObject> obj) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void SharedHeapSerializer::
|
||||
ReconstructSharedHeapObjectCacheForTestingIfNeeded() {
|
||||
if (!reconstruct_read_only_and_shared_object_caches_for_testing()) return;
|
||||
std::vector<Object>* 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<HeapObject> obj(HeapObject::cast(cache->at(i)), isolate());
|
||||
int cache_index = SerializeInObjectCache(obj);
|
||||
USE(cache_index);
|
||||
DCHECK_EQ(cache_index, i);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -43,6 +43,8 @@ class V8_EXPORT_PRIVATE SharedHeapSerializer : public RootsSerializer {
|
||||
bool SerializeUsingSharedHeapObjectCache(SnapshotByteSink* sink,
|
||||
Handle<HeapObject> obj);
|
||||
|
||||
void ReconstructSharedHeapObjectCacheForTestingIfNeeded();
|
||||
|
||||
static bool CanBeInSharedOldSpace(HeapObject obj);
|
||||
|
||||
static bool ShouldBeInSharedHeapObjectCache(HeapObject obj);
|
||||
|
@ -313,13 +313,17 @@ void Snapshot::SerializeDeserializeAndVerifyForTesting(
|
||||
// Test serialization.
|
||||
{
|
||||
GlobalSafepointScope global_safepoint(isolate);
|
||||
base::Optional<SafepointScope> 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);
|
||||
|
@ -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<SerializerFlag>;
|
||||
V8_EXPORT_PRIVATE static constexpr SerializerFlags kDefaultSerializerFlags =
|
||||
|
Loading…
Reference in New Issue
Block a user