• 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:
Hash(Address key)26   static uint32_t Hash(Address key) {
27     return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >>
28                                  kPointerSizeLog2);
29   }
30 
31   base::HashMap* map_;
32 
33   DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
34 };
35 
36 class HotObjectsList {
37  public:
HotObjectsList()38   HotObjectsList() : index_(0) {
39     for (int i = 0; i < kSize; i++) circular_queue_[i] = NULL;
40   }
41 
Add(HeapObject * object)42   void Add(HeapObject* object) {
43     DCHECK(!AllowHeapAllocation::IsAllowed());
44     circular_queue_[index_] = object;
45     index_ = (index_ + 1) & kSizeMask;
46   }
47 
Get(int index)48   HeapObject* Get(int index) {
49     DCHECK(!AllowHeapAllocation::IsAllowed());
50     DCHECK_NOT_NULL(circular_queue_[index]);
51     return circular_queue_[index];
52   }
53 
54   static const int kNotFound = -1;
55 
Find(HeapObject * object)56   int Find(HeapObject* object) {
57     DCHECK(!AllowHeapAllocation::IsAllowed());
58     for (int i = 0; i < kSize; i++) {
59       if (circular_queue_[i] == object) return i;
60     }
61     return kNotFound;
62   }
63 
64   static const int kSize = 8;
65 
66  private:
67   STATIC_ASSERT(IS_POWER_OF_TWO(kSize));
68   static const int kSizeMask = kSize - 1;
69   HeapObject* circular_queue_[kSize];
70   int index_;
71 
72   DISALLOW_COPY_AND_ASSIGN(HotObjectsList);
73 };
74 
75 // The Serializer/Deserializer class is a common superclass for Serializer and
76 // Deserializer which is used to store common constants and methods used by
77 // both.
78 class SerializerDeserializer : public ObjectVisitor {
79  public:
80   static void Iterate(Isolate* isolate, ObjectVisitor* visitor);
81 
82   // No reservation for large object space necessary.
83   static const int kNumberOfPreallocatedSpaces = LAST_PAGED_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 
174   // 8 hot (recently seen or back-referenced) objects with optional skip.
175   static const int kNumberOfHotObjects = 8;
176   STATIC_ASSERT(kNumberOfHotObjects == HotObjectsList::kSize);
177   // 0x38..0x3f
178   static const int kHotObject = 0x38;
179   // 0x58..0x5f
180   static const int kHotObjectWithSkip = 0x58;
181   static const int kHotObjectMask = 0x07;
182 
183   // 0x1f, 0x35..0x37, 0x55..0x57, 0x75..0x7f unused.
184 
185   // ---------- byte code range 0x80..0xff ----------
186   // First 32 root array items.
187   static const int kNumberOfRootArrayConstants = 0x20;
188   // 0x80..0x9f
189   static const int kRootArrayConstants = 0x80;
190   // 0xa0..0xbf
191   static const int kRootArrayConstantsWithSkip = 0xa0;
192   static const int kRootArrayConstantsMask = 0x1f;
193 
194   // 32 common raw data lengths.
195   static const int kNumberOfFixedRawData = 0x20;
196   // 0xc0..0xdf
197   static const int kFixedRawData = 0xc0;
198   static const int kOnePointerRawData = kFixedRawData;
199   static const int kFixedRawDataStart = kFixedRawData - 1;
200 
201   // 16 repeats lengths.
202   static const int kNumberOfFixedRepeat = 0x10;
203   // 0xe0..0xef
204   static const int kFixedRepeat = 0xe0;
205   static const int kFixedRepeatStart = kFixedRepeat - 1;
206 
207   // 0xf0..0xff unused.
208 
209   // ---------- special values ----------
210   static const int kAnyOldSpace = -1;
211 
212   // Sentinel after a new object to indicate that double alignment is needed.
213   static const int kDoubleAlignmentSentinel = 0;
214 
215   // ---------- member variable ----------
216   HotObjectsList hot_objects_;
217 };
218 
219 class SerializedData {
220  public:
221   class Reservation {
222    public:
Reservation(uint32_t size)223     explicit Reservation(uint32_t size)
224         : reservation_(ChunkSizeBits::encode(size)) {}
225 
chunk_size()226     uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); }
is_last()227     bool is_last() const { return IsLastChunkBits::decode(reservation_); }
228 
mark_as_last()229     void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); }
230 
231    private:
232     uint32_t reservation_;
233   };
234 
SerializedData(byte * data,int size)235   SerializedData(byte* data, int size)
236       : data_(data), size_(size), owns_data_(false) {}
SerializedData()237   SerializedData() : data_(NULL), size_(0), owns_data_(false) {}
238 
~SerializedData()239   ~SerializedData() {
240     if (owns_data_) DeleteArray<byte>(data_);
241   }
242 
GetMagicNumber()243   uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }
244 
245   class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
246   class IsLastChunkBits : public BitField<bool, 31, 1> {};
247 
ComputeMagicNumber(ExternalReferenceTable * table)248   static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) {
249     uint32_t external_refs = table->size();
250     return 0xC0DE0000 ^ external_refs;
251   }
252 
253  protected:
SetHeaderValue(int offset,uint32_t value)254   void SetHeaderValue(int offset, uint32_t value) {
255     uint32_t* address = reinterpret_cast<uint32_t*>(data_ + offset);
256     memcpy(reinterpret_cast<uint32_t*>(address), &value, sizeof(value));
257   }
258 
GetHeaderValue(int offset)259   uint32_t GetHeaderValue(int offset) const {
260     uint32_t value;
261     memcpy(&value, reinterpret_cast<int*>(data_ + offset), sizeof(value));
262     return value;
263   }
264 
265   void AllocateData(int size);
266 
ComputeMagicNumber(Isolate * isolate)267   static uint32_t ComputeMagicNumber(Isolate* isolate) {
268     return ComputeMagicNumber(ExternalReferenceTable::instance(isolate));
269   }
270 
SetMagicNumber(Isolate * isolate)271   void SetMagicNumber(Isolate* isolate) {
272     SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate));
273   }
274 
275   static const int kMagicNumberOffset = 0;
276 
277   byte* data_;
278   int size_;
279   bool owns_data_;
280 };
281 
282 }  // namespace internal
283 }  // namespace v8
284 
285 #endif  // V8_SNAPSHOT_SERIALIZER_COMMON_H_
286