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