[snapshot] Add serializer option to reconstruct the RO object cache

This option is used for --stress-snapshot when sharing the RO heap. The
RO heap is shared, so deserializing non-startup snapshots need to ensure
they use the same RO object cache mapping as the startup snapshot.

Cq-Include-Trybots: luci.v8.try:v8_linux64_gc_stress_custom_snapshot_dbg_ng
Bug: v8:11750
Change-Id: Ia2baa24d5b7d494ef5b7ff3c9cbcee846881182e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2897945
Reviewed-by: Dan Elphick <delphick@chromium.org>
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74574}
This commit is contained in:
Shu-yu Guo 2021-05-14 11:49:40 -07:00 committed by V8 LUCI CQ
parent 34dc2607db
commit aebe382ab7
7 changed files with 41 additions and 1 deletions

View File

@ -249,6 +249,10 @@ bool ReadOnlyHeap::read_only_object_cache_is_initialized() const {
return read_only_object_cache_.size() > 0;
}
size_t ReadOnlyHeap::read_only_object_cache_size() const {
return read_only_object_cache_.size();
}
ReadOnlyHeapObjectIterator::ReadOnlyHeapObjectIterator(ReadOnlyHeap* ro_heap)
: ReadOnlyHeapObjectIterator(ro_heap->read_only_space()) {}

View File

@ -81,6 +81,7 @@ class ReadOnlyHeap {
// Returns a read-only cache entry at a particular index.
Object cached_read_only_object(size_t i) const;
bool read_only_object_cache_is_initialized() const;
size_t read_only_object_cache_size() const;
ReadOnlySpace* read_only_space() const { return read_only_space_; }

View File

@ -74,6 +74,10 @@ void ReadOnlySerializer::SerializeReadOnlyRoots() {
isolate()->handle_scope_implementer()->blocks()->empty());
ReadOnlyRoots(isolate()).Iterate(this);
if (reconstruct_read_only_object_cache_for_testing()) {
ReconstructReadOnlyObjectCacheForTesting();
}
}
void ReadOnlySerializer::FinalizeSerialization() {
@ -129,5 +133,18 @@ bool ReadOnlySerializer::SerializeUsingReadOnlyObjectCache(
return true;
}
void ReadOnlySerializer::ReconstructReadOnlyObjectCacheForTesting() {
ReadOnlyHeap* ro_heap = isolate()->read_only_heap();
DCHECK(ro_heap->read_only_object_cache_is_initialized());
for (size_t i = 0, size = ro_heap->read_only_object_cache_size(); i < size;
i++) {
Handle<HeapObject> obj(
HeapObject::cast(ro_heap->cached_read_only_object(i)), isolate());
int cache_index = SerializeInObjectCache(obj);
USE(cache_index);
DCHECK_EQ(cache_index, i);
}
}
} // namespace internal
} // namespace v8

View File

@ -37,6 +37,8 @@ class V8_EXPORT_PRIVATE ReadOnlySerializer : public RootsSerializer {
Handle<HeapObject> obj);
private:
void ReconstructReadOnlyObjectCacheForTesting();
void SerializeObjectImpl(Handle<HeapObject> o) override;
bool MustBeDeferred(HeapObject object) override;

View File

@ -298,6 +298,10 @@ class Serializer : public SerializerDeserializer {
return (flags_ & Snapshot::kAllowActiveIsolateForTesting) != 0;
}
bool reconstruct_read_only_object_cache_for_testing() const {
return (flags_ & Snapshot::kReconstructReadOnlyObjectCacheForTesting) != 0;
}
private:
// A circular queue of hot objects. This is added to in the same order as in
// Deserializer::HotObjectsList, but this stores the objects as an array of

View File

@ -286,7 +286,10 @@ void Snapshot::SerializeDeserializeAndVerifyForTesting(
Snapshot::SerializerFlags flags(
Snapshot::kAllowUnknownExternalReferencesForTesting |
Snapshot::kAllowActiveIsolateForTesting);
Snapshot::kAllowActiveIsolateForTesting |
(ReadOnlyHeap::IsReadOnlySpaceShared()
? Snapshot::kReconstructReadOnlyObjectCacheForTesting
: 0));
serialized_data = Snapshot::Create(isolate, *default_context, no_gc, flags);
auto_delete_serialized_data.reset(serialized_data.data);
}

View File

@ -36,6 +36,15 @@ 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
// 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,
};
using SerializerFlags = base::Flags<SerializerFlag>;
V8_EXPORT_PRIVATE static constexpr SerializerFlags kDefaultSerializerFlags =