blob: bdd2b51e7ee1c9df2fde752f4bca891ad8c7bb27 [file] [log] [blame]
Ben Murdochda12d292016-06-02 14:46:10 +01001// 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
12namespace v8 {
13namespace internal {
14
15class Isolate;
16
17class 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 static uint32_t Hash(Address key) {
27 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >>
28 kPointerSizeLog2);
29 }
30
Ben Murdoch61f157c2016-09-16 13:49:30 +010031 base::HashMap* map_;
Ben Murdochda12d292016-06-02 14:46:10 +010032
33 DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
34};
35
36class HotObjectsList {
37 public:
38 HotObjectsList() : index_(0) {
39 for (int i = 0; i < kSize; i++) circular_queue_[i] = NULL;
40 }
41
42 void Add(HeapObject* object) {
Ben Murdochc5610432016-08-08 18:44:38 +010043 DCHECK(!AllowHeapAllocation::IsAllowed());
Ben Murdochda12d292016-06-02 14:46:10 +010044 circular_queue_[index_] = object;
45 index_ = (index_ + 1) & kSizeMask;
46 }
47
48 HeapObject* Get(int index) {
Ben Murdochc5610432016-08-08 18:44:38 +010049 DCHECK(!AllowHeapAllocation::IsAllowed());
Ben Murdochda12d292016-06-02 14:46:10 +010050 DCHECK_NOT_NULL(circular_queue_[index]);
51 return circular_queue_[index];
52 }
53
54 static const int kNotFound = -1;
55
56 int Find(HeapObject* object) {
Ben Murdochc5610432016-08-08 18:44:38 +010057 DCHECK(!AllowHeapAllocation::IsAllowed());
Ben Murdochda12d292016-06-02 14:46:10 +010058 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.
78class 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.
Ben Murdoch61f157c2016-09-16 13:49:30 +010097 kNewObject = 0x00,
Ben Murdochda12d292016-06-02 14:46:10 +010098 // 0x08..0x0c Reference to previous object from space.
99 kBackref = 0x08,
Ben Murdochda12d292016-06-02 14:46:10 +0100100 // 0x10..0x14 Reference to previous object from space after skip.
101 kBackrefWithSkip = 0x10,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100102
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).
Ben Murdochda12d292016-06-02 14:46:10 +0100117 };
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.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100145 static const int kSkip = 0x0f;
Ben Murdochda12d292016-06-02 14:46:10 +0100146 // Do nothing, used for padding.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100147 static const int kNop = 0x2f;
Ben Murdochda12d292016-06-02 14:46:10 +0100148 // Move to next reserved chunk.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100149 static const int kNextChunk = 0x4f;
Ben Murdochda12d292016-06-02 14:46:10 +0100150 // Deferring object content.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100151 static const int kDeferred = 0x6f;
152 // Alignment prefixes 0x15..0x17
153 static const int kAlignmentPrefix = 0x15;
Ben Murdochda12d292016-06-02 14:46:10 +0100154 // 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.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100159 static const int kSynchronize = 0x18;
Ben Murdochda12d292016-06-02 14:46:10 +0100160 // Repeats of variable length.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100161 static const int kVariableRepeat = 0x19;
Ben Murdochda12d292016-06-02 14:46:10 +0100162 // Raw data of variable length.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100163 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;
Ben Murdochda12d292016-06-02 14:46:10 +0100173
Ben Murdoch61f157c2016-09-16 13:49:30 +0100174 // 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.
Ben Murdochda12d292016-06-02 14:46:10 +0100184
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
Ben Murdochda12d292016-06-02 14:46:10 +0100194 // 32 common raw data lengths.
195 static const int kNumberOfFixedRawData = 0x20;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100196 // 0xc0..0xdf
197 static const int kFixedRawData = 0xc0;
Ben Murdochda12d292016-06-02 14:46:10 +0100198 static const int kOnePointerRawData = kFixedRawData;
199 static const int kFixedRawDataStart = kFixedRawData - 1;
200
201 // 16 repeats lengths.
202 static const int kNumberOfFixedRepeat = 0x10;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100203 // 0xe0..0xef
204 static const int kFixedRepeat = 0xe0;
Ben Murdochda12d292016-06-02 14:46:10 +0100205 static const int kFixedRepeatStart = kFixedRepeat - 1;
206
Ben Murdoch61f157c2016-09-16 13:49:30 +0100207 // 0xf0..0xff unused.
208
Ben Murdochda12d292016-06-02 14:46:10 +0100209 // ---------- 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
Ben Murdochda12d292016-06-02 14:46:10 +0100215 // ---------- member variable ----------
216 HotObjectsList hot_objects_;
217};
218
219class SerializedData {
220 public:
221 class Reservation {
222 public:
223 explicit Reservation(uint32_t size)
224 : reservation_(ChunkSizeBits::encode(size)) {}
225
226 uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); }
227 bool is_last() const { return IsLastChunkBits::decode(reservation_); }
228
229 void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); }
230
231 private:
232 uint32_t reservation_;
233 };
234
235 SerializedData(byte* data, int size)
236 : data_(data), size_(size), owns_data_(false) {}
237 SerializedData() : data_(NULL), size_(0), owns_data_(false) {}
238
239 ~SerializedData() {
240 if (owns_data_) DeleteArray<byte>(data_);
241 }
242
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
248 static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) {
249 uint32_t external_refs = table->size();
250 return 0xC0DE0000 ^ external_refs;
251 }
252
253 protected:
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
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
267 static uint32_t ComputeMagicNumber(Isolate* isolate) {
268 return ComputeMagicNumber(ExternalReferenceTable::instance(isolate));
269 }
270
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_