v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
serializer.h
Go to the documentation of this file.
1// Copyright 2016 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
5#ifndef V8_SNAPSHOT_SERIALIZER_H_
6#define V8_SNAPSHOT_SERIALIZER_H_
7
12#include "src/logging/log.h"
16#include "src/objects/objects.h"
21
22namespace v8 {
23namespace internal {
24
26 public:
27 explicit CodeAddressMap(Isolate* isolate) : CodeEventLogger(isolate) {
28 CHECK(isolate->logger()->AddListener(this));
29 }
30
31 ~CodeAddressMap() override {
33 }
34
36 Tagged<InstructionStream> to) override {
37 address_to_name_map_.Move(from.address(), to.address());
38 }
40 Tagged<BytecodeArray> to) override {
41 address_to_name_map_.Move(from.address(), to.address());
42 }
43
46
47 const char* Lookup(Address address) {
48 return address_to_name_map_.Lookup(address);
49 }
50
51 private:
52 class NameMap {
53 public:
54 NameMap() : impl_() {}
55 NameMap(const NameMap&) = delete;
56 NameMap& operator=(const NameMap&) = delete;
57
59 for (base::HashMap::Entry* p = impl_.Start(); p != nullptr;
60 p = impl_.Next(p)) {
61 DeleteArray(static_cast<const char*>(p->value));
62 }
63 }
64
65 void Insert(Address code_address, const char* name, size_t name_size) {
66 base::HashMap::Entry* entry = FindOrCreateEntry(code_address);
67 if (entry->value == nullptr) {
68 entry->value = CopyName(name, name_size);
69 }
70 }
71
72 const char* Lookup(Address code_address) {
73 base::HashMap::Entry* entry = FindEntry(code_address);
74 return (entry != nullptr) ? static_cast<const char*>(entry->value)
75 : nullptr;
76 }
77
78 void Remove(Address code_address) {
79 base::HashMap::Entry* entry = FindEntry(code_address);
80 if (entry != nullptr) {
81 DeleteArray(static_cast<char*>(entry->value));
82 RemoveEntry(entry);
83 }
84 }
85
86 void Move(Address from, Address to) {
87 if (from == to) return;
88 base::HashMap::Entry* from_entry = FindEntry(from);
89 DCHECK_NOT_NULL(from_entry);
90 void* value = from_entry->value;
91 RemoveEntry(from_entry);
93 DCHECK_NULL(to_entry->value);
94 to_entry->value = value;
95 }
96
97 private:
98 static char* CopyName(const char* name, size_t name_size) {
99 char* result = NewArray<char>(name_size + 1);
100 for (size_t i = 0; i < name_size; ++i) {
101 char c = name[i];
102 if (c == '\0') c = ' ';
103 result[i] = c;
104 }
105 result[name_size] = '\0';
106 return result;
107 }
108
110 return impl_.LookupOrInsert(reinterpret_cast<void*>(code_address),
111 ComputeAddressHash(code_address));
112 }
113
115 return impl_.Lookup(reinterpret_cast<void*>(code_address),
116 ComputeAddressHash(code_address));
117 }
118
120 impl_.Remove(entry->key, entry->hash);
121 }
122
124 };
125
128 const char* name, size_t length) override {
130 address_to_name_map_.Insert(code.address(), name, length);
131 }
132
133#if V8_ENABLE_WEBASSEMBLY
134 void LogRecordedBuffer(const wasm::WasmCode* code, const char* name,
135 size_t length) override {
136 UNREACHABLE();
137 }
138#endif // V8_ENABLE_WEBASSEMBLY
139
141};
142
144 public:
148
149 // If |obj| is in the map, immediately return true. Otherwise add it to the
150 // map and return false. In either case set |*index_out| to the index
151 // associated with the map.
152 bool LookupOrInsert(Tagged<HeapObject> obj, int* index_out) {
153 auto find_result = map_.FindOrInsert(obj);
154 if (!find_result.already_exists) {
155 *find_result.entry = next_index_++;
156 }
157 *index_out = *find_result.entry;
158 return find_result.already_exists;
159 }
160 bool LookupOrInsert(DirectHandle<HeapObject> obj, int* index_out) {
161 return LookupOrInsert(*obj, index_out);
162 }
163
164 bool Lookup(Tagged<HeapObject> obj, int* index_out) const {
165 int* index = map_.Find(obj);
166 if (index == nullptr) {
167 return false;
168 }
169 *index_out = *index;
170 return true;
171 }
172
174
175 int size() const { return next_index_; }
176
177 private:
180};
181
183 public:
186 Serializer(const Serializer&) = delete;
187 Serializer& operator=(const Serializer&) = delete;
188
189 const std::vector<uint8_t>* Payload() const { return sink_.data(); }
190
194
195 Isolate* isolate() const { return isolate_; }
196
197 // The pointer compression cage base value used for decompression of all
198 // tagged values except references to InstructionStream objects.
200#if V8_COMPRESS_POINTERS
201 return cage_base_;
202#else
203 return PtrComprCageBase{};
204#endif // V8_COMPRESS_POINTERS
205 }
206
207 int TotalAllocationSize() const;
208
209 protected:
210 using PendingObjectReferences = std::vector<int>*;
211
212 class ObjectSerializer;
214 public:
215 explicit RecursionScope(Serializer* serializer) : serializer_(serializer) {
216 serializer_->recursion_depth_++;
217 }
218 ~RecursionScope() { serializer_->recursion_depth_--; }
219 bool ExceedsMaximum() const {
220 return serializer_->recursion_depth_ > kMaxRecursionDepth;
221 }
222 int ExceedsMaximumBy() const {
223 return serializer_->recursion_depth_ - kMaxRecursionDepth;
224 }
225
226 private:
227 static const int kMaxRecursionDepth = 32;
229 };
230
231 // Compares obj with not_mapped_symbol root. When V8_EXTERNAL_CODE_SPACE is
232 // enabled it compares full pointers.
234
238 SlotType slot_type) = 0;
239
240 virtual bool MustBeDeferred(Tagged<HeapObject> object);
241
242 void VisitRootPointers(Root root, const char* description,
245
246 void PutRoot(RootIndex root_index);
247 void PutSmiRoot(FullObjectSlot slot);
249 SerializerReference reference);
252 void PutRepeatRoot(int repeat_count, RootIndex root_index);
253
254 // Emit a marker noting that this slot is a forward reference to the an
255 // object which has not yet been serialized.
257 // Resolve the given previously registered forward reference to the current
258 // object.
259 void ResolvePendingForwardReference(int obj);
260
261 // Returns true if the object was successfully serialized as a root.
263
264 // Returns true if the object was successfully serialized as hot object.
266
267 // Returns true if the object was successfully serialized as back reference.
269
270 // Returns true if the object was successfully serialized as pending object.
272
273 // Returns true if the given heap object is a bytecode handler code object.
275
277
282
284 SnapshotByteSink* sink);
285
286 // GetInt reads 4 bytes at once, requiring padding at the end.
287 // Use padding_offset to specify the space you want to use after padding.
288 void Pad(int padding_offset = 0);
289
290 // We may not need the code address map for logging for every instance
291 // of the serializer. Initialize it on demand.
293
295
300
301 // Register that the the given object shouldn't be immediately serialized, but
302 // will be serialized later and any references to it should be pending forward
303 // references.
305
306 // Resolve the given pending object reference with the current object.
308
309 void OutputStatistics(const char* name);
310
311 void CountAllocation(Tagged<Map> map, int size, SnapshotSpace space);
312
313#ifdef DEBUG
314 void PushStack(DirectHandle<HeapObject> o) { stack_.Push(*o); }
315 void PopStack();
316 void PrintStack();
317 void PrintStack(std::ostream&);
318#endif // DEBUG
319
321 const RootIndexMap* root_index_map() const { return &root_index_map_; }
322
323 SnapshotByteSink sink_; // Used directly by subclasses.
324
331
336
337 bool deferred_objects_empty() { return deferred_objects_.size() == 0; }
338
339 protected:
346
347 private:
348 // A circular queue of hot objects. This is added to in the same order as in
349 // Deserializer::HotObjectsList, but this stores the objects as an array of
350 // raw addresses that are considered strong roots. This allows objects to be
351 // added to the list without having to extend their handle's lifetime.
352 //
353 // We should never allow this class to return Handles to objects in the queue,
354 // as the object in the queue may change if kSize other objects are added to
355 // the queue during that Handle's lifetime.
357 public:
358 explicit HotObjectsList(Heap* heap);
362
363 void Add(Tagged<HeapObject> object) {
364 circular_queue_[index_] = object.ptr();
365 index_ = (index_ + 1) & kSizeMask;
366 }
367
368 static const int kNotFound = -1;
369
371 DCHECK(!AllowGarbageCollection::IsAllowed());
372 for (int i = 0; i < kSize; i++) {
373 if (circular_queue_[i] == object.ptr()) {
374 return i;
375 }
376 }
377 return kNotFound;
378 }
379
380 private:
381 static const int kSize = kHotObjectCount;
382 static const int kSizeMask = kSize - 1;
383 static_assert(base::bits::IsPowerOfTwo(kSize));
387 int index_ = 0;
388 };
389
390 // Disallow GC during serialization.
391 // TODO(leszeks, v8:10815): Remove this constraint.
393
395#if V8_COMPRESS_POINTERS
396 const PtrComprCageBase cage_base_;
397#endif // V8_COMPRESS_POINTERS
402 std::unique_ptr<CodeAddressMap> code_address_map_;
403 std::vector<uint8_t> code_buffer_;
405 deferred_objects_; // To handle stack overflow.
407
408 // Used to provide deterministic IDs to the serialized dispatch handles.
409 std::unordered_map<JSDispatchHandle, uint32_t> dispatch_handle_map_;
410
411 // Objects which have started being serialized, but haven't yet been allocated
412 // with the allocator, are considered "pending". References to them don't have
413 // an allocation to backref to, so instead they are registered as pending
414 // forward references, which are resolved once the object is allocated.
415 //
416 // Forward references are registered in a deterministic order, and can
417 // therefore be identified by an incrementing integer index, which is
418 // effectively an index into a vector of the currently registered forward
419 // refs. The references in this vector might not be resolved in order, so we
420 // can only clear it (and reset the indices) when there are no unresolved
421 // forward refs remaining.
426
427 // Used to keep track of the off-heap backing stores used by TypedArrays/
428 // ArrayBuffers. Note that the index begins at 1 and not 0, because when a
429 // TypedArray has an on-heap backing store, the backing_store pointer in the
430 // corresponding ArrayBuffer will be null, which makes it indistinguishable
431 // from index 0.
433
436
439#ifdef OBJECT_PRINT
440// Verbose serialization_statistics output is only enabled conditionally.
441#define VERBOSE_SERIALIZATION_STATISTICS
442#endif
443#ifdef VERBOSE_SERIALIZATION_STATISTICS
444 static constexpr int kInstanceTypes = LAST_TYPE + 1;
445 std::unique_ptr<int[]> instance_type_count_[kNumberOfSnapshotSpaces];
446 std::unique_ptr<size_t[]> instance_type_size_[kNumberOfSnapshotSpaces];
447#endif // VERBOSE_SERIALIZATION_STATISTICS
448
449#ifdef DEBUG
452#endif // DEBUG
453};
454
456 public:
458 SnapshotByteSink* sink)
459 : isolate_(serializer->isolate()),
460 serializer_(serializer),
461 object_(obj),
462 sink_(sink),
464#ifdef DEBUG
465 serializer_->PushStack(obj);
466#endif // DEBUG
467 }
468 ~ObjectSerializer() override {
469#ifdef DEBUG
470 serializer_->PopStack();
471#endif // DEBUG
472 }
473 void Serialize(SlotType slot_type);
474 void SerializeObject();
475 void SerializeDeferred();
477 ObjectSlot end) override;
479 MaybeObjectSlot end) override;
481 InstructionStreamSlot slot) override;
483 RelocInfo* target) override;
485 RelocInfo* rinfo) override;
487 RelocInfo* rinfo) override;
489 RelocInfo* target) override;
491 RelocInfo* target) override;
492
494 ExternalPointerSlot slot) override;
496 IndirectPointerMode mode) override;
498 IndirectPointerSlot slot) override;
500 ProtectedPointerSlot slot) override;
502 ProtectedMaybeObjectSlot slot) override;
504 CppHeapPointerSlot slot) override;
506 JSDispatchHandle handle) override;
507
508 Isolate* isolate() { return isolate_; }
509
510 private:
511 void SerializePrologue(SnapshotSpace space, int size, Tagged<Map> map);
512
513 // This function outputs or skips the raw data between the last pointer and
514 // up to the current position.
515 void SerializeContent(Tagged<Map> map, int size);
516 void OutputExternalReference(Address target, int target_size, bool sandboxify,
518 void OutputRawData(Address up_to);
519 uint32_t SerializeBackingStore(void* backing_store, uint32_t byte_length,
520 Maybe<uint32_t> max_byte_length);
525
531};
532
533} // namespace internal
534} // namespace v8
535
536#endif // V8_SNAPSHOT_SERIALIZER_H_
#define DISALLOW_GARBAGE_COLLECTION(name)
Entry * Next(Entry *entry) const
Definition hashmap.h:345
Entry * LookupOrInsert(const Key &key, uint32_t hash)
Definition hashmap.h:223
Value Remove(const Key &key, uint32_t hash)
Definition hashmap.h:265
Entry * Lookup(const Key &key, uint32_t hash) const
Definition hashmap.h:214
base::HashMap::Entry * FindOrCreateEntry(Address code_address)
Definition serializer.h:109
base::HashMap::Entry * FindEntry(Address code_address)
Definition serializer.h:114
NameMap(const NameMap &)=delete
void Move(Address from, Address to)
Definition serializer.h:86
static char * CopyName(const char *name, size_t name_size)
Definition serializer.h:98
void Insert(Address code_address, const char *name, size_t name_size)
Definition serializer.h:65
NameMap & operator=(const NameMap &)=delete
void RemoveEntry(base::HashMap::Entry *entry)
Definition serializer.h:119
void Remove(Address code_address)
Definition serializer.h:78
const char * Lookup(Address code_address)
Definition serializer.h:72
void LogRecordedBuffer(Tagged< AbstractCode > code, MaybeDirectHandle< SharedFunctionInfo >, const char *name, size_t length) override
Definition serializer.h:126
void CodeDisableOptEvent(DirectHandle< AbstractCode > code, DirectHandle< SharedFunctionInfo > shared) override
Definition serializer.h:44
void CodeMoveEvent(Tagged< InstructionStream > from, Tagged< InstructionStream > to) override
Definition serializer.h:35
const char * Lookup(Address address)
Definition serializer.h:47
void BytecodeMoveEvent(Tagged< BytecodeArray > from, Tagged< BytecodeArray > to) override
Definition serializer.h:39
CodeAddressMap(Isolate *isolate)
Definition serializer.h:27
Maybe< Value > TryEncode(Address key) const
Logger * logger() const
Definition isolate.h:1508
bool RemoveListener(LogEventListener *listener)
ObjectCacheIndexMap & operator=(const ObjectCacheIndexMap &)=delete
DirectHandle< FixedArray > Values(Isolate *isolate)
bool LookupOrInsert(Tagged< HeapObject > obj, int *index_out)
Definition serializer.h:152
ObjectCacheIndexMap(const ObjectCacheIndexMap &)=delete
IdentityMap< int, base::DefaultAllocationPolicy > map_
Definition serializer.h:178
bool LookupOrInsert(DirectHandle< HeapObject > obj, int *index_out)
Definition serializer.h:160
bool Lookup(Tagged< HeapObject > obj, int *index_out) const
Definition serializer.h:164
const SerializerReference * LookupReference(Tagged< HeapObject > object) const
Definition references.h:108
HotObjectsList & operator=(const HotObjectsList &)=delete
int Find(Tagged< HeapObject > object)
Definition serializer.h:370
HotObjectsList(const HotObjectsList &)=delete
void Add(Tagged< HeapObject > object)
Definition serializer.h:363
void VisitInstructionStreamPointer(Tagged< Code > host, InstructionStreamSlot slot) override
void SerializeContent(Tagged< Map > map, int size)
ObjectSerializer(Serializer *serializer, Handle< HeapObject > obj, SnapshotByteSink *sink)
Definition serializer.h:457
void VisitExternalReference(Tagged< InstructionStream > host, RelocInfo *rinfo) override
void VisitJSDispatchTableEntry(Tagged< HeapObject > host, JSDispatchHandle handle) override
void VisitPointers(Tagged< HeapObject > host, ObjectSlot start, ObjectSlot end) override
uint32_t SerializeBackingStore(void *backing_store, uint32_t byte_length, Maybe< uint32_t > max_byte_length)
void VisitProtectedPointer(Tagged< TrustedObject > host, ProtectedPointerSlot slot) override
void VisitEmbeddedPointer(Tagged< InstructionStream > host, RelocInfo *target) override
void VisitTrustedPointerTableEntry(Tagged< HeapObject > host, IndirectPointerSlot slot) override
void VisitExternalPointer(Tagged< HeapObject > host, ExternalPointerSlot slot) override
void VisitIndirectPointer(Tagged< HeapObject > host, IndirectPointerSlot slot, IndirectPointerMode mode) override
void VisitOffHeapTarget(Tagged< InstructionStream > host, RelocInfo *target) override
void OutputExternalReference(Address target, int target_size, bool sandboxify, ExternalPointerTag tag)
void VisitCodeTarget(Tagged< InstructionStream > host, RelocInfo *target) override
void VisitInternalReference(Tagged< InstructionStream > host, RelocInfo *rinfo) override
void VisitCppHeapPointer(Tagged< HeapObject > host, CppHeapPointerSlot slot) override
void SerializePrologue(SnapshotSpace space, int size, Tagged< Map > map)
RecursionScope(Serializer *serializer)
Definition serializer.h:215
bool ReferenceMapContains(DirectHandle< HeapObject > o)
Definition serializer.h:191
bool allow_unknown_external_references_for_testing() const
Definition serializer.h:325
HotObjectsList hot_objects_
Definition serializer.h:398
bool SerializePendingObject(Tagged< HeapObject > obj)
PtrComprCageBase cage_base() const
Definition serializer.h:199
Serializer & operator=(const Serializer &)=delete
ExternalReferenceEncoder::Value EncodeExternalReference(Address addr)
virtual bool MustBeDeferred(Tagged< HeapObject > object)
Tagged< InstructionStream > CopyCode(Tagged< InstructionStream > istream)
std::unique_ptr< CodeAddressMap > code_address_map_
Definition serializer.h:402
void ResolvePendingObject(Tagged< HeapObject > obj)
bool ObjectIsBytecodeHandler(Tagged< HeapObject > obj) const
Isolate * isolate() const
Definition serializer.h:195
void PutSmiRoot(FullObjectSlot slot)
void RegisterObjectIsPending(Tagged< HeapObject > obj)
void VisitRootPointers(Root root, const char *description, FullObjectSlot start, FullObjectSlot end) override
bool reconstruct_read_only_and_shared_object_caches_for_testing() const
Definition serializer.h:332
SerializerReferenceMap reference_map_
Definition serializer.h:399
RootIndexMap root_index_map_
Definition serializer.h:401
bool serializer_tracks_serialization_statistics() const
Definition serializer.h:340
const std::vector< uint8_t > * Payload() const
Definition serializer.h:189
const RootIndexMap * root_index_map() const
Definition serializer.h:321
void set_serializer_tracks_serialization_statistics(bool v)
Definition serializer.h:343
void PutBackReference(Tagged< HeapObject > object, SerializerReference reference)
void QueueDeferredObject(Tagged< HeapObject > obj)
Definition serializer.h:296
void CountAllocation(Tagged< Map > map, int size, SnapshotSpace space)
Definition serializer.cc:67
SnapshotByteSink sink_
Definition serializer.h:323
void PutPendingForwardReference(PendingObjectReferences &ref)
ExternalReferenceEncoder external_reference_encoder_
Definition serializer.h:400
virtual void SerializeObjectImpl(Handle< HeapObject > o, SlotType slot_type)=0
void SerializeRootObject(FullObjectSlot slot)
void PutRepeatRoot(int repeat_count, RootIndex root_index)
Serializer(const Serializer &)=delete
void PutRoot(RootIndex root_index)
bool SerializeRoot(Tagged< HeapObject > obj)
bool SerializeReadOnlyObjectReference(Tagged< HeapObject > obj, SnapshotByteSink *sink)
void OutputStatistics(const char *name)
bool serializer_tracks_serialization_statistics_
Definition serializer.h:437
IdentityMap< PendingObjectReferences, base::DefaultAllocationPolicy > forward_refs_per_pending_object_
Definition serializer.h:425
void ResolvePendingForwardReference(int obj)
void PutAttachedReference(SerializerReference reference)
Serializer(Isolate *isolate, Snapshot::SerializerFlags flags)
Definition serializer.cc:34
void Pad(int padding_offset=0)
uint32_t seen_backing_stores_index_
Definition serializer.h:432
int TotalAllocationSize() const
Definition serializer.cc:80
std::vector< uint8_t > code_buffer_
Definition serializer.h:403
void PutNextChunk(SnapshotSpace space)
std::unordered_map< JSDispatchHandle, uint32_t > dispatch_handle_map_
Definition serializer.h:409
void SerializeObject(Handle< HeapObject > o, SlotType slot_type)
bool allow_active_isolate_for_testing() const
Definition serializer.h:328
Maybe< ExternalReferenceEncoder::Value > TryEncodeExternalReference(Address addr)
Definition serializer.h:278
std::vector< int > * PendingObjectReferences
Definition serializer.h:210
SerializerReferenceMap * reference_map()
Definition serializer.h:320
bool SerializeHotObject(Tagged< HeapObject > obj)
V8_INLINE bool IsNotMappedSymbol(Tagged< HeapObject > obj) const
size_t allocation_size_[kNumberOfSnapshotSpaces]
Definition serializer.h:438
GlobalHandleVector< HeapObject > deferred_objects_
Definition serializer.h:405
bool SerializeBackReference(Tagged< HeapObject > obj)
const Snapshot::SerializerFlags flags_
Definition serializer.h:435
const std::vector< uint8_t > * data() const
@ kReconstructReadOnlyAndSharedObjectCachesForTesting
Definition snapshot.h:54
@ kAllowUnknownExternalReferencesForTesting
Definition snapshot.h:34
int start
int end
DisallowGarbageCollection no_gc_
ZoneVector< RpoNumber > & result
constexpr bool IsPowerOfTwo(T value)
Definition bits.h:187
void DeleteArray(T *array)
Definition allocation.h:63
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
static constexpr int kNumberOfSnapshotSpaces
Definition references.h:24
return value
Definition map-inl.h:893
static constexpr Address kNullAddress
Definition v8-internal.h:53
T * NewArray(size_t size)
Definition allocation.h:43
uint32_t ComputeAddressHash(Address address)
Definition utils.h:306
#define DCHECK_NULL(val)
Definition logging.h:491
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_INLINE
Definition v8config.h:500
#define V8_NODISCARD
Definition v8config.h:693