Line data Source code
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 : #include "src/visitors.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 :
16 : class Isolate;
17 :
18 : class ExternalReferenceEncoder {
19 : public:
20 : explicit ExternalReferenceEncoder(Isolate* isolate);
21 :
22 : uint32_t Encode(Address key) const;
23 :
24 : const char* NameOfAddress(Isolate* isolate, Address address) const;
25 :
26 : private:
27 : AddressToIndexHashMap* map_;
28 : #ifdef DEBUG
29 : ExternalReferenceTable* table_;
30 : #endif // DEBUG
31 :
32 : DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
33 : };
34 :
35 : class HotObjectsList {
36 : public:
37 168777 : HotObjectsList() : index_(0) {
38 1350216 : for (int i = 0; i < kSize; i++) circular_queue_[i] = NULL;
39 : }
40 :
41 : void Add(HeapObject* object) {
42 : DCHECK(!AllowHeapAllocation::IsAllowed());
43 917563114 : circular_queue_[index_] = object;
44 917563114 : index_ = (index_ + 1) & kSizeMask;
45 : }
46 :
47 : HeapObject* Get(int index) {
48 : DCHECK(!AllowHeapAllocation::IsAllowed());
49 : DCHECK_NOT_NULL(circular_queue_[index]);
50 552990916 : return circular_queue_[index];
51 : }
52 :
53 : static const int kNotFound = -1;
54 :
55 : int Find(HeapObject* object) {
56 : DCHECK(!AllowHeapAllocation::IsAllowed());
57 60256799 : for (int i = 0; i < kSize; i++) {
58 61672687 : if (circular_queue_[i] == object) return i;
59 : }
60 : return kNotFound;
61 : }
62 :
63 : static const int kSize = 8;
64 :
65 : private:
66 : STATIC_ASSERT(IS_POWER_OF_TWO(kSize));
67 : static const int kSizeMask = kSize - 1;
68 : HeapObject* circular_queue_[kSize];
69 : int index_;
70 :
71 : DISALLOW_COPY_AND_ASSIGN(HotObjectsList);
72 : };
73 :
74 : // The Serializer/Deserializer class is a common superclass for Serializer and
75 : // Deserializer which is used to store common constants and methods used by
76 : // both.
77 337626 : class SerializerDeserializer : public RootVisitor {
78 : public:
79 : static void Iterate(Isolate* isolate, RootVisitor* visitor);
80 :
81 : // No reservation for large object space necessary.
82 : // We also handle map space differenly.
83 : STATIC_ASSERT(MAP_SPACE == CODE_SPACE + 1);
84 : static const int kNumberOfPreallocatedSpaces = CODE_SPACE + 1;
85 : static const int kNumberOfSpaces = LAST_SPACE + 1;
86 :
87 : protected:
88 : static bool CanBeDeferred(HeapObject* o);
89 :
90 : void RestoreExternalReferenceRedirectors(List<AccessorInfo*>* accessor_infos);
91 :
92 : // ---------- byte code range 0x00..0x7f ----------
93 : // Byte codes in this range represent Where, HowToCode and WhereToPoint.
94 : // Where the pointed-to object can be found:
95 : // The static assert below will trigger when the number of preallocated spaces
96 : // changed. If that happens, update the bytecode ranges in the comments below.
97 : STATIC_ASSERT(5 == kNumberOfSpaces);
98 : enum Where {
99 : // 0x00..0x04 Allocate new object, in specified space.
100 : kNewObject = 0x00,
101 : // 0x08..0x0c Reference to previous object from space.
102 : kBackref = 0x08,
103 : // 0x10..0x14 Reference to previous object from space after skip.
104 : kBackrefWithSkip = 0x10,
105 :
106 : // 0x05 Root array item.
107 : kRootArray = 0x05,
108 : // 0x06 Object in the partial snapshot cache.
109 : kPartialSnapshotCache = 0x06,
110 : // 0x07 External reference referenced by id.
111 : kExternalReference = 0x07,
112 :
113 : // 0x0d Object provided in the attached list.
114 : kAttachedReference = 0x0d,
115 : // 0x0e Builtin code referenced by index.
116 : kBuiltin = 0x0e,
117 :
118 : // 0x0f Misc, see below (incl. 0x2f, 0x4f, 0x6f).
119 : // 0x15..0x1f Misc, see below (incl. 0x35..0x3f, 0x55..0x5f, 0x75..0x7f).
120 : };
121 :
122 : static const int kWhereMask = 0x1f;
123 : static const int kSpaceMask = 7;
124 : STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
125 :
126 : // How to code the pointer to the object.
127 : enum HowToCode {
128 : // Straight pointer.
129 : kPlain = 0,
130 : // A pointer inlined in code. What this means depends on the architecture.
131 : kFromCode = 0x20
132 : };
133 :
134 : static const int kHowToCodeMask = 0x20;
135 :
136 : // Where to point within the object.
137 : enum WhereToPoint {
138 : // Points to start of object
139 : kStartOfObject = 0,
140 : // Points to instruction in code object or payload of cell.
141 : kInnerPointer = 0x40
142 : };
143 :
144 : static const int kWhereToPointMask = 0x40;
145 :
146 : // ---------- Misc ----------
147 : // Skip.
148 : static const int kSkip = 0x0f;
149 : // Do nothing, used for padding.
150 : static const int kNop = 0x2f;
151 : // Move to next reserved chunk.
152 : static const int kNextChunk = 0x4f;
153 : // Deferring object content.
154 : static const int kDeferred = 0x6f;
155 : // Alignment prefixes 0x15..0x17
156 : static const int kAlignmentPrefix = 0x15;
157 : // A tag emitted at strategic points in the snapshot to delineate sections.
158 : // If the deserializer does not find these at the expected moments then it
159 : // is an indication that the snapshot and the VM do not fit together.
160 : // Examine the build process for architecture, version or configuration
161 : // mismatches.
162 : static const int kSynchronize = 0x18;
163 : // Repeats of variable length.
164 : static const int kVariableRepeat = 0x19;
165 : // Raw data of variable length.
166 : static const int kVariableRawData = 0x1a;
167 : // Internal reference encoded as offsets of pc and target from code entry.
168 : static const int kInternalReference = 0x1b;
169 : static const int kInternalReferenceEncoded = 0x1c;
170 : // Used to encode deoptimizer entry code.
171 : static const int kDeoptimizerEntryPlain = 0x1d;
172 : static const int kDeoptimizerEntryFromCode = 0x1e;
173 : // Used for embedder-provided serialization data for embedder fields.
174 : static const int kEmbedderFieldsData = 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:
225 : explicit Reservation(uint32_t size)
226 4615 : : reservation_(ChunkSizeBits::encode(size)) {}
227 :
228 961638 : uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); }
229 961566 : bool is_last() const { return IsLastChunkBits::decode(reservation_); }
230 :
231 4235 : void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); }
232 :
233 : private:
234 : uint32_t reservation_;
235 : };
236 :
237 : SerializedData(byte* data, int size)
238 168076 : : data_(data), size_(size), owns_data_(false) {}
239 847 : SerializedData() : data_(NULL), size_(0), owns_data_(false) {}
240 : SerializedData(SerializedData&& other)
241 385 : : data_(other.data_), size_(other.size_), owns_data_(other.owns_data_) {
242 : // Ensure |other| will not attempt to destroy our data in destructor.
243 385 : other.owns_data_ = false;
244 : }
245 :
246 : ~SerializedData() {
247 169236 : if (owns_data_) DeleteArray<byte>(data_);
248 : }
249 :
250 418 : uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }
251 418 : uint32_t GetExtraReferences() const {
252 : return GetHeaderValue(kExtraExternalReferencesOffset);
253 : }
254 :
255 : class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
256 : class IsLastChunkBits : public BitField<bool, 31, 1> {};
257 :
258 : static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) {
259 : uint32_t external_refs = table->size() - table->num_api_references();
260 169267 : return 0xC0DE0000 ^ external_refs;
261 : }
262 : static uint32_t GetExtraReferences(ExternalReferenceTable* table) {
263 : return table->num_api_references();
264 : }
265 :
266 : static const int kMagicNumberOffset = 0;
267 : static const int kExtraExternalReferencesOffset =
268 : kMagicNumberOffset + kInt32Size;
269 : static const int kVersionHashOffset =
270 : kExtraExternalReferencesOffset + kInt32Size;
271 :
272 : protected:
273 : void SetHeaderValue(int offset, uint32_t value) {
274 6730 : uint32_t* address = reinterpret_cast<uint32_t*>(data_ + offset);
275 : memcpy(reinterpret_cast<uint32_t*>(address), &value, sizeof(value));
276 : }
277 :
278 : uint32_t GetHeaderValue(int offset) const {
279 : uint32_t value;
280 : memcpy(&value, reinterpret_cast<int*>(data_ + offset), sizeof(value));
281 : return value;
282 : }
283 :
284 : void AllocateData(int size);
285 :
286 : static uint32_t ComputeMagicNumber(Isolate* isolate) {
287 1265 : return ComputeMagicNumber(ExternalReferenceTable::instance(isolate));
288 : }
289 : static uint32_t GetExtraReferences(Isolate* isolate) {
290 1265 : return GetExtraReferences(ExternalReferenceTable::instance(isolate));
291 : }
292 :
293 2541 : void SetMagicNumber(Isolate* isolate) {
294 : SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate));
295 : SetHeaderValue(kExtraExternalReferencesOffset, GetExtraReferences(isolate));
296 847 : }
297 :
298 : byte* data_;
299 : int size_;
300 : bool owns_data_;
301 :
302 : private:
303 : DISALLOW_COPY_AND_ASSIGN(SerializedData);
304 : };
305 :
306 : } // namespace internal
307 : } // namespace v8
308 :
309 : #endif // V8_SNAPSHOT_SERIALIZER_COMMON_H_
|