blob: 71b274b330e20f535fa2a3bd93389337fdbf2251 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
5#ifndef V8_SERIALIZE_H_
6#define V8_SERIALIZE_H_
7
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/compiler.h"
9#include "src/hashmap.h"
10#include "src/heap-profiler.h"
11#include "src/isolate.h"
12#include "src/snapshot-source-sink.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000013
14namespace v8 {
15namespace internal {
16
17// A TypeCode is used to distinguish different kinds of external reference.
18// It is a single bit to make testing for types easy.
19enum TypeCode {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020 UNCLASSIFIED, // One-of-a-kind references.
21 C_BUILTIN,
Steve Blocka7e24c12009-10-30 11:49:00 +000022 BUILTIN,
23 RUNTIME_FUNCTION,
24 IC_UTILITY,
Steve Blocka7e24c12009-10-30 11:49:00 +000025 STATS_COUNTER,
26 TOP_ADDRESS,
Steve Blocka7e24c12009-10-30 11:49:00 +000027 ACCESSOR,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028 STUB_CACHE_TABLE,
Steve Blocka7e24c12009-10-30 11:49:00 +000029 RUNTIME_ENTRY,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030 LAZY_DEOPTIMIZATION
Steve Blocka7e24c12009-10-30 11:49:00 +000031};
32
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033const int kTypeCodeCount = LAZY_DEOPTIMIZATION + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +000034const int kFirstTypeCode = UNCLASSIFIED;
35
36const int kReferenceIdBits = 16;
37const int kReferenceIdMask = (1 << kReferenceIdBits) - 1;
38const int kReferenceTypeShift = kReferenceIdBits;
Steve Blocka7e24c12009-10-30 11:49:00 +000039
Ben Murdochb8a8cc12014-11-26 15:28:44 +000040const int kDeoptTableSerializeEntryCount = 64;
Steve Blocka7e24c12009-10-30 11:49:00 +000041
Ben Murdoch69a99ed2011-11-30 16:03:39 +000042// ExternalReferenceTable is a helper class that defines the relationship
43// between external references and their encodings. It is used to build
44// hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder.
45class ExternalReferenceTable {
46 public:
47 static ExternalReferenceTable* instance(Isolate* isolate);
48
49 ~ExternalReferenceTable() { }
50
51 int size() const { return refs_.length(); }
52
53 Address address(int i) { return refs_[i].address; }
54
55 uint32_t code(int i) { return refs_[i].code; }
56
57 const char* name(int i) { return refs_[i].name; }
58
59 int max_id(int code) { return max_id_[code]; }
60
61 private:
62 explicit ExternalReferenceTable(Isolate* isolate) : refs_(64) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000063 PopulateTable(isolate);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000064 }
65
66 struct ExternalReferenceEntry {
67 Address address;
68 uint32_t code;
69 const char* name;
70 };
71
72 void PopulateTable(Isolate* isolate);
73
74 // For a few types of references, we can get their address from their id.
75 void AddFromId(TypeCode type,
76 uint16_t id,
77 const char* name,
78 Isolate* isolate);
79
80 // For other types of references, the caller will figure out the address.
81 void Add(Address address, TypeCode type, uint16_t id, const char* name);
82
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083 void Add(Address address, const char* name) {
84 Add(address, UNCLASSIFIED, ++max_id_[UNCLASSIFIED], name);
85 }
86
Ben Murdoch69a99ed2011-11-30 16:03:39 +000087 List<ExternalReferenceEntry> refs_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000088 uint16_t max_id_[kTypeCodeCount];
Ben Murdoch69a99ed2011-11-30 16:03:39 +000089};
90
91
Steve Blocka7e24c12009-10-30 11:49:00 +000092class ExternalReferenceEncoder {
93 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000094 explicit ExternalReferenceEncoder(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000095
96 uint32_t Encode(Address key) const;
97
98 const char* NameOfAddress(Address key) const;
99
100 private:
101 HashMap encodings_;
102 static uint32_t Hash(Address key) {
103 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >> 2);
104 }
105
106 int IndexOf(Address key) const;
107
Steve Blocka7e24c12009-10-30 11:49:00 +0000108 void Put(Address key, int index);
Steve Block44f0eee2011-05-26 01:26:41 +0100109
110 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000111};
112
113
114class ExternalReferenceDecoder {
115 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000116 explicit ExternalReferenceDecoder(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000117 ~ExternalReferenceDecoder();
118
119 Address Decode(uint32_t key) const {
120 if (key == 0) return NULL;
121 return *Lookup(key);
122 }
123
124 private:
125 Address** encodings_;
126
127 Address* Lookup(uint32_t key) const {
128 int type = key >> kReferenceTypeShift;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000129 DCHECK(kFirstTypeCode <= type && type < kTypeCodeCount);
Steve Blocka7e24c12009-10-30 11:49:00 +0000130 int id = key & kReferenceIdMask;
131 return &encodings_[type][id];
132 }
133
134 void Put(uint32_t key, Address value) {
135 *Lookup(key) = value;
136 }
Steve Block44f0eee2011-05-26 01:26:41 +0100137
138 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000139};
140
141
Leon Clarked91b9f72010-01-27 17:25:45 +0000142// The Serializer/Deserializer class is a common superclass for Serializer and
143// Deserializer which is used to store common constants and methods used by
144// both.
145class SerializerDeserializer: public ObjectVisitor {
146 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000147 static void Iterate(Isolate* isolate, ObjectVisitor* visitor);
148
149 static int nop() { return kNop; }
Leon Clarked91b9f72010-01-27 17:25:45 +0000150
Steve Blockd0582a62009-12-15 09:54:21 +0000151 protected:
Leon Clarkef7060e22010-06-03 12:02:55 +0100152 // Where the pointed-to object can be found:
153 enum Where {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154 kNewObject = 0, // Object is next in snapshot.
155 // 1-6 One per space.
156 kRootArray = 0x9, // Object is found in root array.
157 kPartialSnapshotCache = 0xa, // Object is in the cache.
158 kExternalReference = 0xb, // Pointer to an external reference.
159 kSkip = 0xc, // Skip n bytes.
160 kBuiltin = 0xd, // Builtin code object.
161 kAttachedReference = 0xe, // Object is described in an attached list.
162 kNop = 0xf, // Does nothing, used to pad.
163 kBackref = 0x10, // Object is described relative to end.
164 // 0x11-0x16 One per space.
165 kBackrefWithSkip = 0x18, // Object is described relative to end.
166 // 0x19-0x1e One per space.
167 // 0x20-0x3f Used by misc. tags below.
Leon Clarkef7060e22010-06-03 12:02:55 +0100168 kPointedToMask = 0x3f
Steve Blockd0582a62009-12-15 09:54:21 +0000169 };
Leon Clarkef7060e22010-06-03 12:02:55 +0100170
171 // How to code the pointer to the object.
172 enum HowToCode {
173 kPlain = 0, // Straight pointer.
174 // What this means depends on the architecture:
175 kFromCode = 0x40, // A pointer inlined in code.
176 kHowToCodeMask = 0x40
177 };
178
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000179 // For kRootArrayConstants
180 enum WithSkip {
181 kNoSkipDistance = 0,
182 kHasSkipDistance = 0x40,
183 kWithSkipMask = 0x40
184 };
185
Leon Clarkef7060e22010-06-03 12:02:55 +0100186 // Where to point within the object.
187 enum WhereToPoint {
188 kStartOfObject = 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 kInnerPointer = 0x80, // First insn in code object or payload of cell.
Leon Clarkef7060e22010-06-03 12:02:55 +0100190 kWhereToPointMask = 0x80
191 };
192
193 // Misc.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194 // Raw data to be copied from the snapshot. This byte code does not advance
195 // the current pointer, which is used for code objects, where we write the
196 // entire code in one memcpy, then fix up stuff with kSkip and other byte
197 // codes that overwrite data.
198 static const int kRawData = 0x20;
199 // Some common raw lengths: 0x21-0x3f. These autoadvance the current pointer.
Leon Clarkef7060e22010-06-03 12:02:55 +0100200 // A tag emitted at strategic points in the snapshot to delineate sections.
201 // If the deserializer does not find these at the expected moments then it
202 // is an indication that the snapshot and the VM do not fit together.
203 // Examine the build process for architecture, version or configuration
204 // mismatches.
Ben Murdoch257744e2011-11-30 15:57:28 +0000205 static const int kSynchronize = 0x70;
Leon Clarkef7060e22010-06-03 12:02:55 +0100206 // Used for the source code of the natives, which is in the executable, but
207 // is referred to from external strings in the snapshot.
Ben Murdoch257744e2011-11-30 15:57:28 +0000208 static const int kNativesStringResource = 0x71;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209 static const int kRepeat = 0x72;
210 static const int kConstantRepeat = 0x73;
211 // 0x73-0x7f Repeat last word (subtract 0x72 to get the count).
212 static const int kMaxRepeats = 0x7f - 0x72;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100213 static int CodeForRepeats(int repeats) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214 DCHECK(repeats >= 1 && repeats <= kMaxRepeats);
215 return 0x72 + repeats;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100216 }
217 static int RepeatsForCode(int byte_code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218 DCHECK(byte_code >= kConstantRepeat && byte_code <= 0x7f);
219 return byte_code - 0x72;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100220 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221 static const int kRootArrayConstants = 0xa0;
222 // 0xa0-0xbf Things from the first 32 elements of the root array.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100223 static const int kRootArrayNumberOfConstantEncodings = 0x20;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100224 static int RootArrayConstantFromByteCode(int byte_code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225 return byte_code & 0x1f;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100226 }
Leon Clarkef7060e22010-06-03 12:02:55 +0100227
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228 static const int kNumberOfSpaces = LO_SPACE;
Ben Murdoch257744e2011-11-30 15:57:28 +0000229 static const int kAnyOldSpace = -1;
Steve Blockd0582a62009-12-15 09:54:21 +0000230
231 // A bitmask for getting the space out of an instruction.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232 static const int kSpaceMask = 7;
Steve Blockd0582a62009-12-15 09:54:21 +0000233};
234
235
Steve Blocka7e24c12009-10-30 11:49:00 +0000236// A Deserializer reads a snapshot and reconstructs the Object graph it defines.
Leon Clarked91b9f72010-01-27 17:25:45 +0000237class Deserializer: public SerializerDeserializer {
Steve Blocka7e24c12009-10-30 11:49:00 +0000238 public:
Steve Blockd0582a62009-12-15 09:54:21 +0000239 // Create a deserializer from a snapshot byte source.
240 explicit Deserializer(SnapshotByteSource* source);
Steve Blocka7e24c12009-10-30 11:49:00 +0000241
Leon Clarked91b9f72010-01-27 17:25:45 +0000242 virtual ~Deserializer();
Steve Blocka7e24c12009-10-30 11:49:00 +0000243
244 // Deserialize the snapshot into an empty heap.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245 void Deserialize(Isolate* isolate);
Leon Clarkee46be812010-01-19 14:06:41 +0000246
247 // Deserialize a single object and the objects reachable from it.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000248 void DeserializePartial(Isolate* isolate, Object** root);
249
250 void set_reservation(int space_number, int reservation) {
251 DCHECK(space_number >= 0);
252 DCHECK(space_number <= LAST_SPACE);
253 reservations_[space_number] = reservation;
254 }
255
256 void FlushICacheForNewCodeObjects();
257
258 // Serialized user code reference certain objects that are provided in a list
259 // By calling this method, we assume that we are deserializing user code.
260 void SetAttachedObjects(Vector<Handle<Object> >* attached_objects) {
261 attached_objects_ = attached_objects;
262 }
263
264 bool deserializing_user_code() { return attached_objects_ != NULL; }
Leon Clarkee46be812010-01-19 14:06:41 +0000265
Steve Blocka7e24c12009-10-30 11:49:00 +0000266 private:
267 virtual void VisitPointers(Object** start, Object** end);
Steve Blocka7e24c12009-10-30 11:49:00 +0000268
Steve Blockd0582a62009-12-15 09:54:21 +0000269 virtual void VisitRuntimeEntry(RelocInfo* rinfo) {
270 UNREACHABLE();
271 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000272
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273 // Allocation sites are present in the snapshot, and must be linked into
274 // a list at deserialization time.
275 void RelinkAllocationSite(AllocationSite* site);
276
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100277 // Fills in some heap data in an area from start to end (non-inclusive). The
278 // space id is used for the write barrier. The object_address is the address
279 // of the object we are writing into, or NULL if we are not writing into an
280 // object, i.e. if we are writing a series of tagged values that are not on
281 // the heap.
282 void ReadChunk(
283 Object** start, Object** end, int space, Address object_address);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000284 void ReadObject(int space_number, Object** write_back);
285
286 // Special handling for serialized code like hooking up internalized strings.
287 HeapObject* ProcessNewObjectFromSerializedCode(HeapObject* obj);
288 Object* ProcessBackRefInSerializedCode(Object* obj);
289
290 // This routine both allocates a new object, and also keeps
291 // track of where objects have been allocated so that we can
292 // fix back references when deserializing.
293 Address Allocate(int space_index, int size) {
294 Address address = high_water_[space_index];
295 high_water_[space_index] = address + size;
296 return address;
297 }
298
299 // This returns the address of an object that has been described in the
300 // snapshot as being offset bytes back in a particular space.
301 HeapObject* GetAddressFromEnd(int space) {
302 int offset = source_->GetInt();
303 offset <<= kObjectAlignmentBits;
304 return HeapObject::FromAddress(high_water_[space] - offset);
305 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000306
Steve Block44f0eee2011-05-26 01:26:41 +0100307 // Cached current isolate.
308 Isolate* isolate_;
309
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000310 // Objects from the attached object descriptions in the serialized user code.
311 Vector<Handle<Object> >* attached_objects_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000312
Steve Blockd0582a62009-12-15 09:54:21 +0000313 SnapshotByteSource* source_;
Steve Blockd0582a62009-12-15 09:54:21 +0000314 // This is the address of the next object that will be allocated in each
315 // space. It is used to calculate the addresses of back-references.
316 Address high_water_[LAST_SPACE + 1];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000317
318 int reservations_[LAST_SPACE + 1];
319 static const intptr_t kUninitializedReservation = -1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000320
Steve Block44f0eee2011-05-26 01:26:41 +0100321 ExternalReferenceDecoder* external_reference_decoder_;
322
Steve Blocka7e24c12009-10-30 11:49:00 +0000323 DISALLOW_COPY_AND_ASSIGN(Deserializer);
324};
325
Steve Blockd0582a62009-12-15 09:54:21 +0000326
Leon Clarked91b9f72010-01-27 17:25:45 +0000327// Mapping objects to their location after deserialization.
328// This is used during building, but not at runtime by V8.
329class SerializationAddressMapper {
330 public:
331 SerializationAddressMapper()
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332 : no_allocation_(),
333 serialization_map_(new HashMap(HashMap::PointersMatch)) { }
Leon Clarked91b9f72010-01-27 17:25:45 +0000334
335 ~SerializationAddressMapper() {
336 delete serialization_map_;
Leon Clarked91b9f72010-01-27 17:25:45 +0000337 }
338
339 bool IsMapped(HeapObject* obj) {
340 return serialization_map_->Lookup(Key(obj), Hash(obj), false) != NULL;
341 }
342
343 int MappedTo(HeapObject* obj) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000344 DCHECK(IsMapped(obj));
Leon Clarked91b9f72010-01-27 17:25:45 +0000345 return static_cast<int>(reinterpret_cast<intptr_t>(
346 serialization_map_->Lookup(Key(obj), Hash(obj), false)->value));
347 }
348
349 void AddMapping(HeapObject* obj, int to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000350 DCHECK(!IsMapped(obj));
Leon Clarked91b9f72010-01-27 17:25:45 +0000351 HashMap::Entry* entry =
352 serialization_map_->Lookup(Key(obj), Hash(obj), true);
353 entry->value = Value(to);
354 }
355
356 private:
Ben Murdoch257744e2011-11-30 15:57:28 +0000357 static uint32_t Hash(HeapObject* obj) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000358 return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
359 }
360
Ben Murdoch257744e2011-11-30 15:57:28 +0000361 static void* Key(HeapObject* obj) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000362 return reinterpret_cast<void*>(obj->address());
363 }
364
Ben Murdoch257744e2011-11-30 15:57:28 +0000365 static void* Value(int v) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000366 return reinterpret_cast<void*>(v);
367 }
368
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000369 DisallowHeapAllocation no_allocation_;
Leon Clarked91b9f72010-01-27 17:25:45 +0000370 HashMap* serialization_map_;
Leon Clarked91b9f72010-01-27 17:25:45 +0000371 DISALLOW_COPY_AND_ASSIGN(SerializationAddressMapper);
372};
373
374
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000375class CodeAddressMap;
376
Steve Block44f0eee2011-05-26 01:26:41 +0100377// There can be only one serializer per V8 process.
Ben Murdoch257744e2011-11-30 15:57:28 +0000378class Serializer : public SerializerDeserializer {
Steve Blockd0582a62009-12-15 09:54:21 +0000379 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000380 Serializer(Isolate* isolate, SnapshotByteSink* sink);
Andrei Popescu31002712010-02-23 13:46:05 +0000381 ~Serializer();
Steve Blockd0582a62009-12-15 09:54:21 +0000382 void VisitPointers(Object** start, Object** end);
Leon Clarkee46be812010-01-19 14:06:41 +0000383 // You can call this after serialization to find out how much space was used
384 // in each space.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000385 int CurrentAllocationAddress(int space) const {
386 DCHECK(space < kNumberOfSpaces);
Leon Clarkee46be812010-01-19 14:06:41 +0000387 return fullness_[space];
388 }
Steve Blockd0582a62009-12-15 09:54:21 +0000389
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000390 Isolate* isolate() const { return isolate_; }
Steve Blockd0582a62009-12-15 09:54:21 +0000391
Leon Clarked91b9f72010-01-27 17:25:45 +0000392 SerializationAddressMapper* address_mapper() { return &address_mapper_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000393 void PutRoot(int index,
394 HeapObject* object,
395 HowToCode how,
396 WhereToPoint where,
397 int skip);
Steve Blockd0582a62009-12-15 09:54:21 +0000398
Leon Clarked91b9f72010-01-27 17:25:45 +0000399 protected:
Ben Murdoch257744e2011-11-30 15:57:28 +0000400 static const int kInvalidRootIndex = -1;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100401
402 int RootIndex(HeapObject* heap_object, HowToCode from);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100403 intptr_t root_index_wave_front() { return root_index_wave_front_; }
404 void set_root_index_wave_front(intptr_t value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000405 DCHECK(value >= root_index_wave_front_);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100406 root_index_wave_front_ = value;
407 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000408
Steve Blockd0582a62009-12-15 09:54:21 +0000409 class ObjectSerializer : public ObjectVisitor {
410 public:
411 ObjectSerializer(Serializer* serializer,
412 Object* o,
413 SnapshotByteSink* sink,
Leon Clarkef7060e22010-06-03 12:02:55 +0100414 HowToCode how_to_code,
415 WhereToPoint where_to_point)
Steve Blockd0582a62009-12-15 09:54:21 +0000416 : serializer_(serializer),
417 object_(HeapObject::cast(o)),
418 sink_(sink),
Leon Clarkef7060e22010-06-03 12:02:55 +0100419 reference_representation_(how_to_code + where_to_point),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000420 bytes_processed_so_far_(0),
421 code_object_(o->IsCode()),
422 code_has_been_output_(false) { }
Steve Blockd0582a62009-12-15 09:54:21 +0000423 void Serialize();
424 void VisitPointers(Object** start, Object** end);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100425 void VisitEmbeddedPointer(RelocInfo* target);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000426 void VisitExternalReference(Address* p);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100427 void VisitExternalReference(RelocInfo* rinfo);
Steve Blockd0582a62009-12-15 09:54:21 +0000428 void VisitCodeTarget(RelocInfo* target);
Steve Block791712a2010-08-27 10:21:07 +0100429 void VisitCodeEntry(Address entry_address);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000430 void VisitCell(RelocInfo* rinfo);
Steve Blockd0582a62009-12-15 09:54:21 +0000431 void VisitRuntimeEntry(RelocInfo* reloc);
432 // Used for seralizing the external strings that hold the natives source.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433 void VisitExternalOneByteString(
434 v8::String::ExternalOneByteStringResource** resource);
Steve Blockd0582a62009-12-15 09:54:21 +0000435 // We can't serialize a heap with external two byte strings.
436 void VisitExternalTwoByteString(
437 v8::String::ExternalStringResource** resource) {
438 UNREACHABLE();
439 }
440
441 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000442 enum ReturnSkip { kCanReturnSkipInsteadOfSkipping, kIgnoringReturn };
443 // This function outputs or skips the raw data between the last pointer and
444 // up to the current position. It optionally can just return the number of
445 // bytes to skip instead of performing a skip instruction, in case the skip
446 // can be merged into the next instruction.
447 int OutputRawData(Address up_to, ReturnSkip return_skip = kIgnoringReturn);
Steve Blockd0582a62009-12-15 09:54:21 +0000448
449 Serializer* serializer_;
450 HeapObject* object_;
451 SnapshotByteSink* sink_;
Leon Clarkef7060e22010-06-03 12:02:55 +0100452 int reference_representation_;
Steve Blockd0582a62009-12-15 09:54:21 +0000453 int bytes_processed_so_far_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000454 bool code_object_;
455 bool code_has_been_output_;
Steve Blockd0582a62009-12-15 09:54:21 +0000456 };
457
Leon Clarked91b9f72010-01-27 17:25:45 +0000458 virtual void SerializeObject(Object* o,
Leon Clarkef7060e22010-06-03 12:02:55 +0100459 HowToCode how_to_code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000460 WhereToPoint where_to_point,
461 int skip) = 0;
462 void SerializeReferenceToPreviousObject(HeapObject* heap_object,
463 HowToCode how_to_code,
464 WhereToPoint where_to_point,
465 int skip);
Steve Blockd0582a62009-12-15 09:54:21 +0000466 void InitializeAllocators();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000467 // This will return the space for an object.
Ben Murdoch257744e2011-11-30 15:57:28 +0000468 static int SpaceOfObject(HeapObject* object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000469 int Allocate(int space, int size);
Steve Blockd0582a62009-12-15 09:54:21 +0000470 int EncodeExternalReference(Address addr) {
471 return external_reference_encoder_->Encode(addr);
472 }
473
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100474 int SpaceAreaSize(int space);
475
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000476 // Some roots should not be serialized, because their actual value depends on
477 // absolute addresses and they are reset after deserialization, anyway.
478 bool ShouldBeSkipped(Object** current);
479
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100480 Isolate* isolate_;
Steve Blockd0582a62009-12-15 09:54:21 +0000481 // Keep track of the fullness of each space in order to generate
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000482 // relative addresses for back references.
Steve Blockd0582a62009-12-15 09:54:21 +0000483 int fullness_[LAST_SPACE + 1];
484 SnapshotByteSink* sink_;
Steve Blockd0582a62009-12-15 09:54:21 +0000485 ExternalReferenceEncoder* external_reference_encoder_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000486
Leon Clarked91b9f72010-01-27 17:25:45 +0000487 SerializationAddressMapper address_mapper_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100488 intptr_t root_index_wave_front_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000489 void Pad();
Steve Blockd0582a62009-12-15 09:54:21 +0000490
491 friend class ObjectSerializer;
492 friend class Deserializer;
493
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494 // We may not need the code address map for logging for every instance
495 // of the serializer. Initialize it on demand.
496 void InitializeCodeAddressMap();
497
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100498 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000499 CodeAddressMap* code_address_map_;
Steve Blockd0582a62009-12-15 09:54:21 +0000500 DISALLOW_COPY_AND_ASSIGN(Serializer);
501};
502
Leon Clarked91b9f72010-01-27 17:25:45 +0000503
504class PartialSerializer : public Serializer {
505 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000506 PartialSerializer(Isolate* isolate,
507 Serializer* startup_snapshot_serializer,
Leon Clarked91b9f72010-01-27 17:25:45 +0000508 SnapshotByteSink* sink)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000509 : Serializer(isolate, sink),
Leon Clarked91b9f72010-01-27 17:25:45 +0000510 startup_serializer_(startup_snapshot_serializer) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100511 set_root_index_wave_front(Heap::kStrongRootListLength);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000512 InitializeCodeAddressMap();
Leon Clarked91b9f72010-01-27 17:25:45 +0000513 }
514
515 // Serialize the objects reachable from a single object pointer.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000516 void Serialize(Object** o);
Leon Clarked91b9f72010-01-27 17:25:45 +0000517 virtual void SerializeObject(Object* o,
Leon Clarkef7060e22010-06-03 12:02:55 +0100518 HowToCode how_to_code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000519 WhereToPoint where_to_point,
520 int skip);
Leon Clarked91b9f72010-01-27 17:25:45 +0000521
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000522 private:
523 int PartialSnapshotCacheIndex(HeapObject* o);
524 bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
Andrei Popescu31002712010-02-23 13:46:05 +0000525 // Scripts should be referred only through shared function infos. We can't
526 // allow them to be part of the partial snapshot because they contain a
527 // unique ID, and deserializing several partial snapshots containing script
528 // would cause dupes.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000529 DCHECK(!o->IsScript());
530 return o->IsName() || o->IsSharedFunctionInfo() ||
Iain Merrick75681382010-08-19 15:07:18 +0100531 o->IsHeapNumber() || o->IsCode() ||
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100532 o->IsScopeInfo() ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000533 o->map() ==
534 startup_serializer_->isolate()->heap()->fixed_cow_array_map();
Leon Clarked91b9f72010-01-27 17:25:45 +0000535 }
536
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000537
Leon Clarked91b9f72010-01-27 17:25:45 +0000538 Serializer* startup_serializer_;
539 DISALLOW_COPY_AND_ASSIGN(PartialSerializer);
540};
541
542
543class StartupSerializer : public Serializer {
544 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000545 StartupSerializer(Isolate* isolate, SnapshotByteSink* sink)
546 : Serializer(isolate, sink) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000547 // Clear the cache of objects used by the partial snapshot. After the
548 // strong roots have been serialized we can create a partial snapshot
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100549 // which will repopulate the cache with objects needed by that partial
Leon Clarked91b9f72010-01-27 17:25:45 +0000550 // snapshot.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000551 isolate->set_serialize_partial_snapshot_cache_length(0);
552 InitializeCodeAddressMap();
Leon Clarked91b9f72010-01-27 17:25:45 +0000553 }
554 // Serialize the current state of the heap. The order is:
555 // 1) Strong references.
556 // 2) Partial snapshot cache.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000557 // 3) Weak references (e.g. the string table).
Leon Clarked91b9f72010-01-27 17:25:45 +0000558 virtual void SerializeStrongReferences();
559 virtual void SerializeObject(Object* o,
Leon Clarkef7060e22010-06-03 12:02:55 +0100560 HowToCode how_to_code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000561 WhereToPoint where_to_point,
562 int skip);
Leon Clarked91b9f72010-01-27 17:25:45 +0000563 void SerializeWeakReferences();
564 void Serialize() {
565 SerializeStrongReferences();
566 SerializeWeakReferences();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000567 Pad();
Leon Clarked91b9f72010-01-27 17:25:45 +0000568 }
569
570 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000571 DISALLOW_COPY_AND_ASSIGN(StartupSerializer);
Leon Clarked91b9f72010-01-27 17:25:45 +0000572};
573
Andrei Popescu31002712010-02-23 13:46:05 +0000574
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000575class CodeSerializer : public Serializer {
576 public:
577 CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source)
578 : Serializer(isolate, sink), source_(source) {
579 set_root_index_wave_front(Heap::kStrongRootListLength);
580 InitializeCodeAddressMap();
581 }
582
583 static ScriptData* Serialize(Isolate* isolate,
584 Handle<SharedFunctionInfo> info,
585 Handle<String> source);
586
587 virtual void SerializeObject(Object* o, HowToCode how_to_code,
588 WhereToPoint where_to_point, int skip);
589
590 static Handle<SharedFunctionInfo> Deserialize(Isolate* isolate,
591 ScriptData* data,
592 Handle<String> source);
593
594 static const int kSourceObjectIndex = 0;
595 static const int kCodeStubsBaseIndex = 1;
596
597 String* source() {
598 DCHECK(!AllowHeapAllocation::IsAllowed());
599 return source_;
600 }
601
602 List<uint32_t>* stub_keys() { return &stub_keys_; }
603
604 private:
605 void SerializeBuiltin(Code* builtin, HowToCode how_to_code,
606 WhereToPoint where_to_point, int skip);
607 void SerializeCodeStub(Code* code, HowToCode how_to_code,
608 WhereToPoint where_to_point, int skip);
609 void SerializeSourceObject(HowToCode how_to_code, WhereToPoint where_to_point,
610 int skip);
611 void SerializeHeapObject(HeapObject* heap_object, HowToCode how_to_code,
612 WhereToPoint where_to_point, int skip);
613 int AddCodeStubKey(uint32_t stub_key);
614
615 DisallowHeapAllocation no_gc_;
616 String* source_;
617 List<uint32_t> stub_keys_;
618 DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
619};
620
621
622// Wrapper around ScriptData to provide code-serializer-specific functionality.
623class SerializedCodeData {
624 public:
625 // Used by when consuming.
626 explicit SerializedCodeData(ScriptData* data, String* source)
627 : script_data_(data), owns_script_data_(false) {
628 DisallowHeapAllocation no_gc;
629 CHECK(IsSane(source));
630 }
631
632 // Used when producing.
633 SerializedCodeData(List<byte>* payload, CodeSerializer* cs);
634
635 ~SerializedCodeData() {
636 if (owns_script_data_) delete script_data_;
637 }
638
639 // Return ScriptData object and relinquish ownership over it to the caller.
640 ScriptData* GetScriptData() {
641 ScriptData* result = script_data_;
642 script_data_ = NULL;
643 DCHECK(owns_script_data_);
644 owns_script_data_ = false;
645 return result;
646 }
647
648 Vector<const uint32_t> CodeStubKeys() const {
649 return Vector<const uint32_t>(
650 reinterpret_cast<const uint32_t*>(script_data_->data() + kHeaderSize),
651 GetHeaderValue(kNumCodeStubKeysOffset));
652 }
653
654 const byte* Payload() const {
655 int code_stubs_size = GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size;
656 return script_data_->data() + kHeaderSize + code_stubs_size;
657 }
658
659 int PayloadLength() const {
660 int payload_length = GetHeaderValue(kPayloadLengthOffset);
661 DCHECK_EQ(script_data_->data() + script_data_->length(),
662 Payload() + payload_length);
663 return payload_length;
664 }
665
666 int GetReservation(int space) const {
667 return GetHeaderValue(kReservationsOffset + space);
668 }
669
670 private:
671 void SetHeaderValue(int offset, int value) {
672 reinterpret_cast<int*>(const_cast<byte*>(script_data_->data()))[offset] =
673 value;
674 }
675
676 int GetHeaderValue(int offset) const {
677 return reinterpret_cast<const int*>(script_data_->data())[offset];
678 }
679
680 bool IsSane(String* source);
681
682 int CheckSum(String* source);
683
684 // The data header consists of int-sized entries:
685 // [0] version hash
686 // [1] number of code stub keys
687 // [2] payload length
688 // [3..9] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
689 static const int kCheckSumOffset = 0;
690 static const int kNumCodeStubKeysOffset = 1;
691 static const int kPayloadLengthOffset = 2;
692 static const int kReservationsOffset = 3;
693
694 static const int kNumSpaces = PROPERTY_CELL_SPACE - NEW_SPACE + 1;
695 static const int kHeaderEntries = kReservationsOffset + kNumSpaces;
696 static const int kHeaderSize = kHeaderEntries * kIntSize;
697
698 // Following the header, we store, in sequential order
699 // - code stub keys
700 // - serialization payload
701
702 ScriptData* script_data_;
703 bool owns_script_data_;
704};
Steve Blocka7e24c12009-10-30 11:49:00 +0000705} } // namespace v8::internal
706
707#endif // V8_SERIALIZE_H_