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