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/default-serializer-allocator.h"
14 : #include "src/snapshot/serializer-common.h"
15 : #include "src/snapshot/snapshot-source-sink.h"
16 :
17 : namespace v8 {
18 : namespace internal {
19 :
20 : class CodeAddressMap : public CodeEventLogger {
21 : public:
22 936 : explicit CodeAddressMap(Isolate* isolate) : isolate_(isolate) {
23 624 : isolate->logger()->addCodeEventListener(this);
24 312 : }
25 :
26 936 : ~CodeAddressMap() override {
27 312 : isolate_->logger()->removeCodeEventListener(this);
28 624 : }
29 :
30 0 : void CodeMoveEvent(AbstractCode* from, Address to) override {
31 0 : address_to_name_map_.Move(from->address(), to);
32 0 : }
33 :
34 0 : void CodeDisableOptEvent(AbstractCode* code,
35 0 : SharedFunctionInfo* shared) override {}
36 :
37 : const char* Lookup(Address address) {
38 1348056 : return address_to_name_map_.Lookup(address);
39 : }
40 :
41 : private:
42 : class NameMap {
43 : public:
44 : NameMap() : impl_() {}
45 :
46 312 : ~NameMap() {
47 624 : for (base::HashMap::Entry* p = impl_.Start(); p != nullptr;
48 : p = impl_.Next(p)) {
49 0 : DeleteArray(static_cast<const char*>(p->value));
50 : }
51 312 : }
52 :
53 0 : void Insert(Address code_address, const char* name, int name_size) {
54 0 : base::HashMap::Entry* entry = FindOrCreateEntry(code_address);
55 0 : if (entry->value == nullptr) {
56 0 : entry->value = CopyName(name, name_size);
57 : }
58 0 : }
59 :
60 : const char* Lookup(Address code_address) {
61 1348056 : base::HashMap::Entry* entry = FindEntry(code_address);
62 : return (entry != nullptr) ? static_cast<const char*>(entry->value)
63 1348056 : : nullptr;
64 : }
65 :
66 : void Remove(Address code_address) {
67 : base::HashMap::Entry* entry = FindEntry(code_address);
68 : if (entry != nullptr) {
69 : DeleteArray(static_cast<char*>(entry->value));
70 : RemoveEntry(entry);
71 : }
72 : }
73 :
74 0 : void Move(Address from, Address to) {
75 0 : if (from == to) return;
76 0 : base::HashMap::Entry* from_entry = FindEntry(from);
77 : DCHECK_NOT_NULL(from_entry);
78 0 : void* value = from_entry->value;
79 : RemoveEntry(from_entry);
80 0 : base::HashMap::Entry* to_entry = FindOrCreateEntry(to);
81 : DCHECK_NULL(to_entry->value);
82 0 : to_entry->value = value;
83 : }
84 :
85 : private:
86 0 : static char* CopyName(const char* name, int name_size) {
87 0 : char* result = NewArray<char>(name_size + 1);
88 0 : for (int i = 0; i < name_size; ++i) {
89 0 : char c = name[i];
90 0 : if (c == '\0') c = ' ';
91 0 : result[i] = c;
92 : }
93 0 : result[name_size] = '\0';
94 0 : return result;
95 : }
96 :
97 0 : base::HashMap::Entry* FindOrCreateEntry(Address code_address) {
98 : return impl_.LookupOrInsert(code_address,
99 0 : ComputePointerHash(code_address));
100 : }
101 :
102 1348056 : base::HashMap::Entry* FindEntry(Address code_address) {
103 1348056 : return impl_.Lookup(code_address, ComputePointerHash(code_address));
104 : }
105 :
106 : void RemoveEntry(base::HashMap::Entry* entry) {
107 0 : impl_.Remove(entry->key, entry->hash);
108 : }
109 :
110 : base::HashMap impl_;
111 :
112 : DISALLOW_COPY_AND_ASSIGN(NameMap);
113 : };
114 :
115 0 : void LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo*,
116 : const char* name, int length) override {
117 0 : address_to_name_map_.Insert(code->address(), name, length);
118 0 : }
119 :
120 : NameMap address_to_name_map_;
121 : Isolate* isolate_;
122 : };
123 :
124 : template <class AllocatorT = DefaultSerializerAllocator>
125 : class Serializer : public SerializerDeserializer {
126 : public:
127 : explicit Serializer(Isolate* isolate);
128 : ~Serializer() override;
129 :
130 0 : std::vector<SerializedData::Reservation> EncodeReservations() const {
131 891 : return allocator_.EncodeReservations();
132 : }
133 :
134 0 : const std::vector<byte>* Payload() const { return sink_.data(); }
135 :
136 0 : bool ReferenceMapContains(HeapObject* o) {
137 0 : return reference_map()->Lookup(o).is_valid();
138 : }
139 :
140 15193 : Isolate* isolate() const { return isolate_; }
141 :
142 : protected:
143 : class ObjectSerializer;
144 : class RecursionScope {
145 : public:
146 0 : explicit RecursionScope(Serializer* serializer) : serializer_(serializer) {
147 1511422 : serializer_->recursion_depth_++;
148 0 : }
149 1511422 : ~RecursionScope() { serializer_->recursion_depth_--; }
150 0 : bool ExceedsMaximum() {
151 0 : return serializer_->recursion_depth_ >= kMaxRecursionDepth;
152 : }
153 :
154 : private:
155 : static const int kMaxRecursionDepth = 32;
156 : Serializer* serializer_;
157 : };
158 :
159 : void SerializeDeferredObjects();
160 : virtual void SerializeObject(HeapObject* o, HowToCode how_to_code,
161 : WhereToPoint where_to_point, int skip) = 0;
162 :
163 : virtual bool MustBeDeferred(HeapObject* object);
164 :
165 : void VisitRootPointers(Root root, Object** start, Object** end) override;
166 :
167 : void PutRoot(int index, HeapObject* object, HowToCode how, WhereToPoint where,
168 : int skip);
169 : void PutSmi(Smi* smi);
170 : void PutBackReference(HeapObject* object, SerializerReference reference);
171 : void PutAttachedReference(SerializerReference reference,
172 : HowToCode how_to_code, WhereToPoint where_to_point);
173 : // Emit alignment prefix if necessary, return required padding space in bytes.
174 : int PutAlignmentPrefix(HeapObject* object);
175 : void PutNextChunk(int space);
176 :
177 : // Returns true if the object was successfully serialized as hot object.
178 : bool SerializeHotObject(HeapObject* obj, HowToCode how_to_code,
179 : WhereToPoint where_to_point, int skip);
180 :
181 : // Returns true if the object was successfully serialized as back reference.
182 : bool SerializeBackReference(HeapObject* obj, HowToCode how_to_code,
183 : WhereToPoint where_to_point, int skip);
184 :
185 : // Determines whether the interpreter trampoline is replaced by CompileLazy.
186 : enum BuiltinReferenceSerializationMode {
187 : kDefault,
188 : kCanonicalizeCompileLazy,
189 : };
190 :
191 : // Returns true if the object was successfully serialized as a builtin
192 : // reference.
193 : bool SerializeBuiltinReference(
194 : HeapObject* obj, HowToCode how_to_code, WhereToPoint where_to_point,
195 : int skip, BuiltinReferenceSerializationMode mode = kDefault);
196 :
197 3611691 : inline void FlushSkip(int skip) {
198 3611691 : if (skip != 0) {
199 : sink_.Put(kSkip, "SkipFromSerializeObject");
200 974678 : sink_.PutInt(skip, "SkipDistanceFromSerializeObject");
201 : }
202 3611691 : }
203 :
204 0 : ExternalReferenceEncoder::Value EncodeExternalReference(Address addr) {
205 845893 : return external_reference_encoder_.Encode(addr);
206 : }
207 :
208 : // GetInt reads 4 bytes at once, requiring padding at the end.
209 : void Pad();
210 :
211 : // We may not need the code address map for logging for every instance
212 : // of the serializer. Initialize it on demand.
213 : void InitializeCodeAddressMap();
214 :
215 : Code* CopyCode(Code* code);
216 :
217 0 : void QueueDeferredObject(HeapObject* obj) {
218 : DCHECK(reference_map_.Lookup(obj).is_back_reference());
219 3628 : deferred_objects_.push_back(obj);
220 0 : }
221 :
222 : void OutputStatistics(const char* name);
223 :
224 : #ifdef OBJECT_PRINT
225 : void CountInstanceType(Map* map, int size);
226 : #endif // OBJECT_PRINT
227 :
228 : #ifdef DEBUG
229 : void PushStack(HeapObject* o) { stack_.push_back(o); }
230 : void PopStack() { stack_.pop_back(); }
231 : void PrintStack();
232 : #endif // DEBUG
233 :
234 0 : SerializerReferenceMap* reference_map() { return &reference_map_; }
235 0 : RootIndexMap* root_index_map() { return &root_index_map_; }
236 0 : AllocatorT* allocator() { return &allocator_; }
237 :
238 : SnapshotByteSink sink_; // Used directly by subclasses.
239 :
240 : private:
241 : Isolate* isolate_;
242 : SerializerReferenceMap reference_map_;
243 : ExternalReferenceEncoder external_reference_encoder_;
244 : RootIndexMap root_index_map_;
245 : CodeAddressMap* code_address_map_ = nullptr;
246 : std::vector<byte> code_buffer_;
247 : std::vector<HeapObject*> deferred_objects_; // To handle stack overflow.
248 : int recursion_depth_ = 0;
249 : AllocatorT allocator_;
250 :
251 : #ifdef OBJECT_PRINT
252 : static const int kInstanceTypes = 256;
253 : int* instance_type_count_;
254 : size_t* instance_type_size_;
255 : #endif // OBJECT_PRINT
256 :
257 : #ifdef DEBUG
258 : std::vector<HeapObject*> stack_;
259 : #endif // DEBUG
260 :
261 : friend class DefaultSerializerAllocator;
262 :
263 : DISALLOW_COPY_AND_ASSIGN(Serializer);
264 : };
265 :
266 : template <class AllocatorT>
267 : class Serializer<AllocatorT>::ObjectSerializer : public ObjectVisitor {
268 : public:
269 0 : ObjectSerializer(Serializer* serializer, HeapObject* obj,
270 : SnapshotByteSink* sink, HowToCode how_to_code,
271 : WhereToPoint where_to_point)
272 : : serializer_(serializer),
273 : object_(obj),
274 : sink_(sink),
275 : reference_representation_(how_to_code + where_to_point),
276 3030150 : bytes_processed_so_far_(0) {
277 : #ifdef DEBUG
278 : serializer_->PushStack(obj);
279 : #endif // DEBUG
280 0 : }
281 0 : ~ObjectSerializer() override {
282 : #ifdef DEBUG
283 : serializer_->PopStack();
284 : #endif // DEBUG
285 1515075 : }
286 : void Serialize();
287 : void SerializeObject();
288 : void SerializeDeferred();
289 : void VisitPointers(HeapObject* host, Object** start, Object** end) override;
290 : void VisitEmbeddedPointer(Code* host, RelocInfo* target) override;
291 : void VisitExternalReference(Foreign* host, Address* p) override;
292 : void VisitExternalReference(Code* host, RelocInfo* rinfo) override;
293 : void VisitInternalReference(Code* host, RelocInfo* rinfo) override;
294 : void VisitCodeTarget(Code* host, RelocInfo* target) override;
295 : void VisitRuntimeEntry(Code* host, RelocInfo* reloc) override;
296 :
297 : private:
298 : void SerializePrologue(AllocationSpace space, int size, Map* map);
299 :
300 : // This function outputs or skips the raw data between the last pointer and
301 : // up to the current position.
302 : void SerializeContent(Map* map, int size);
303 : void OutputRawData(Address up_to);
304 : void OutputCode(int size);
305 : int SkipTo(Address to);
306 : int32_t SerializeBackingStore(void* backing_store, int32_t byte_length);
307 : void FixupIfNeutered();
308 : void SerializeJSArrayBuffer();
309 : void SerializeFixedTypedArray();
310 : void SerializeExternalString();
311 : void SerializeExternalStringAsSequentialString();
312 :
313 : Serializer* serializer_;
314 : HeapObject* object_;
315 : SnapshotByteSink* sink_;
316 : std::map<void*, Smi*> backing_stores;
317 : int reference_representation_;
318 : int bytes_processed_so_far_;
319 : };
320 :
321 : } // namespace internal
322 : } // namespace v8
323 :
324 : #endif // V8_SNAPSHOT_SERIALIZER_H_
|