Line data Source code
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 :
8 : #include <map>
9 :
10 : #include "src/isolate.h"
11 : #include "src/log.h"
12 : #include "src/objects.h"
13 : #include "src/snapshot/embedded-data.h"
14 : #include "src/snapshot/serializer-allocator.h"
15 : #include "src/snapshot/serializer-common.h"
16 : #include "src/snapshot/snapshot-source-sink.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 :
21 : class CodeAddressMap : public CodeEventLogger {
22 : public:
23 964 : explicit CodeAddressMap(Isolate* isolate) : CodeEventLogger(isolate) {
24 964 : isolate->logger()->AddCodeEventListener(this);
25 482 : }
26 :
27 1446 : ~CodeAddressMap() override {
28 482 : isolate_->logger()->RemoveCodeEventListener(this);
29 964 : }
30 :
31 0 : void CodeMoveEvent(AbstractCode from, AbstractCode to) override {
32 0 : address_to_name_map_.Move(from->address(), to->address());
33 0 : }
34 :
35 0 : void CodeDisableOptEvent(AbstractCode code,
36 0 : SharedFunctionInfo shared) override {}
37 :
38 : const char* Lookup(Address address) {
39 1613347 : return address_to_name_map_.Lookup(address);
40 : }
41 :
42 : private:
43 : class NameMap {
44 : public:
45 : NameMap() : impl_() {}
46 :
47 482 : ~NameMap() {
48 964 : for (base::HashMap::Entry* p = impl_.Start(); p != nullptr;
49 : p = impl_.Next(p)) {
50 0 : DeleteArray(static_cast<const char*>(p->value));
51 : }
52 482 : }
53 :
54 0 : void Insert(Address code_address, const char* name, int name_size) {
55 0 : base::HashMap::Entry* entry = FindOrCreateEntry(code_address);
56 0 : if (entry->value == nullptr) {
57 0 : entry->value = CopyName(name, name_size);
58 : }
59 0 : }
60 :
61 : const char* Lookup(Address code_address) {
62 1613347 : base::HashMap::Entry* entry = FindEntry(code_address);
63 : return (entry != nullptr) ? static_cast<const char*>(entry->value)
64 1613347 : : nullptr;
65 : }
66 :
67 : void Remove(Address code_address) {
68 : base::HashMap::Entry* entry = FindEntry(code_address);
69 : if (entry != nullptr) {
70 : DeleteArray(static_cast<char*>(entry->value));
71 : RemoveEntry(entry);
72 : }
73 : }
74 :
75 0 : void Move(Address from, Address to) {
76 0 : if (from == to) return;
77 0 : base::HashMap::Entry* from_entry = FindEntry(from);
78 : DCHECK_NOT_NULL(from_entry);
79 0 : void* value = from_entry->value;
80 : RemoveEntry(from_entry);
81 0 : base::HashMap::Entry* to_entry = FindOrCreateEntry(to);
82 : DCHECK_NULL(to_entry->value);
83 0 : to_entry->value = value;
84 : }
85 :
86 : private:
87 0 : static char* CopyName(const char* name, int name_size) {
88 0 : char* result = NewArray<char>(name_size + 1);
89 0 : for (int i = 0; i < name_size; ++i) {
90 0 : char c = name[i];
91 0 : if (c == '\0') c = ' ';
92 0 : result[i] = c;
93 : }
94 0 : result[name_size] = '\0';
95 0 : return result;
96 : }
97 :
98 0 : base::HashMap::Entry* FindOrCreateEntry(Address code_address) {
99 : return impl_.LookupOrInsert(reinterpret_cast<void*>(code_address),
100 0 : ComputeAddressHash(code_address));
101 : }
102 :
103 1613347 : base::HashMap::Entry* FindEntry(Address code_address) {
104 : return impl_.Lookup(reinterpret_cast<void*>(code_address),
105 1613347 : ComputeAddressHash(code_address));
106 : }
107 :
108 : void RemoveEntry(base::HashMap::Entry* entry) {
109 0 : impl_.Remove(entry->key, entry->hash);
110 : }
111 :
112 : base::HashMap impl_;
113 :
114 : DISALLOW_COPY_AND_ASSIGN(NameMap);
115 : };
116 :
117 0 : void LogRecordedBuffer(AbstractCode code, SharedFunctionInfo,
118 : const char* name, int length) override {
119 0 : address_to_name_map_.Insert(code->address(), name, length);
120 0 : }
121 :
122 0 : void LogRecordedBuffer(const wasm::WasmCode* code, const char* name,
123 : int length) override {
124 0 : UNREACHABLE();
125 : }
126 :
127 : NameMap address_to_name_map_;
128 : };
129 :
130 : class ObjectCacheIndexMap {
131 : public:
132 1004 : ObjectCacheIndexMap() : map_(), next_index_(0) {}
133 :
134 : // If |obj| is in the map, immediately return true. Otherwise add it to the
135 : // map and return false. In either case set |*index_out| to the index
136 : // associated with the map.
137 591567 : bool LookupOrInsert(HeapObject obj, int* index_out) {
138 591567 : Maybe<uint32_t> maybe_index = map_.Get(obj);
139 591567 : if (maybe_index.IsJust()) {
140 193865 : *index_out = maybe_index.FromJust();
141 193865 : return true;
142 : }
143 397702 : *index_out = next_index_;
144 397702 : map_.Set(obj, next_index_++);
145 397702 : return false;
146 : }
147 :
148 : private:
149 : DisallowHeapAllocation no_allocation_;
150 :
151 : HeapObjectToIndexHashMap map_;
152 : int next_index_;
153 :
154 : DISALLOW_COPY_AND_ASSIGN(ObjectCacheIndexMap);
155 : };
156 :
157 : class Serializer : public SerializerDeserializer {
158 : public:
159 : explicit Serializer(Isolate* isolate);
160 : ~Serializer() override;
161 :
162 : std::vector<SerializedData::Reservation> EncodeReservations() const {
163 1112 : return allocator_.EncodeReservations();
164 : }
165 :
166 : const std::vector<byte>* Payload() const { return sink_.data(); }
167 :
168 : bool ReferenceMapContains(HeapObject o) {
169 : return reference_map()
170 : ->LookupReference(reinterpret_cast<void*>(o->ptr()))
171 : .is_valid();
172 : }
173 :
174 : Isolate* isolate() const { return isolate_; }
175 :
176 : protected:
177 : class ObjectSerializer;
178 : class RecursionScope {
179 : public:
180 : explicit RecursionScope(Serializer* serializer) : serializer_(serializer) {
181 1837909 : serializer_->recursion_depth_++;
182 : }
183 1837909 : ~RecursionScope() { serializer_->recursion_depth_--; }
184 : bool ExceedsMaximum() {
185 : return serializer_->recursion_depth_ >= kMaxRecursionDepth;
186 : }
187 :
188 : private:
189 : static const int kMaxRecursionDepth = 32;
190 : Serializer* serializer_;
191 : };
192 :
193 : void SerializeDeferredObjects();
194 : virtual void SerializeObject(HeapObject o, HowToCode how_to_code,
195 : WhereToPoint where_to_point, int skip) = 0;
196 :
197 : virtual bool MustBeDeferred(HeapObject object);
198 :
199 : void VisitRootPointers(Root root, const char* description,
200 : FullObjectSlot start, FullObjectSlot end) override;
201 : void SerializeRootObject(Object object);
202 :
203 : void PutRoot(RootIndex root_index, HeapObject object, HowToCode how,
204 : WhereToPoint where, int skip);
205 : void PutSmi(Smi smi);
206 : void PutBackReference(HeapObject object, SerializerReference reference);
207 : void PutAttachedReference(SerializerReference reference,
208 : HowToCode how_to_code, WhereToPoint where_to_point);
209 : // Emit alignment prefix if necessary, return required padding space in bytes.
210 : int PutAlignmentPrefix(HeapObject object);
211 : void PutNextChunk(int space);
212 :
213 : // Returns true if the object was successfully serialized as a root.
214 : bool SerializeRoot(HeapObject obj, HowToCode how_to_code,
215 : WhereToPoint where_to_point, int skip);
216 :
217 : // Returns true if the object was successfully serialized as hot object.
218 : bool SerializeHotObject(HeapObject obj, HowToCode how_to_code,
219 : WhereToPoint where_to_point, int skip);
220 :
221 : // Returns true if the object was successfully serialized as back reference.
222 : bool SerializeBackReference(HeapObject obj, HowToCode how_to_code,
223 : WhereToPoint where_to_point, int skip);
224 :
225 : // Returns true if the given heap object is a bytecode handler code object.
226 : bool ObjectIsBytecodeHandler(HeapObject obj) const;
227 :
228 3360366 : static inline void FlushSkip(SnapshotByteSink* sink, int skip) {
229 3360366 : if (skip != 0) {
230 : sink->Put(kSkip, "SkipFromSerializeObject");
231 379274 : sink->PutInt(skip, "SkipDistanceFromSerializeObject");
232 : }
233 3360366 : }
234 :
235 2768799 : inline void FlushSkip(int skip) { FlushSkip(&sink_, skip); }
236 :
237 : ExternalReferenceEncoder::Value EncodeExternalReference(Address addr) {
238 8516 : return external_reference_encoder_.Encode(addr);
239 : }
240 :
241 : // GetInt reads 4 bytes at once, requiring padding at the end.
242 : // Use padding_offset to specify the space you want to use after padding.
243 : void Pad(int padding_offset = 0);
244 :
245 : // We may not need the code address map for logging for every instance
246 : // of the serializer. Initialize it on demand.
247 : void InitializeCodeAddressMap();
248 :
249 : Code CopyCode(Code code);
250 :
251 : void QueueDeferredObject(HeapObject obj) {
252 : DCHECK(reference_map_.LookupReference(reinterpret_cast<void*>(obj->ptr()))
253 : .is_back_reference());
254 3896 : deferred_objects_.push_back(obj);
255 : }
256 :
257 : void OutputStatistics(const char* name);
258 :
259 : #ifdef OBJECT_PRINT
260 : void CountInstanceType(Map map, int size, AllocationSpace space);
261 : #endif // OBJECT_PRINT
262 :
263 : #ifdef DEBUG
264 : void PushStack(HeapObject o) { stack_.push_back(o); }
265 : void PopStack() { stack_.pop_back(); }
266 : void PrintStack();
267 : #endif // DEBUG
268 :
269 : SerializerReferenceMap* reference_map() { return &reference_map_; }
270 : const RootIndexMap* root_index_map() const { return &root_index_map_; }
271 : SerializerAllocator* allocator() { return &allocator_; }
272 :
273 : SnapshotByteSink sink_; // Used directly by subclasses.
274 :
275 : private:
276 : Isolate* isolate_;
277 : SerializerReferenceMap reference_map_;
278 : ExternalReferenceEncoder external_reference_encoder_;
279 : RootIndexMap root_index_map_;
280 : CodeAddressMap* code_address_map_ = nullptr;
281 : std::vector<byte> code_buffer_;
282 : std::vector<HeapObject> deferred_objects_; // To handle stack overflow.
283 : int recursion_depth_ = 0;
284 : SerializerAllocator allocator_;
285 :
286 : #ifdef OBJECT_PRINT
287 : static const int kInstanceTypes = LAST_TYPE + 1;
288 : int* instance_type_count_[LAST_SPACE];
289 : size_t* instance_type_size_[LAST_SPACE];
290 : #endif // OBJECT_PRINT
291 :
292 : #ifdef DEBUG
293 : std::vector<HeapObject> stack_;
294 : #endif // DEBUG
295 :
296 : friend class SerializerAllocator;
297 :
298 : DISALLOW_COPY_AND_ASSIGN(Serializer);
299 : };
300 :
301 : class RelocInfoIterator;
302 :
303 : class Serializer::ObjectSerializer : public ObjectVisitor {
304 : public:
305 : ObjectSerializer(Serializer* serializer, HeapObject obj,
306 : SnapshotByteSink* sink, HowToCode how_to_code,
307 : WhereToPoint where_to_point)
308 : : serializer_(serializer),
309 : object_(obj),
310 : sink_(sink),
311 1837929 : reference_representation_(how_to_code + where_to_point),
312 3679754 : bytes_processed_so_far_(0) {
313 : #ifdef DEBUG
314 : serializer_->PushStack(obj);
315 : #endif // DEBUG
316 : }
317 : // NOLINTNEXTLINE (modernize-use-equals-default)
318 4061 : ~ObjectSerializer() override {
319 : #ifdef DEBUG
320 : serializer_->PopStack();
321 : #endif // DEBUG
322 0 : }
323 : void Serialize();
324 : void SerializeObject();
325 : void SerializeDeferred();
326 : void VisitPointers(HeapObject host, ObjectSlot start,
327 : ObjectSlot end) override;
328 : void VisitPointers(HeapObject host, MaybeObjectSlot start,
329 : MaybeObjectSlot end) override;
330 : void VisitEmbeddedPointer(Code host, RelocInfo* target) override;
331 : void VisitExternalReference(Foreign host, Address* p) override;
332 : void VisitExternalReference(Code host, RelocInfo* rinfo) override;
333 : void VisitInternalReference(Code host, RelocInfo* rinfo) override;
334 : void VisitCodeTarget(Code host, RelocInfo* target) override;
335 : void VisitRuntimeEntry(Code host, RelocInfo* reloc) override;
336 : void VisitOffHeapTarget(Code host, RelocInfo* target) override;
337 : // Relocation info needs to be visited sorted by target_address_address.
338 : void VisitRelocInfo(RelocIterator* it) override;
339 :
340 : private:
341 : void SerializePrologue(AllocationSpace space, int size, Map map);
342 :
343 : // This function outputs or skips the raw data between the last pointer and
344 : // up to the current position.
345 : void SerializeContent(Map map, int size);
346 : void OutputRawData(Address up_to);
347 : void OutputCode(int size);
348 : int SkipTo(Address to);
349 : int32_t SerializeBackingStore(void* backing_store, int32_t byte_length);
350 : void SerializeJSTypedArray();
351 : void SerializeJSArrayBuffer();
352 : void SerializeExternalString();
353 : void SerializeExternalStringAsSequentialString();
354 :
355 : Serializer* serializer_;
356 : HeapObject object_;
357 : SnapshotByteSink* sink_;
358 : int reference_representation_;
359 : int bytes_processed_so_far_;
360 : };
361 :
362 : } // namespace internal
363 : } // namespace v8
364 :
365 : #endif // V8_SNAPSHOT_SERIALIZER_H_
|