V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
serializer.h
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 
22  public:
23  explicit CodeAddressMap(Isolate* isolate) : CodeEventLogger(isolate) {
24  isolate->logger()->AddCodeEventListener(this);
25  }
26 
27  ~CodeAddressMap() override {
28  isolate_->logger()->RemoveCodeEventListener(this);
29  }
30 
31  void CodeMoveEvent(AbstractCode from, AbstractCode to) override {
32  address_to_name_map_.Move(from->address(), to->address());
33  }
34 
35  void CodeDisableOptEvent(AbstractCode code,
36  SharedFunctionInfo* shared) override {}
37 
38  const char* Lookup(Address address) {
39  return address_to_name_map_.Lookup(address);
40  }
41 
42  private:
43  class NameMap {
44  public:
45  NameMap() : impl_() {}
46 
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 
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 
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 
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  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:
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 
98  base::HashMap::Entry* FindOrCreateEntry(Address code_address) {
99  return impl_.LookupOrInsert(reinterpret_cast<void*>(code_address),
100  ComputeAddressHash(code_address));
101  }
102 
103  base::HashMap::Entry* FindEntry(Address code_address) {
104  return impl_.Lookup(reinterpret_cast<void*>(code_address),
105  ComputeAddressHash(code_address));
106  }
107 
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 
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 
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 
131  public:
132  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  bool LookupOrInsert(HeapObject* obj, int* index_out) {
138  Maybe<uint32_t> maybe_index = map_.Get(obj);
139  if (maybe_index.IsJust()) {
140  *index_out = maybe_index.FromJust();
141  return true;
142  }
143  *index_out = next_index_;
144  map_.Set(obj, next_index_++);
145  return false;
146  }
147 
148  private:
149  DisallowHeapAllocation no_allocation_;
150 
152  int next_index_;
153 
154  DISALLOW_COPY_AND_ASSIGN(ObjectCacheIndexMap);
155 };
156 
158  public:
159  explicit Serializer(Isolate* isolate);
160  ~Serializer() override;
161 
162  std::vector<SerializedData::Reservation> EncodeReservations() const {
163  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()->LookupReference(o).is_valid();
170  }
171 
172  Isolate* isolate() const { return isolate_; }
173 
174  protected:
175  class ObjectSerializer;
177  public:
178  explicit RecursionScope(Serializer* serializer) : serializer_(serializer) {
179  serializer_->recursion_depth_++;
180  }
181  ~RecursionScope() { serializer_->recursion_depth_--; }
182  bool ExceedsMaximum() {
183  return serializer_->recursion_depth_ >= kMaxRecursionDepth;
184  }
185 
186  private:
187  static const int kMaxRecursionDepth = 32;
188  Serializer* serializer_;
189  };
190 
191  void SerializeDeferredObjects();
192  virtual void SerializeObject(HeapObject* o, HowToCode how_to_code,
193  WhereToPoint where_to_point, int skip) = 0;
194 
195  virtual bool MustBeDeferred(HeapObject* object);
196 
197  void VisitRootPointers(Root root, const char* description, ObjectSlot start,
198  ObjectSlot end) override;
199  void SerializeRootObject(Object* object);
200 
201  void PutRoot(RootIndex root_index, HeapObject* object, HowToCode how,
202  WhereToPoint where, int skip);
203  void PutSmi(Smi smi);
204  void PutBackReference(HeapObject* object, SerializerReference reference);
205  void PutAttachedReference(SerializerReference reference,
206  HowToCode how_to_code, WhereToPoint where_to_point);
207  // Emit alignment prefix if necessary, return required padding space in bytes.
208  int PutAlignmentPrefix(HeapObject* object);
209  void PutNextChunk(int space);
210 
211  // Returns true if the object was successfully serialized as a root.
212  bool SerializeRoot(HeapObject* obj, HowToCode how_to_code,
213  WhereToPoint where_to_point, int skip);
214 
215  // Returns true if the object was successfully serialized as hot object.
216  bool SerializeHotObject(HeapObject* obj, HowToCode how_to_code,
217  WhereToPoint where_to_point, int skip);
218 
219  // Returns true if the object was successfully serialized as back reference.
220  bool SerializeBackReference(HeapObject* obj, HowToCode how_to_code,
221  WhereToPoint where_to_point, int skip);
222 
223  // Returns true if the given heap object is a bytecode handler code object.
224  bool ObjectIsBytecodeHandler(HeapObject* obj) const;
225 
226  static inline void FlushSkip(SnapshotByteSink* sink, int skip) {
227  if (skip != 0) {
228  sink->Put(kSkip, "SkipFromSerializeObject");
229  sink->PutInt(skip, "SkipDistanceFromSerializeObject");
230  }
231  }
232 
233  inline void FlushSkip(int skip) { FlushSkip(&sink_, skip); }
234 
235  ExternalReferenceEncoder::Value EncodeExternalReference(Address addr) {
236  return external_reference_encoder_.Encode(addr);
237  }
238 
239  // GetInt reads 4 bytes at once, requiring padding at the end.
240  // Use padding_offset to specify the space you want to use after padding.
241  void Pad(int padding_offset = 0);
242 
243  // We may not need the code address map for logging for every instance
244  // of the serializer. Initialize it on demand.
245  void InitializeCodeAddressMap();
246 
247  Code CopyCode(Code code);
248 
249  void QueueDeferredObject(HeapObject* obj) {
250  DCHECK(reference_map_.LookupReference(obj).is_back_reference());
251  deferred_objects_.push_back(obj);
252  }
253 
254  void OutputStatistics(const char* name);
255 
256 #ifdef OBJECT_PRINT
257  void CountInstanceType(Map map, int size, AllocationSpace space);
258 #endif // OBJECT_PRINT
259 
260 #ifdef DEBUG
261  void PushStack(HeapObject* o) { stack_.push_back(o); }
262  void PopStack() { stack_.pop_back(); }
263  void PrintStack();
264 #endif // DEBUG
265 
266  SerializerReferenceMap* reference_map() { return &reference_map_; }
267  const RootIndexMap* root_index_map() const { return &root_index_map_; }
268  SerializerAllocator* allocator() { return &allocator_; }
269 
270  SnapshotByteSink sink_; // Used directly by subclasses.
271 
272  private:
273  Isolate* isolate_;
274  SerializerReferenceMap reference_map_;
275  ExternalReferenceEncoder external_reference_encoder_;
276  RootIndexMap root_index_map_;
277  CodeAddressMap* code_address_map_ = nullptr;
278  std::vector<byte> code_buffer_;
279  std::vector<HeapObject*> deferred_objects_; // To handle stack overflow.
280  int recursion_depth_ = 0;
281  SerializerAllocator allocator_;
282 
283 #ifdef OBJECT_PRINT
284  static const int kInstanceTypes = LAST_TYPE + 1;
285  int* instance_type_count_[LAST_SPACE];
286  size_t* instance_type_size_[LAST_SPACE];
287 #endif // OBJECT_PRINT
288 
289 #ifdef DEBUG
290  std::vector<HeapObject*> stack_;
291 #endif // DEBUG
292 
293  friend class SerializerAllocator;
294 
295  DISALLOW_COPY_AND_ASSIGN(Serializer);
296 };
297 
298 class RelocInfoIterator;
299 
301  public:
302  ObjectSerializer(Serializer* serializer, HeapObject* obj,
303  SnapshotByteSink* sink, HowToCode how_to_code,
304  WhereToPoint where_to_point)
305  : serializer_(serializer),
306  object_(obj),
307  sink_(sink),
308  reference_representation_(how_to_code + where_to_point),
309  bytes_processed_so_far_(0) {
310 #ifdef DEBUG
311  serializer_->PushStack(obj);
312 #endif // DEBUG
313  }
314  // NOLINTNEXTLINE (modernize-use-equals-default)
315  ~ObjectSerializer() override {
316 #ifdef DEBUG
317  serializer_->PopStack();
318 #endif // DEBUG
319  }
320  void Serialize();
321  void SerializeObject();
322  void SerializeDeferred();
323  void VisitPointers(HeapObject* host, ObjectSlot start,
324  ObjectSlot end) override;
325  void VisitPointers(HeapObject* host, MaybeObjectSlot start,
326  MaybeObjectSlot end) override;
327  void VisitEmbeddedPointer(Code host, RelocInfo* target) override;
328  void VisitExternalReference(Foreign* host, Address* p) override;
329  void VisitExternalReference(Code host, RelocInfo* rinfo) override;
330  void VisitInternalReference(Code host, RelocInfo* rinfo) override;
331  void VisitCodeTarget(Code host, RelocInfo* target) override;
332  void VisitRuntimeEntry(Code host, RelocInfo* reloc) override;
333  void VisitOffHeapTarget(Code host, RelocInfo* target) override;
334  // Relocation info needs to be visited sorted by target_address_address.
335  void VisitRelocInfo(RelocIterator* it) override;
336 
337  private:
338  void SerializePrologue(AllocationSpace space, int size, Map map);
339 
340  // This function outputs or skips the raw data between the last pointer and
341  // up to the current position.
342  void SerializeContent(Map map, int size);
343  void OutputRawData(Address up_to);
344  void OutputCode(int size);
345  int SkipTo(Address to);
346  int32_t SerializeBackingStore(void* backing_store, int32_t byte_length);
347  void SerializeJSTypedArray();
348  void SerializeJSArrayBuffer();
349  void SerializeExternalString();
350  void SerializeExternalStringAsSequentialString();
351 
352  Serializer* serializer_;
353  HeapObject* object_;
354  SnapshotByteSink* sink_;
355  int reference_representation_;
356  int bytes_processed_so_far_;
357 };
358 
359 } // namespace internal
360 } // namespace v8
361 
362 #endif // V8_SNAPSHOT_SERIALIZER_H_
Definition: v8.h:56
V8_INLINE T FromJust() const
Definition: v8.h:8683
Definition: libplatform.h:13