[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);
|
ReadOnlyRoots(isolate()).Iterate(this);
|
||||||
|
|
||||||
if (reconstruct_read_only_object_cache_for_testing()) {
|
if (reconstruct_read_only_and_shared_object_caches_for_testing()) {
|
||||||
ReconstructReadOnlyObjectCacheForTesting();
|
ReconstructReadOnlyObjectCacheForTesting();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -309,8 +309,9 @@ class Serializer : public SerializerDeserializer {
|
|||||||
return (flags_ & Snapshot::kAllowActiveIsolateForTesting) != 0;
|
return (flags_ & Snapshot::kAllowActiveIsolateForTesting) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool reconstruct_read_only_object_cache_for_testing() const {
|
bool reconstruct_read_only_and_shared_object_caches_for_testing() const {
|
||||||
return (flags_ & Snapshot::kReconstructReadOnlyObjectCacheForTesting) != 0;
|
return (flags_ &
|
||||||
|
Snapshot::kReconstructReadOnlyAndSharedObjectCachesForTesting) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -65,10 +65,6 @@ void SharedHeapSerializer::FinalizeSerialization() {
|
|||||||
Pad();
|
Pad();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#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
|
// Check that all serialized object are in shared heap and not RO. RO objects
|
||||||
// should be in the RO snapshot.
|
// should be in the RO snapshot.
|
||||||
IdentityMap<int, base::DefaultAllocationPolicy>::IteratableScope it_scope(
|
IdentityMap<int, base::DefaultAllocationPolicy>::IteratableScope it_scope(
|
||||||
@ -90,6 +86,20 @@ bool SharedHeapSerializer::SerializeUsingSharedHeapObjectCache(
|
|||||||
SnapshotByteSink* sink, Handle<HeapObject> obj) {
|
SnapshotByteSink* sink, Handle<HeapObject> obj) {
|
||||||
if (!ShouldBeInSharedHeapObjectCache(*obj)) return false;
|
if (!ShouldBeInSharedHeapObjectCache(*obj)) return false;
|
||||||
int cache_index = SerializeInObjectCache(obj);
|
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->Put(kSharedHeapObjectCache, "SharedHeapObjectCache");
|
||||||
sink->PutInt(cache_index, "shared_heap_object_cache_index");
|
sink->PutInt(cache_index, "shared_heap_object_cache_index");
|
||||||
return true;
|
return true;
|
||||||
@ -170,5 +180,18 @@ void SharedHeapSerializer::SerializeObjectImpl(Handle<HeapObject> obj) {
|
|||||||
#endif
|
#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 internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
@ -43,6 +43,8 @@ class V8_EXPORT_PRIVATE SharedHeapSerializer : public RootsSerializer {
|
|||||||
bool SerializeUsingSharedHeapObjectCache(SnapshotByteSink* sink,
|
bool SerializeUsingSharedHeapObjectCache(SnapshotByteSink* sink,
|
||||||
Handle<HeapObject> obj);
|
Handle<HeapObject> obj);
|
||||||
|
|
||||||
|
void ReconstructSharedHeapObjectCacheForTestingIfNeeded();
|
||||||
|
|
||||||
static bool CanBeInSharedOldSpace(HeapObject obj);
|
static bool CanBeInSharedOldSpace(HeapObject obj);
|
||||||
|
|
||||||
static bool ShouldBeInSharedHeapObjectCache(HeapObject obj);
|
static bool ShouldBeInSharedHeapObjectCache(HeapObject obj);
|
||||||
|
@ -313,13 +313,17 @@ void Snapshot::SerializeDeserializeAndVerifyForTesting(
|
|||||||
// Test serialization.
|
// Test serialization.
|
||||||
{
|
{
|
||||||
GlobalSafepointScope global_safepoint(isolate);
|
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;
|
DisallowGarbageCollection no_gc;
|
||||||
|
|
||||||
Snapshot::SerializerFlags flags(
|
Snapshot::SerializerFlags flags(
|
||||||
Snapshot::kAllowUnknownExternalReferencesForTesting |
|
Snapshot::kAllowUnknownExternalReferencesForTesting |
|
||||||
Snapshot::kAllowActiveIsolateForTesting |
|
Snapshot::kAllowActiveIsolateForTesting |
|
||||||
(ReadOnlyHeap::IsReadOnlySpaceShared()
|
((isolate->shared_isolate() || ReadOnlyHeap::IsReadOnlySpaceShared())
|
||||||
? Snapshot::kReconstructReadOnlyObjectCacheForTesting
|
? Snapshot::kReconstructReadOnlyAndSharedObjectCachesForTesting
|
||||||
: 0));
|
: 0));
|
||||||
serialized_data = Snapshot::Create(isolate, *default_context,
|
serialized_data = Snapshot::Create(isolate, *default_context,
|
||||||
global_safepoint, no_gc, flags);
|
global_safepoint, no_gc, flags);
|
||||||
@ -337,6 +341,9 @@ void Snapshot::SerializeDeserializeAndVerifyForTesting(
|
|||||||
new_isolate->set_snapshot_blob(&serialized_data);
|
new_isolate->set_snapshot_blob(&serialized_data);
|
||||||
new_isolate->set_array_buffer_allocator(
|
new_isolate->set_array_buffer_allocator(
|
||||||
v8::ArrayBuffer::Allocator::NewDefaultAllocator());
|
v8::ArrayBuffer::Allocator::NewDefaultAllocator());
|
||||||
|
if (Isolate* shared_isolate = isolate->shared_isolate()) {
|
||||||
|
new_isolate->set_shared_isolate(shared_isolate);
|
||||||
|
}
|
||||||
CHECK(Snapshot::Initialize(new_isolate));
|
CHECK(Snapshot::Initialize(new_isolate));
|
||||||
|
|
||||||
HandleScope scope(new_isolate);
|
HandleScope scope(new_isolate);
|
||||||
@ -376,6 +383,7 @@ v8::StartupData Snapshot::Create(
|
|||||||
|
|
||||||
SharedHeapSerializer shared_heap_serializer(isolate, flags,
|
SharedHeapSerializer shared_heap_serializer(isolate, flags,
|
||||||
&read_only_serializer);
|
&read_only_serializer);
|
||||||
|
shared_heap_serializer.ReconstructSharedHeapObjectCacheForTestingIfNeeded();
|
||||||
|
|
||||||
StartupSerializer startup_serializer(isolate, flags, &read_only_serializer,
|
StartupSerializer startup_serializer(isolate, flags, &read_only_serializer,
|
||||||
&shared_heap_serializer);
|
&shared_heap_serializer);
|
||||||
|
@ -39,15 +39,17 @@ class Snapshot : public AllStatic {
|
|||||||
// after deserialization.
|
// after deserialization.
|
||||||
// If unset, we assert that these previously mentioned areas are empty.
|
// If unset, we assert that these previously mentioned areas are empty.
|
||||||
kAllowActiveIsolateForTesting = 1 << 1,
|
kAllowActiveIsolateForTesting = 1 << 1,
|
||||||
// If set, the ReadOnlySerializer reconstructs the read-only object cache
|
// If set, the ReadOnlySerializer and the SharedHeapSerializer reconstructs
|
||||||
// from the existing ReadOnlyHeap's read-only object cache so the same
|
// 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
|
// mapping is used. This mode is used for testing deserialization of a
|
||||||
// snapshot from a live isolate that's using a shared
|
// snapshot from a live isolate that's using a shared ReadOnlyHeap or is
|
||||||
// ReadOnlyHeap. Otherwise during deserialization the indices will mismatch,
|
// attached to a shared isolate. Otherwise during deserialization the
|
||||||
// causing deserialization crashes when e.g. types mismatch.
|
// indices will mismatch, causing deserialization crashes when e.g. types
|
||||||
// If unset, the read-only object cache is populated as read-only objects
|
// mismatch. If unset, the read-only object cache is populated as read-only
|
||||||
// are serialized.
|
// objects are serialized, and the shared heap object cache is populated as
|
||||||
kReconstructReadOnlyObjectCacheForTesting = 1 << 2,
|
// shared heap objects are serialized.
|
||||||
|
kReconstructReadOnlyAndSharedObjectCachesForTesting = 1 << 2,
|
||||||
};
|
};
|
||||||
using SerializerFlags = base::Flags<SerializerFlag>;
|
using SerializerFlags = base::Flags<SerializerFlag>;
|
||||||
V8_EXPORT_PRIVATE static constexpr SerializerFlags kDefaultSerializerFlags =
|
V8_EXPORT_PRIVATE static constexpr SerializerFlags kDefaultSerializerFlags =
|
||||||
|
Loading…
Reference in New Issue
Block a user