• 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/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   void RestoreExternalReferenceRedirectors(List<AccessorInfo*>* accessor_infos);
90 
91   // ---------- byte code range 0x00..0x7f ----------
92   // Byte codes in this range represent Where, HowToCode and WhereToPoint.
93   // Where the pointed-to object can be found:
94   // The static assert below will trigger when the number of preallocated spaces
95   // changed. If that happens, update the bytecode ranges in the comments below.
96   STATIC_ASSERT(5 == kNumberOfSpaces);
97   enum Where {
98     // 0x00..0x04  Allocate new object, in specified space.
99     kNewObject = 0x00,
100     // 0x08..0x0c  Reference to previous object from space.
101     kBackref = 0x08,
102     // 0x10..0x14  Reference to previous object from space after skip.
103     kBackrefWithSkip = 0x10,
104 
105     // 0x05       Root array item.
106     kRootArray = 0x05,
107     // 0x06        Object in the partial snapshot cache.
108     kPartialSnapshotCache = 0x06,
109     // 0x07        External reference referenced by id.
110     kExternalReference = 0x07,
111 
112     // 0x0d        Object provided in the attached list.
113     kAttachedReference = 0x0d,
114     // 0x0e        Builtin code referenced by index.
115     kBuiltin = 0x0e,
116 
117     // 0x0f        Misc, see below (incl. 0x2f, 0x4f, 0x6f).
118     // 0x15..0x1f  Misc, see below (incl. 0x35..0x3f, 0x55..0x5f, 0x75..0x7f).
119   };
120 
121   static const int kWhereMask = 0x1f;
122   static const int kSpaceMask = 7;
123   STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
124 
125   // How to code the pointer to the object.
126   enum HowToCode {
127     // Straight pointer.
128     kPlain = 0,
129     // A pointer inlined in code. What this means depends on the architecture.
130     kFromCode = 0x20
131   };
132 
133   static const int kHowToCodeMask = 0x20;
134 
135   // Where to point within the object.
136   enum WhereToPoint {
137     // Points to start of object
138     kStartOfObject = 0,
139     // Points to instruction in code object or payload of cell.
140     kInnerPointer = 0x40
141   };
142 
143   static const int kWhereToPointMask = 0x40;
144 
145   // ---------- Misc ----------
146   // Skip.
147   static const int kSkip = 0x0f;
148   // Do nothing, used for padding.
149   static const int kNop = 0x2f;
150   // Move to next reserved chunk.
151   static const int kNextChunk = 0x4f;
152   // Deferring object content.
153   static const int kDeferred = 0x6f;
154   // Alignment prefixes 0x15..0x17
155   static const int kAlignmentPrefix = 0x15;
156   // A tag emitted at strategic points in the snapshot to delineate sections.
157   // If the deserializer does not find these at the expected moments then it
158   // is an indication that the snapshot and the VM do not fit together.
159   // Examine the build process for architecture, version or configuration
160   // mismatches.
161   static const int kSynchronize = 0x18;
162   // Repeats of variable length.
163   static const int kVariableRepeat = 0x19;
164   // Raw data of variable length.
165   static const int kVariableRawData = 0x1a;
166   // Internal reference encoded as offsets of pc and target from code entry.
167   static const int kInternalReference = 0x1b;
168   static const int kInternalReferenceEncoded = 0x1c;
169   // Used for the source code of the natives, which is in the executable, but
170   // is referred to from external strings in the snapshot.
171   static const int kNativesStringResource = 0x1d;
172   // Used for the source code for compiled stubs, which is in the executable,
173   // but is referred to from external strings in the snapshot.
174   static const int kExtraNativesStringResource = 0x1e;
175   // Used for embedder-provided serialization data for internal fields.
176   static const int kInternalFieldsData = 0x1f;
177 
178   // 8 hot (recently seen or back-referenced) objects with optional skip.
179   static const int kNumberOfHotObjects = 8;
180   STATIC_ASSERT(kNumberOfHotObjects == HotObjectsList::kSize);
181   // 0x38..0x3f
182   static const int kHotObject = 0x38;
183   // 0x58..0x5f
184   static const int kHotObjectWithSkip = 0x58;
185   static const int kHotObjectMask = 0x07;
186 
187   // 0x35..0x37, 0x55..0x57, 0x75..0x7f unused.
188 
189   // ---------- byte code range 0x80..0xff ----------
190   // First 32 root array items.
191   static const int kNumberOfRootArrayConstants = 0x20;
192   // 0x80..0x9f
193   static const int kRootArrayConstants = 0x80;
194   // 0xa0..0xbf
195   static const int kRootArrayConstantsWithSkip = 0xa0;
196   static const int kRootArrayConstantsMask = 0x1f;
197 
198   // 32 common raw data lengths.
199   static const int kNumberOfFixedRawData = 0x20;
200   // 0xc0..0xdf
201   static const int kFixedRawData = 0xc0;
202   static const int kOnePointerRawData = kFixedRawData;
203   static const int kFixedRawDataStart = kFixedRawData - 1;
204 
205   // 16 repeats lengths.
206   static const int kNumberOfFixedRepeat = 0x10;
207   // 0xe0..0xef
208   static const int kFixedRepeat = 0xe0;
209   static const int kFixedRepeatStart = kFixedRepeat - 1;
210 
211   // 0xf0..0xff unused.
212 
213   // ---------- special values ----------
214   static const int kAnyOldSpace = -1;
215 
216   // Sentinel after a new object to indicate that double alignment is needed.
217   static const int kDoubleAlignmentSentinel = 0;
218 
219   // ---------- member variable ----------
220   HotObjectsList hot_objects_;
221 };
222 
223 class SerializedData {
224  public:
225   class Reservation {
226    public:
Reservation(uint32_t size)227     explicit Reservation(uint32_t size)
228         : reservation_(ChunkSizeBits::encode(size)) {}
229 
chunk_size()230     uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); }
is_last()231     bool is_last() const { return IsLastChunkBits::decode(reservation_); }
232 
mark_as_last()233     void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); }
234 
235    private:
236     uint32_t reservation_;
237   };
238 
SerializedData(byte * data,int size)239   SerializedData(byte* data, int size)
240       : data_(data), size_(size), owns_data_(false) {}
SerializedData()241   SerializedData() : data_(NULL), size_(0), owns_data_(false) {}
242 
~SerializedData()243   ~SerializedData() {
244     if (owns_data_) DeleteArray<byte>(data_);
245   }
246 
GetMagicNumber()247   uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }
248 
249   class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
250   class IsLastChunkBits : public BitField<bool, 31, 1> {};
251 
ComputeMagicNumber(ExternalReferenceTable * table)252   static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) {
253     uint32_t external_refs = table->size();
254     return 0xC0DE0000 ^ external_refs;
255   }
256 
257  protected:
SetHeaderValue(int offset,uint32_t value)258   void SetHeaderValue(int offset, uint32_t value) {
259     uint32_t* address = reinterpret_cast<uint32_t*>(data_ + offset);
260     memcpy(reinterpret_cast<uint32_t*>(address), &value, sizeof(value));
261   }
262 
GetHeaderValue(int offset)263   uint32_t GetHeaderValue(int offset) const {
264     uint32_t value;
265     memcpy(&value, reinterpret_cast<int*>(data_ + offset), sizeof(value));
266     return value;
267   }
268 
269   void AllocateData(int size);
270 
ComputeMagicNumber(Isolate * isolate)271   static uint32_t ComputeMagicNumber(Isolate* isolate) {
272     return ComputeMagicNumber(ExternalReferenceTable::instance(isolate));
273   }
274 
SetMagicNumber(Isolate * isolate)275   void SetMagicNumber(Isolate* isolate) {
276     SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate));
277   }
278 
279   static const int kMagicNumberOffset = 0;
280 
281   byte* data_;
282   int size_;
283   bool owns_data_;
284 };
285 
286 }  // namespace internal
287 }  // namespace v8
288 
289 #endif  // V8_SNAPSHOT_SERIALIZER_COMMON_H_
290