• 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_COMMON_H_
6 #define V8_SNAPSHOT_SERIALIZER_COMMON_H_
7 
8 #include "src/address-map.h"
9 #include "src/base/bits.h"
10 #include "src/external-reference-table.h"
11 #include "src/globals.h"
12 #include "src/snapshot/references.h"
13 #include "src/v8memory.h"
14 #include "src/visitors.h"
15 
16 namespace v8 {
17 namespace internal {
18 
19 class CallHandlerInfo;
20 class Isolate;
21 
22 class ExternalReferenceEncoder {
23  public:
24   class Value {
25    public:
Value(uint32_t raw)26     explicit Value(uint32_t raw) : value_(raw) {}
Value()27     Value() : value_(0) {}
Encode(uint32_t index,bool is_from_api)28     static uint32_t Encode(uint32_t index, bool is_from_api) {
29       return Index::encode(index) | IsFromAPI::encode(is_from_api);
30     }
31 
is_from_api()32     bool is_from_api() const { return IsFromAPI::decode(value_); }
index()33     uint32_t index() const { return Index::decode(value_); }
34 
35    private:
36     class Index : public BitField<uint32_t, 0, 31> {};
37     class IsFromAPI : public BitField<bool, 31, 1> {};
38     uint32_t value_;
39   };
40 
41   explicit ExternalReferenceEncoder(Isolate* isolate);
42   ~ExternalReferenceEncoder();
43 
44   Value Encode(Address key);
45   Maybe<Value> TryEncode(Address key);
46 
47   const char* NameOfAddress(Isolate* isolate, Address address) const;
48 
49  private:
50   AddressToIndexHashMap* map_;
51 
52 #ifdef DEBUG
53   std::vector<int> count_;
54   const intptr_t* api_references_;
55 #endif  // DEBUG
56 
57   DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
58 };
59 
60 class HotObjectsList {
61  public:
HotObjectsList()62   HotObjectsList() : index_(0) {
63     for (int i = 0; i < kSize; i++) circular_queue_[i] = nullptr;
64   }
65 
Add(HeapObject * object)66   void Add(HeapObject* object) {
67     DCHECK(!AllowHeapAllocation::IsAllowed());
68     circular_queue_[index_] = object;
69     index_ = (index_ + 1) & kSizeMask;
70   }
71 
Get(int index)72   HeapObject* Get(int index) {
73     DCHECK(!AllowHeapAllocation::IsAllowed());
74     DCHECK_NOT_NULL(circular_queue_[index]);
75     return circular_queue_[index];
76   }
77 
78   static const int kNotFound = -1;
79 
Find(HeapObject * object)80   int Find(HeapObject* object) {
81     DCHECK(!AllowHeapAllocation::IsAllowed());
82     for (int i = 0; i < kSize; i++) {
83       if (circular_queue_[i] == object) return i;
84     }
85     return kNotFound;
86   }
87 
88   static const int kSize = 8;
89 
90  private:
91   static_assert(base::bits::IsPowerOfTwo(kSize), "kSize must be power of two");
92   static const int kSizeMask = kSize - 1;
93   HeapObject* circular_queue_[kSize];
94   int index_;
95 
96   DISALLOW_COPY_AND_ASSIGN(HotObjectsList);
97 };
98 
99 // The Serializer/Deserializer class is a common superclass for Serializer and
100 // Deserializer which is used to store common constants and methods used by
101 // both.
102 class SerializerDeserializer : public RootVisitor {
103  public:
104   static void Iterate(Isolate* isolate, RootVisitor* visitor);
105 
106   // No reservation for large object space necessary.
107   // We also handle map space differenly.
108   STATIC_ASSERT(MAP_SPACE == CODE_SPACE + 1);
109 
110   // We do not support young generation large objects.
111   STATIC_ASSERT(LAST_SPACE == NEW_LO_SPACE);
112   STATIC_ASSERT(LAST_SPACE - 1 == LO_SPACE);
113   static const int kNumberOfPreallocatedSpaces = CODE_SPACE + 1;
114   static const int kNumberOfSpaces = LO_SPACE + 1;
115 
116  protected:
117   static bool CanBeDeferred(HeapObject* o);
118 
119   void RestoreExternalReferenceRedirectors(
120       const std::vector<AccessorInfo*>& accessor_infos);
121   void RestoreExternalReferenceRedirectors(
122       const std::vector<CallHandlerInfo*>& call_handler_infos);
123 
124 #define UNUSED_SERIALIZER_BYTE_CODES(V) \
125   V(0x18)                               \
126   V(0x3d)                               \
127   V(0x3e)                               \
128   V(0x3f)                               \
129   V(0x58)                               \
130   V(0x59)                               \
131   V(0x5a)                               \
132   V(0x5b)                               \
133   V(0x5c)                               \
134   V(0x5d)                               \
135   V(0x5e)                               \
136   V(0x5f)                               \
137   V(0x67)                               \
138   V(0x76)                               \
139   V(0x78)                               \
140   V(0x79)                               \
141   V(0x7a)                               \
142   V(0x7b)                               \
143   V(0x7c)                               \
144   V(0x7d)
145 
146   // ---------- byte code range 0x00..0x7f ----------
147   // Byte codes in this range represent Where, HowToCode and WhereToPoint.
148   // Where the pointed-to object can be found:
149   // The static assert below will trigger when the number of preallocated spaces
150   // changed. If that happens, update the bytecode ranges in the comments below.
151   STATIC_ASSERT(6 == kNumberOfSpaces);
152   enum Where {
153     // 0x00..0x05  Allocate new object, in specified space.
154     kNewObject = 0x00,
155     // 0x08..0x0d  Reference to previous object from space.
156     kBackref = 0x08,
157     // 0x10..0x15  Reference to previous object from space after skip.
158     kBackrefWithSkip = 0x10,
159 
160     // 0x06        Object in the partial snapshot cache.
161     kPartialSnapshotCache = 0x06,
162     // 0x07        External reference referenced by id.
163     kExternalReference = 0x07,
164 
165     // 0x0e        Builtin code referenced by index.
166     kBuiltin = 0x0e,
167     // 0x16       Root array item.
168     kRootArray = 0x16,
169     // 0x17        Object provided in the attached list.
170     kAttachedReference = 0x17,
171 
172     // 0x0f        Misc, see below (incl. 0x2f, 0x4f, 0x6f).
173     // 0x18..0x1f  Misc, see below (incl. 0x38..0x3f, 0x58..0x5f, 0x78..0x7f).
174   };
175 
176   static const int kWhereMask = 0x1f;
177   static const int kSpaceMask = 7;
178   STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
179 
180   // How to code the pointer to the object.
181   enum HowToCode {
182     // Straight pointer.
183     kPlain = 0,
184     // A pointer inlined in code. What this means depends on the architecture.
185     kFromCode = 0x20
186   };
187 
188   static const int kHowToCodeMask = 0x20;
189 
190   // Where to point within the object.
191   enum WhereToPoint {
192     // Points to start of object
193     kStartOfObject = 0,
194     // Points to instruction in code object or payload of cell.
195     kInnerPointer = 0x40
196   };
197 
198   static const int kWhereToPointMask = 0x40;
199 
200   // ---------- Misc ----------
201   // Skip.
202   static const int kSkip = 0x0f;
203   // Do nothing, used for padding.
204   static const int kNop = 0x2f;
205   // Move to next reserved chunk.
206   static const int kNextChunk = 0x4f;
207   // Deferring object content.
208   static const int kDeferred = 0x6f;
209   // Alignment prefixes 0x19..0x1b
210   static const int kAlignmentPrefix = 0x19;
211   // A tag emitted at strategic points in the snapshot to delineate sections.
212   // If the deserializer does not find these at the expected moments then it
213   // is an indication that the snapshot and the VM do not fit together.
214   // Examine the build process for architecture, version or configuration
215   // mismatches.
216   static const int kSynchronize = 0x1c;
217   // Repeats of variable length.
218   static const int kVariableRepeat = 0x1d;
219   // Raw data of variable length.
220 
221   // Used for embedder-allocated backing stores for TypedArrays.
222   static const int kOffHeapBackingStore = 0x1e;
223 
224   // Used for embedder-provided serialization data for embedder fields.
225   static const int kEmbedderFieldsData = 0x1f;
226 
227   // Used to encode external referenced provided through the API.
228   static const int kApiReference = 0x38;
229 
230   static const int kVariableRawCode = 0x39;
231   static const int kVariableRawData = 0x3a;
232 
233   static const int kInternalReference = 0x3b;
234   static const int kInternalReferenceEncoded = 0x3c;
235 
236   // In-place weak references
237   static const int kWeakPrefix = 0x7e;
238 
239   // Encodes an off-heap instruction stream target.
240   static const int kOffHeapTarget = 0x7f;
241 
242   // ---------- byte code range 0x80..0xff ----------
243   // First 32 root array items.
244   static const int kNumberOfRootArrayConstants = 0x20;
245   // 0x80..0x9f
246   static const int kRootArrayConstants = 0x80;
247   // 0xa0..0xbf
248   static const int kRootArrayConstantsWithSkip = 0xa0;
249   static const int kRootArrayConstantsMask = 0x1f;
250 
251   // 32 common raw data lengths.
252   static const int kNumberOfFixedRawData = 0x20;
253   // 0xc0..0xdf
254   static const int kFixedRawData = 0xc0;
255   static const int kOnePointerRawData = kFixedRawData;
256   static const int kFixedRawDataStart = kFixedRawData - 1;
257 
258   // 16 repeats lengths.
259   static const int kNumberOfFixedRepeat = 0x10;
260   // 0xe0..0xef
261   static const int kFixedRepeat = 0xe0;
262   static const int kFixedRepeatStart = kFixedRepeat - 1;
263 
264   // 8 hot (recently seen or back-referenced) objects with optional skip.
265   static const int kNumberOfHotObjects = 8;
266   STATIC_ASSERT(kNumberOfHotObjects == HotObjectsList::kSize);
267   // 0xf0..0xf7
268   static const int kHotObject = 0xf0;
269   // 0xf8..0xff
270   static const int kHotObjectWithSkip = 0xf8;
271   static const int kHotObjectMask = 0x07;
272 
273   // ---------- special values ----------
274   static const int kAnyOldSpace = -1;
275 
276   // Sentinel after a new object to indicate that double alignment is needed.
277   static const int kDoubleAlignmentSentinel = 0;
278 
279   // ---------- member variable ----------
280   HotObjectsList hot_objects_;
281 };
282 
283 class SerializedData {
284  public:
285   class Reservation {
286    public:
Reservation()287     Reservation() : reservation_(0) {}
Reservation(uint32_t size)288     explicit Reservation(uint32_t size)
289         : reservation_(ChunkSizeBits::encode(size)) {}
290 
chunk_size()291     uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); }
is_last()292     bool is_last() const { return IsLastChunkBits::decode(reservation_); }
293 
mark_as_last()294     void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); }
295 
296    private:
297     uint32_t reservation_;
298   };
299 
SerializedData(byte * data,int size)300   SerializedData(byte* data, int size)
301       : data_(data), size_(size), owns_data_(false) {}
SerializedData()302   SerializedData() : data_(nullptr), size_(0), owns_data_(false) {}
SerializedData(SerializedData && other)303   SerializedData(SerializedData&& other) V8_NOEXCEPT
304       : data_(other.data_),
305         size_(other.size_),
306         owns_data_(other.owns_data_) {
307     // Ensure |other| will not attempt to destroy our data in destructor.
308     other.owns_data_ = false;
309   }
310 
~SerializedData()311   virtual ~SerializedData() {
312     if (owns_data_) DeleteArray<byte>(data_);
313   }
314 
GetMagicNumber()315   uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }
316 
317   class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
318   class IsLastChunkBits : public BitField<bool, 31, 1> {};
319 
ComputeMagicNumber(ExternalReferenceTable * table)320   static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) {
321     uint32_t external_refs = table->size();
322     return 0xC0DE0000 ^ external_refs;
323   }
324 
325   static const uint32_t kMagicNumberOffset = 0;
326 
327  protected:
SetHeaderValue(uint32_t offset,uint32_t value)328   void SetHeaderValue(uint32_t offset, uint32_t value) {
329     WriteLittleEndianValue(reinterpret_cast<Address>(data_) + offset, value);
330   }
331 
GetHeaderValue(uint32_t offset)332   uint32_t GetHeaderValue(uint32_t offset) const {
333     return ReadLittleEndianValue<uint32_t>(reinterpret_cast<Address>(data_) +
334                                            offset);
335   }
336 
337   void AllocateData(uint32_t size);
338 
339   static uint32_t ComputeMagicNumber(Isolate* isolate);
340 
SetMagicNumber(Isolate * isolate)341   void SetMagicNumber(Isolate* isolate) {
342     SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate));
343   }
344 
345   byte* data_;
346   uint32_t size_;
347   bool owns_data_;
348 
349  private:
350   DISALLOW_COPY_AND_ASSIGN(SerializedData);
351 };
352 
353 }  // namespace internal
354 }  // namespace v8
355 
356 #endif  // V8_SNAPSHOT_SERIALIZER_COMMON_H_
357