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 "src/isolate.h"
9 : #include "src/log.h"
10 : #include "src/objects.h"
11 : #include "src/snapshot/serializer-common.h"
12 : #include "src/snapshot/snapshot-source-sink.h"
13 :
14 : namespace v8 {
15 : namespace internal {
16 :
17 : class CodeAddressMap : public CodeEventLogger {
18 : public:
19 870 : explicit CodeAddressMap(Isolate* isolate) : isolate_(isolate) {
20 580 : isolate->logger()->addCodeEventListener(this);
21 290 : }
22 :
23 870 : ~CodeAddressMap() override {
24 290 : isolate_->logger()->removeCodeEventListener(this);
25 580 : }
26 :
27 0 : void CodeMoveEvent(AbstractCode* from, Address to) override {
28 0 : address_to_name_map_.Move(from->address(), to);
29 0 : }
30 :
31 0 : void CodeDisableOptEvent(AbstractCode* code,
32 0 : SharedFunctionInfo* shared) override {}
33 :
34 : const char* Lookup(Address address) {
35 1559190 : return address_to_name_map_.Lookup(address);
36 : }
37 :
38 : private:
39 : class NameMap {
40 : public:
41 : NameMap() : impl_() {}
42 :
43 290 : ~NameMap() {
44 580 : for (base::HashMap::Entry* p = impl_.Start(); p != NULL;
45 : p = impl_.Next(p)) {
46 0 : DeleteArray(static_cast<const char*>(p->value));
47 : }
48 290 : }
49 :
50 0 : void Insert(Address code_address, const char* name, int name_size) {
51 0 : base::HashMap::Entry* entry = FindOrCreateEntry(code_address);
52 0 : if (entry->value == NULL) {
53 0 : entry->value = CopyName(name, name_size);
54 : }
55 0 : }
56 :
57 : const char* Lookup(Address code_address) {
58 1559190 : base::HashMap::Entry* entry = FindEntry(code_address);
59 1559190 : return (entry != NULL) ? static_cast<const char*>(entry->value) : NULL;
60 : }
61 :
62 : void Remove(Address code_address) {
63 : base::HashMap::Entry* entry = FindEntry(code_address);
64 : if (entry != NULL) {
65 : DeleteArray(static_cast<char*>(entry->value));
66 : RemoveEntry(entry);
67 : }
68 : }
69 :
70 0 : void Move(Address from, Address to) {
71 0 : if (from == to) return;
72 0 : base::HashMap::Entry* from_entry = FindEntry(from);
73 : DCHECK(from_entry != NULL);
74 0 : void* value = from_entry->value;
75 : RemoveEntry(from_entry);
76 0 : base::HashMap::Entry* to_entry = FindOrCreateEntry(to);
77 : DCHECK(to_entry->value == NULL);
78 0 : to_entry->value = value;
79 : }
80 :
81 : private:
82 0 : static char* CopyName(const char* name, int name_size) {
83 0 : char* result = NewArray<char>(name_size + 1);
84 0 : for (int i = 0; i < name_size; ++i) {
85 0 : char c = name[i];
86 0 : if (c == '\0') c = ' ';
87 0 : result[i] = c;
88 : }
89 0 : result[name_size] = '\0';
90 0 : return result;
91 : }
92 :
93 0 : base::HashMap::Entry* FindOrCreateEntry(Address code_address) {
94 : return impl_.LookupOrInsert(code_address,
95 0 : ComputePointerHash(code_address));
96 : }
97 :
98 1559190 : base::HashMap::Entry* FindEntry(Address code_address) {
99 1559190 : return impl_.Lookup(code_address, ComputePointerHash(code_address));
100 : }
101 :
102 : void RemoveEntry(base::HashMap::Entry* entry) {
103 0 : impl_.Remove(entry->key, entry->hash);
104 : }
105 :
106 : base::HashMap impl_;
107 :
108 : DISALLOW_COPY_AND_ASSIGN(NameMap);
109 : };
110 :
111 0 : void LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo*,
112 : const char* name, int length) override {
113 0 : address_to_name_map_.Insert(code->address(), name, length);
114 0 : }
115 :
116 : NameMap address_to_name_map_;
117 : Isolate* isolate_;
118 : };
119 :
120 : // There can be only one serializer per V8 process.
121 : class Serializer : public SerializerDeserializer {
122 : public:
123 : explicit Serializer(Isolate* isolate);
124 : ~Serializer() override;
125 :
126 : void EncodeReservations(List<SerializedData::Reservation>* out) const;
127 :
128 : void SerializeDeferredObjects();
129 :
130 : Isolate* isolate() const { return isolate_; }
131 :
132 : SerializerReferenceMap* reference_map() { return &reference_map_; }
133 : RootIndexMap* root_index_map() { return &root_index_map_; }
134 :
135 : #ifdef OBJECT_PRINT
136 : void CountInstanceType(Map* map, int size);
137 : #endif // OBJECT_PRINT
138 :
139 : protected:
140 : class ObjectSerializer;
141 : class RecursionScope {
142 : public:
143 : explicit RecursionScope(Serializer* serializer) : serializer_(serializer) {
144 1610999 : serializer_->recursion_depth_++;
145 : }
146 1610999 : ~RecursionScope() { serializer_->recursion_depth_--; }
147 : bool ExceedsMaximum() {
148 : return serializer_->recursion_depth_ >= kMaxRecursionDepth;
149 : }
150 :
151 : private:
152 : static const int kMaxRecursionDepth = 32;
153 : Serializer* serializer_;
154 : };
155 :
156 : virtual void SerializeObject(HeapObject* o, HowToCode how_to_code,
157 : WhereToPoint where_to_point, int skip) = 0;
158 :
159 : void VisitRootPointers(Root root, Object** start, Object** end) override;
160 :
161 : void PutRoot(int index, HeapObject* object, HowToCode how, WhereToPoint where,
162 : int skip);
163 :
164 : void PutSmi(Smi* smi);
165 :
166 : void PutBackReference(HeapObject* object, SerializerReference reference);
167 :
168 : void PutAttachedReference(SerializerReference reference,
169 : HowToCode how_to_code, WhereToPoint where_to_point);
170 :
171 : // Emit alignment prefix if necessary, return required padding space in bytes.
172 : int PutAlignmentPrefix(HeapObject* object);
173 :
174 : // Returns true if the object was successfully serialized as hot object.
175 : bool SerializeHotObject(HeapObject* obj, HowToCode how_to_code,
176 : WhereToPoint where_to_point, int skip);
177 :
178 : // Returns true if the object was successfully serialized as back reference.
179 : bool SerializeBackReference(HeapObject* obj, HowToCode how_to_code,
180 : WhereToPoint where_to_point, int skip);
181 :
182 2354242 : inline void FlushSkip(int skip) {
183 2354242 : if (skip != 0) {
184 : sink_.Put(kSkip, "SkipFromSerializeObject");
185 33858 : sink_.PutInt(skip, "SkipDistanceFromSerializeObject");
186 : }
187 2354242 : }
188 :
189 : bool BackReferenceIsAlreadyAllocated(SerializerReference back_reference);
190 :
191 : // This will return the space for an object.
192 : SerializerReference AllocateLargeObject(int size);
193 : SerializerReference AllocateMap();
194 : SerializerReference Allocate(AllocationSpace space, int size);
195 : int EncodeExternalReference(Address addr) {
196 976799 : return external_reference_encoder_.Encode(addr);
197 : }
198 :
199 : bool HasNotExceededFirstPageOfEachSpace();
200 :
201 : // GetInt reads 4 bytes at once, requiring padding at the end.
202 : void Pad();
203 :
204 : // We may not need the code address map for logging for every instance
205 : // of the serializer. Initialize it on demand.
206 : void InitializeCodeAddressMap();
207 :
208 : Code* CopyCode(Code* code);
209 :
210 : inline uint32_t max_chunk_size(int space) const {
211 : DCHECK_LE(0, space);
212 : DCHECK_LT(space, kNumberOfSpaces);
213 1538095 : return max_chunk_size_[space];
214 : }
215 :
216 : const SnapshotByteSink* sink() const { return &sink_; }
217 :
218 : void QueueDeferredObject(HeapObject* obj) {
219 : DCHECK(reference_map_.Lookup(obj).is_back_reference());
220 12437 : deferred_objects_.Add(obj);
221 : }
222 :
223 : void OutputStatistics(const char* name);
224 :
225 : Isolate* isolate_;
226 :
227 : SnapshotByteSink sink_;
228 : ExternalReferenceEncoder external_reference_encoder_;
229 :
230 : SerializerReferenceMap reference_map_;
231 : RootIndexMap root_index_map_;
232 :
233 : int recursion_depth_;
234 :
235 : friend class Deserializer;
236 : friend class ObjectSerializer;
237 : friend class RecursionScope;
238 : friend class SnapshotData;
239 :
240 : private:
241 : CodeAddressMap* code_address_map_;
242 : // Objects from the same space are put into chunks for bulk-allocation
243 : // when deserializing. We have to make sure that each chunk fits into a
244 : // page. So we track the chunk size in pending_chunk_ of a space, but
245 : // when it exceeds a page, we complete the current chunk and start a new one.
246 : uint32_t pending_chunk_[kNumberOfPreallocatedSpaces];
247 : List<uint32_t> completed_chunks_[kNumberOfPreallocatedSpaces];
248 : uint32_t max_chunk_size_[kNumberOfPreallocatedSpaces];
249 : // Number of maps that we need to allocate.
250 : uint32_t num_maps_;
251 :
252 : // We map serialized large objects to indexes for back-referencing.
253 : uint32_t large_objects_total_size_;
254 : uint32_t seen_large_objects_index_;
255 :
256 : List<byte> code_buffer_;
257 :
258 : // To handle stack overflow.
259 : List<HeapObject*> deferred_objects_;
260 :
261 : #ifdef OBJECT_PRINT
262 : static const int kInstanceTypes = 256;
263 : int* instance_type_count_;
264 : size_t* instance_type_size_;
265 : #endif // OBJECT_PRINT
266 :
267 : DISALLOW_COPY_AND_ASSIGN(Serializer);
268 : };
269 :
270 : class Serializer::ObjectSerializer : public ObjectVisitor {
271 : public:
272 : ObjectSerializer(Serializer* serializer, HeapObject* obj,
273 : SnapshotByteSink* sink, HowToCode how_to_code,
274 : WhereToPoint where_to_point)
275 : : serializer_(serializer),
276 : object_(obj),
277 : sink_(sink),
278 1611029 : reference_representation_(how_to_code + where_to_point),
279 : bytes_processed_so_far_(0),
280 3234495 : code_has_been_output_(false) {}
281 12437 : ~ObjectSerializer() override {}
282 : void Serialize();
283 : void SerializeContent();
284 : void SerializeDeferred();
285 : void VisitPointers(HeapObject* host, Object** start, Object** end) override;
286 : void VisitEmbeddedPointer(Code* host, RelocInfo* target) override;
287 : void VisitExternalReference(Foreign* host, Address* p) override;
288 : void VisitExternalReference(Code* host, RelocInfo* rinfo) override;
289 : void VisitInternalReference(Code* host, RelocInfo* rinfo) override;
290 : void VisitCodeTarget(Code* host, RelocInfo* target) override;
291 : void VisitCodeEntry(JSFunction* host, Address entry_address) override;
292 : void VisitCellPointer(Code* host, RelocInfo* rinfo) override;
293 : void VisitRuntimeEntry(Code* host, RelocInfo* reloc) override;
294 :
295 : private:
296 : bool TryEncodeDeoptimizationEntry(HowToCode how_to_code, Address target,
297 : int skip);
298 : void SerializePrologue(AllocationSpace space, int size, Map* map);
299 :
300 :
301 : enum ReturnSkip { kCanReturnSkipInsteadOfSkipping, kIgnoringReturn };
302 : // This function outputs or skips the raw data between the last pointer and
303 : // up to the current position. It optionally can just return the number of
304 : // bytes to skip instead of performing a skip instruction, in case the skip
305 : // can be merged into the next instruction.
306 : int OutputRawData(Address up_to, ReturnSkip return_skip = kIgnoringReturn);
307 : void SerializeExternalString();
308 : void SerializeExternalStringAsSequentialString();
309 :
310 : Address PrepareCode();
311 :
312 : Serializer* serializer_;
313 : HeapObject* object_;
314 : SnapshotByteSink* sink_;
315 : int reference_representation_;
316 : int bytes_processed_so_far_;
317 : bool code_has_been_output_;
318 : };
319 :
320 : } // namespace internal
321 : } // namespace v8
322 :
323 : #endif // V8_SNAPSHOT_SERIALIZER_H_
|