v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
shared-heap-serializer.cc
Go to the documentation of this file.
1// Copyright 2021 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
10
11namespace v8 {
12namespace internal {
13
14// static
16 if (ReadOnlyHeap::Contains(obj)) return false;
17 if (IsString(obj)) {
18 return IsInternalizedString(obj) ||
20 }
21 return false;
22}
23
24// static
27 // To keep the shared heap object cache lean, only include objects that should
28 // not be duplicated. Currently, that is only internalized strings. In-place
29 // internalizable strings will still be allocated in the shared heap by the
30 // deserializer, but do not need to be kept alive forever in the cache.
31 if (CanBeInSharedOldSpace(obj)) {
32 if (IsInternalizedString(obj)) return true;
33 }
34 return false;
35}
36
40#ifdef DEBUG
41 ,
42 serialized_objects_(isolate->heap())
43#endif
44{
47 }
48}
49
53
55 // This is called after serialization of the startup and context snapshots
56 // which entries are added to the shared heap object cache. Terminate the
57 // cache with an undefined.
58 Tagged<Object> undefined = ReadOnlyRoots(isolate()).undefined_value();
59 VisitRootPointer(Root::kSharedHeapObjectCache, nullptr,
60 FullObjectSlot(&undefined));
61
62 // When v8_flags.shared_string_table is true, all internalized and
63 // internalizable-in-place strings are in the shared heap.
64 SerializeStringTable(isolate()->string_table());
66 Pad();
67
68#ifdef DEBUG
69 // Check that all serialized object are in shared heap and not RO. RO objects
70 // should be in the RO snapshot.
72 &serialized_objects_);
73 for (auto it = it_scope.begin(); it != it_scope.end(); ++it) {
77 }
78#endif
79}
80
83 if (!ShouldBeInSharedHeapObjectCache(*obj)) return false;
84 int cache_index = SerializeInObjectCache(obj);
85
86 // When testing deserialization of a snapshot from a live Isolate where there
87 // is also a shared Isolate, the shared object cache needs to be extended
88 // because the live isolate may have had new internalized strings that were
89 // not present in the startup snapshot to be serialized.
91 std::vector<Tagged<Object>>* existing_cache =
93 const size_t existing_cache_size = existing_cache->size();
94 // This is strictly < because the existing cache contains the terminating
95 // undefined value, which the reconstructed cache does not.
96 DCHECK_LT(base::checked_cast<size_t>(cache_index), existing_cache_size);
97 if (base::checked_cast<size_t>(cache_index) == existing_cache_size - 1) {
98 ReadOnlyRoots roots(isolate());
99 DCHECK(IsUndefined(existing_cache->back(), roots));
100 existing_cache->back() = *obj;
101 existing_cache->push_back(roots.undefined_value());
102 }
103 }
104
105 sink->Put(kSharedHeapObjectCache, "SharedHeapObjectCache");
106 sink->PutUint30(cache_index, "shared_heap_object_cache_index");
107 return true;
108}
109
111 // A StringTable is serialized as:
112 //
113 // N : int
114 // string 1
115 // string 2
116 // ...
117 // string N
118 //
119 // Notably, the hashmap structure, including empty and deleted elements, is
120 // not serialized.
121
122 sink_.PutUint30(string_table->NumberOfElements(),
123 "String table number of elements");
124
125 // Custom RootVisitor which walks the string table, but only serializes the
126 // string entries. This is an inline class to be able to access the non-public
127 // SerializeObject method.
128 class SharedHeapSerializerStringTableVisitor : public RootVisitor {
129 public:
130 explicit SharedHeapSerializerStringTableVisitor(
131 SharedHeapSerializer* serializer)
132 : serializer_(serializer) {}
133
134 void VisitRootPointers(Root root, const char* description,
136 UNREACHABLE();
137 }
138
139 void VisitRootPointers(Root root, const char* description,
141 OffHeapObjectSlot end) override {
142 DCHECK_EQ(root, Root::kStringTable);
143 Isolate* isolate = serializer_->isolate();
144 for (OffHeapObjectSlot current = start; current < end; ++current) {
145 Tagged<Object> obj = current.load(isolate);
146 if (IsHeapObject(obj)) {
147 DCHECK(IsInternalizedString(obj));
148 serializer_->SerializeObject(handle(Cast<HeapObject>(obj), isolate),
149 SlotType::kAnySlot);
150 }
151 }
152 }
153
154 private:
155 SharedHeapSerializer* serializer_;
156 };
157
158 SharedHeapSerializerStringTableVisitor string_table_visitor(this);
159 isolate()->string_table()->IterateElements(&string_table_visitor);
160}
161
163 SlotType slot_type) {
164 // Objects in the shared heap cannot depend on per-Isolate roots but can
165 // depend on RO roots since sharing objects requires sharing the RO space.
167 {
169 Tagged<HeapObject> raw = *obj;
170 if (SerializeHotObject(raw)) return;
171 if (IsRootAndHasBeenSerialized(raw) && SerializeRoot(raw)) return;
172 }
173 if (SerializeReadOnlyObjectReference(*obj, &sink_)) return;
174 {
176 Tagged<HeapObject> raw = *obj;
177 if (SerializeBackReference(raw)) return;
179
181 }
182
183 ObjectSerializer object_serializer(this, obj, &sink_);
184 object_serializer.Serialize(slot_type);
185
186#ifdef DEBUG
187 CHECK_NULL(serialized_objects_.Find(obj));
188 // There's no "IdentitySet", so use an IdentityMap with a value that is
189 // later ignored.
190 serialized_objects_.Insert(obj, 0);
191#endif
192}
193
195 const {
196 // When the live Isolate being serialized is not a client Isolate, there's no
197 // need to reconstruct the shared heap object cache because it is not actually
198 // shared.
201}
202
204 std::vector<Tagged<Object>>* cache =
206 // Don't reconstruct the final element, which is always undefined and marks
207 // the end of the cache, since serializing the live Isolate may extend the
208 // shared object cache.
209 for (size_t i = 0, size = cache->size(); i < size - 1; i++) {
210 Handle<HeapObject> obj(Cast<HeapObject>(cache->at(i)), isolate());
212 int cache_index = SerializeInObjectCache(obj);
213 USE(cache_index);
214 DCHECK_EQ(cache_index, i);
215 }
216 DCHECK(IsUndefined(cache->back(), isolate()));
217}
218
219} // namespace internal
220} // namespace v8
Isolate * isolate() const
Definition factory.h:1281
bool has_shared_space() const
Definition isolate.h:2303
StringTable * string_table() const
Definition isolate.h:781
Isolate * shared_space_isolate() const
Definition isolate.h:2295
std::vector< Tagged< Object > > * shared_heap_object_cache()
Definition isolate.h:1889
static V8_EXPORT_PRIVATE bool Contains(Address address)
virtual void VisitRootPointer(Root root, const char *description, FullObjectSlot p)
Definition visitors.h:75
void CheckRehashability(Tagged< HeapObject > obj)
int SerializeInObjectCache(Handle< HeapObject > object)
bool IsRootAndHasBeenSerialized(Tagged< HeapObject > obj) const
Isolate * isolate() const
Definition serializer.h:195
bool reconstruct_read_only_and_shared_object_caches_for_testing() const
Definition serializer.h:332
SnapshotByteSink sink_
Definition serializer.h:323
bool SerializeRoot(Tagged< HeapObject > obj)
bool SerializeReadOnlyObjectReference(Tagged< HeapObject > obj, SnapshotByteSink *sink)
void OutputStatistics(const char *name)
void Pad(int padding_offset=0)
bool SerializeHotObject(Tagged< HeapObject > obj)
bool SerializeBackReference(Tagged< HeapObject > obj)
SharedHeapSerializer(Isolate *isolate, Snapshot::SerializerFlags flags)
static bool CanBeInSharedOldSpace(Tagged< HeapObject > obj)
bool SerializeUsingSharedHeapObjectCache(SnapshotByteSink *sink, Handle< HeapObject > obj)
static bool ShouldBeInSharedHeapObjectCache(Tagged< HeapObject > obj)
void SerializeObjectImpl(Handle< HeapObject > obj, SlotType slot_type) override
void SerializeStringTable(StringTable *string_table)
void PutUint30(uint32_t integer, const char *description)
void Put(uint8_t b, const char *description)
void IterateElements(RootVisitor *visitor)
static bool IsInPlaceInternalizable(Tagged< String > string)
int start
int end
LineAndColumn current
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
#define UNREACHABLE()
Definition logging.h:67
#define CHECK(condition)
Definition logging.h:124
#define CHECK_NULL(val)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define USE(...)
Definition macros.h:293