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/external-reference-table.h"
10 #include "src/globals.h"
11 
12 namespace v8 {
13 namespace internal {
14 
15 class Isolate;
16 
17 class ExternalReferenceEncoder {
18  public:
19   explicit ExternalReferenceEncoder(Isolate* isolate);
20 
21   uint32_t Encode(Address key) const;
22 
23   const char* NameOfAddress(Isolate* isolate, Address address) const;
24 
25  private:
26   AddressToIndexHashMap* map_;
27 #ifdef DEBUG
28   ExternalReferenceTable* table_;
29 #endif  // DEBUG
30 
31   DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
32 };
33 
34 class HotObjectsList {
35  public:
HotObjectsList()36   HotObjectsList() : index_(0) {
37     for (int i = 0; i < kSize; i++) circular_queue_[i] = NULL;
38   }
39 
Add(HeapObject * object)40   void Add(HeapObject* object) {
41     DCHECK(!AllowHeapAllocation::IsAllowed());
42     circular_queue_[index_] = object;
43     index_ = (index_ + 1) & kSizeMask;
44   }
45 
Get(int index)46   HeapObject* Get(int index) {
47     DCHECK(!AllowHeapAllocation::IsAllowed());
48     DCHECK_NOT_NULL(circular_queue_[index]);
49     return circular_queue_[index];
50   }
51 
52   static const int kNotFound = -1;
53 
Find(HeapObject * object)54   int Find(HeapObject* object) {
55     DCHECK(!AllowHeapAllocation::IsAllowed());
56     for (int i = 0; i < kSize; i++) {
57       if (circular_queue_[i] == object) return i;
58     }
59     return kNotFound;
60   }
61 
62   static const int kSize = 8;
63 
64  private:
65   STATIC_ASSERT(IS_POWER_OF_TWO(kSize));
66   static const int kSizeMask = kSize - 1;
67   HeapObject* circular_queue_[kSize];
68   int index_;
69 
70   DISALLOW_COPY_AND_ASSIGN(HotObjectsList);
71 };
72 
73 // The Serializer/Deserializer class is a common superclass for Serializer and
74 // Deserializer which is used to store common constants and methods used by
75 // both.
76 class SerializerDeserializer : public ObjectVisitor {
77  public:
78   static void Iterate(Isolate* isolate, ObjectVisitor* visitor);
79 
80   // No reservation for large object space necessary.
81   // We also handle map space differenly.
82   STATIC_ASSERT(MAP_SPACE == CODE_SPACE + 1);
83   static const int kNumberOfPreallocatedSpaces = CODE_SPACE + 1;
84   static const int kNumberOfSpaces = LAST_SPACE + 1;
85 
86  protected:
87   static bool CanBeDeferred(HeapObject* o);
88 
89   // ---------- byte code range 0x00..0x7f ----------
90   // Byte codes in this range represent Where, HowToCode and WhereToPoint.
91   // Where the pointed-to object can be found:
92   // The static assert below will trigger when the number of preallocated spaces
93   // changed. If that happens, update the bytecode ranges in the comments below.
94   STATIC_ASSERT(5 == kNumberOfSpaces);
95   enum Where {
96     // 0x00..0x04  Allocate new object, in specified space.
97     kNewObject = 0x00,
98     // 0x08..0x0c  Reference to previous object from space.
99     kBackref = 0x08,
100     // 0x10..0x14  Reference to previous object from space after skip.
101     kBackrefWithSkip = 0x10,
102 
103     // 0x05       Root array item.
104     kRootArray = 0x05,
105     // 0x06        Object in the partial snapshot cache.
106     kPartialSnapshotCache = 0x06,
107     // 0x07        External reference referenced by id.
108     kExternalReference = 0x07,
109 
110     // 0x0d        Object provided in the attached list.
111     kAttachedReference = 0x0d,
112     // 0x0e        Builtin code referenced by index.
113     kBuiltin = 0x0e,
114 
115     // 0x0f        Misc, see below (incl. 0x2f, 0x4f, 0x6f).
116     // 0x15..0x1f  Misc, see below (incl. 0x35..0x3f, 0x55..0x5f, 0x75..0x7f).
117   };
118 
119   static const int kWhereMask = 0x1f;
120   static const int kSpaceMask = 7;
121   STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
122 
123   // How to code the pointer to the object.
124   enum HowToCode {
125     // Straight pointer.
126     kPlain = 0,
127     // A pointer inlined in code. What this means depends on the architecture.
128     kFromCode = 0x20
129   };
130 
131   static const int kHowToCodeMask = 0x20;
132 
133   // Where to point within the object.
134   enum WhereToPoint {
135     // Points to start of object
136     kStartOfObject = 0,
137     // Points to instruction in code object or payload of cell.
138     kInnerPointer = 0x40
139   };
140 
141   static const int kWhereToPointMask = 0x40;
142 
143   // ---------- Misc ----------
144   // Skip.
145   static const int kSkip = 0x0f;
146   // Do nothing, used for padding.
147   static const int kNop = 0x2f;
148   // Move to next reserved chunk.
149   static const int kNextChunk = 0x4f;
150   // Deferring object content.
151   static const int kDeferred = 0x6f;
152   // Alignment prefixes 0x15..0x17
153   static const int kAlignmentPrefix = 0x15;
154   // A tag emitted at strategic points in the snapshot to delineate sections.
155   // If the deserializer does not find these at the expected moments then it
156   // is an indication that the snapshot and the VM do not fit together.
157   // Examine the build process for architecture, version or configuration
158   // mismatches.
159   static const int kSynchronize = 0x18;
160   // Repeats of variable length.
161   static const int kVariableRepeat = 0x19;
162   // Raw data of variable length.
163   static const int kVariableRawData = 0x1a;
164   // Internal reference encoded as offsets of pc and target from code entry.
165   static const int kInternalReference = 0x1b;
166   static const int kInternalReferenceEncoded = 0x1c;
167   // Used for the source code of the natives, which is in the executable, but
168   // is referred to from external strings in the snapshot.
169   static const int kNativesStringResource = 0x1d;
170   // Used for the source code for compiled stubs, which is in the executable,
171   // but is referred to from external strings in the snapshot.
172   static const int kExtraNativesStringResource = 0x1e;
173   // Used for embedder-provided serialization data for internal fields.
174   static const int kInternalFieldsData = 0x1f;
175 
176   // 8 hot (recently seen or back-referenced) objects with optional skip.
177   static const int kNumberOfHotObjects = 8;
178   STATIC_ASSERT(kNumberOfHotObjects == HotObjectsList::kSize);
179   // 0x38..0x3f
180   static const int kHotObject = 0x38;
181   // 0x58..0x5f
182   static const int kHotObjectWithSkip = 0x58;
183   static const int kHotObjectMask = 0x07;
184 
185   // 0x35..0x37, 0x55..0x57, 0x75..0x7f unused.
186 
187   // ---------- byte code range 0x80..0xff ----------
188   // First 32 root array items.
189   static const int kNumberOfRootArrayConstants = 0x20;
190   // 0x80..0x9f
191   static const int kRootArrayConstants = 0x80;
192   // 0xa0..0xbf
193   static const int kRootArrayConstantsWithSkip = 0xa0;
194   static const int kRootArrayConstantsMask = 0x1f;
195 
196   // 32 common raw data lengths.
197   static const int kNumberOfFixedRawData = 0x20;
198   // 0xc0..0xdf
199   static const int kFixedRawData = 0xc0;
200   static const int kOnePointerRawData = kFixedRawData;
201   static const int kFixedRawDataStart = kFixedRawData - 1;
202 
203   // 16 repeats lengths.
204   static const int kNumberOfFixedRepeat = 0x10;
205   // 0xe0..0xef
206   static const int kFixedRepeat = 0xe0;
207   static const int kFixedRepeatStart = kFixedRepeat - 1;
208 
209   // 0xf0..0xff unused.
210 
211   // ---------- special values ----------
212   static const int kAnyOldSpace = -1;
213 
214   // Sentinel after a new object to indicate that double alignment is needed.
215   static const int kDoubleAlignmentSentinel = 0;
216 
217   // ---------- member variable ----------
218   HotObjectsList hot_objects_;
219 };
220 
221 class SerializedData {
222  public:
223   class Reservation {
224    public:
Reservation(uint32_t size)225     explicit Reservation(uint32_t size)
226         : reservation_(ChunkSizeBits::encode(size)) {}
227 
chunk_size()228     uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); }
is_last()229     bool is_last() const { return IsLastChunkBits::decode(reservation_); }
230 
mark_as_last()231     void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); }
232 
233    private:
234     uint32_t reservation_;
235   };
236 
SerializedData(byte * data,int size)237   SerializedData(byte* data, int size)
238       : data_(data), size_(size), owns_data_(false) {}
SerializedData()239   SerializedData() : data_(NULL), size_(0), owns_data_(false) {}
240 
~SerializedData()241   ~SerializedData() {
242     if (owns_data_) DeleteArray<byte>(data_);
243   }
244 
GetMagicNumber()245   uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }
246 
247   class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
248   class IsLastChunkBits : public BitField<bool, 31, 1> {};
249 
ComputeMagicNumber(ExternalReferenceTable * table)250   static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) {
251     uint32_t external_refs = table->size();
252     return 0xC0DE0000 ^ external_refs;
253   }
254 
255  protected:
SetHeaderValue(int offset,uint32_t value)256   void SetHeaderValue(int offset, uint32_t value) {
257     uint32_t* address = reinterpret_cast<uint32_t*>(data_ + offset);
258     memcpy(reinterpret_cast<uint32_t*>(address), &value, sizeof(value));
259   }
260 
GetHeaderValue(int offset)261   uint32_t GetHeaderValue(int offset) const {
262     uint32_t value;
263     memcpy(&value, reinterpret_cast<int*>(data_ + offset), sizeof(value));
264     return value;
265   }
266 
267   void AllocateData(int size);
268 
ComputeMagicNumber(Isolate * isolate)269   static uint32_t ComputeMagicNumber(Isolate* isolate) {
270     return ComputeMagicNumber(ExternalReferenceTable::instance(isolate));
271   }
272 
SetMagicNumber(Isolate * isolate)273   void SetMagicNumber(Isolate* isolate) {
274     SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate));
275   }
276 
277   static const int kMagicNumberOffset = 0;
278 
279   byte* data_;
280   int size_;
281   bool owns_data_;
282 };
283 
284 }  // namespace internal
285 }  // namespace v8
286 
287 #endif  // V8_SNAPSHOT_SERIALIZER_COMMON_H_
288