blob: 66d6fb5111ea45c2f7ecf7b1d5fed7003fd9169c [file] [log] [blame]
Ben Murdoch85b71792012-04-11 18:30:58 +01001// Copyright 2006-2009 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_SERIALIZE_H_
29#define V8_SERIALIZE_H_
30
31#include "hashmap.h"
32
33namespace v8 {
34namespace internal {
35
36// A TypeCode is used to distinguish different kinds of external reference.
37// It is a single bit to make testing for types easy.
38enum TypeCode {
39 UNCLASSIFIED, // One-of-a-kind references.
40 BUILTIN,
41 RUNTIME_FUNCTION,
42 IC_UTILITY,
43 DEBUG_ADDRESS,
44 STATS_COUNTER,
45 TOP_ADDRESS,
46 C_BUILTIN,
47 EXTENSION,
48 ACCESSOR,
49 RUNTIME_ENTRY,
50 STUB_CACHE_TABLE
51};
52
53const int kTypeCodeCount = STUB_CACHE_TABLE + 1;
54const int kFirstTypeCode = UNCLASSIFIED;
55
56const int kReferenceIdBits = 16;
57const int kReferenceIdMask = (1 << kReferenceIdBits) - 1;
58const int kReferenceTypeShift = kReferenceIdBits;
59const int kDebugRegisterBits = 4;
60const int kDebugIdShift = kDebugRegisterBits;
61
62
Ben Murdoch69a99ed2011-11-30 16:03:39 +000063// ExternalReferenceTable is a helper class that defines the relationship
64// between external references and their encodings. It is used to build
65// hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder.
66class ExternalReferenceTable {
67 public:
68 static ExternalReferenceTable* instance(Isolate* isolate);
69
70 ~ExternalReferenceTable() { }
71
72 int size() const { return refs_.length(); }
73
74 Address address(int i) { return refs_[i].address; }
75
76 uint32_t code(int i) { return refs_[i].code; }
77
78 const char* name(int i) { return refs_[i].name; }
79
80 int max_id(int code) { return max_id_[code]; }
81
82 private:
83 explicit ExternalReferenceTable(Isolate* isolate) : refs_(64) {
84 PopulateTable(isolate);
85 }
86
87 struct ExternalReferenceEntry {
88 Address address;
89 uint32_t code;
90 const char* name;
91 };
92
93 void PopulateTable(Isolate* isolate);
94
95 // For a few types of references, we can get their address from their id.
96 void AddFromId(TypeCode type,
97 uint16_t id,
98 const char* name,
99 Isolate* isolate);
100
101 // For other types of references, the caller will figure out the address.
102 void Add(Address address, TypeCode type, uint16_t id, const char* name);
103
104 List<ExternalReferenceEntry> refs_;
105 int max_id_[kTypeCodeCount];
106};
107
108
Steve Blocka7e24c12009-10-30 11:49:00 +0000109class ExternalReferenceEncoder {
110 public:
111 ExternalReferenceEncoder();
112
113 uint32_t Encode(Address key) const;
114
115 const char* NameOfAddress(Address key) const;
116
117 private:
118 HashMap encodings_;
119 static uint32_t Hash(Address key) {
120 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >> 2);
121 }
122
123 int IndexOf(Address key) const;
124
125 static bool Match(void* key1, void* key2) { return key1 == key2; }
126
127 void Put(Address key, int index);
Steve Block44f0eee2011-05-26 01:26:41 +0100128
129 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000130};
131
132
133class ExternalReferenceDecoder {
134 public:
135 ExternalReferenceDecoder();
136 ~ExternalReferenceDecoder();
137
138 Address Decode(uint32_t key) const {
139 if (key == 0) return NULL;
140 return *Lookup(key);
141 }
142
143 private:
144 Address** encodings_;
145
146 Address* Lookup(uint32_t key) const {
147 int type = key >> kReferenceTypeShift;
148 ASSERT(kFirstTypeCode <= type && type < kTypeCodeCount);
149 int id = key & kReferenceIdMask;
150 return &encodings_[type][id];
151 }
152
153 void Put(uint32_t key, Address value) {
154 *Lookup(key) = value;
155 }
Steve Block44f0eee2011-05-26 01:26:41 +0100156
157 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000158};
159
160
Steve Blockd0582a62009-12-15 09:54:21 +0000161class SnapshotByteSource {
Steve Blocka7e24c12009-10-30 11:49:00 +0000162 public:
Steve Blockd0582a62009-12-15 09:54:21 +0000163 SnapshotByteSource(const byte* array, int length)
164 : data_(array), length_(length), position_(0) { }
Steve Blocka7e24c12009-10-30 11:49:00 +0000165
Steve Blockd0582a62009-12-15 09:54:21 +0000166 bool HasMore() { return position_ < length_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000167
Steve Blockd0582a62009-12-15 09:54:21 +0000168 int Get() {
169 ASSERT(position_ < length_);
170 return data_[position_++];
Steve Blocka7e24c12009-10-30 11:49:00 +0000171 }
172
Andrei Popescu31002712010-02-23 13:46:05 +0000173 inline void CopyRaw(byte* to, int number_of_bytes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000174
Andrei Popescu31002712010-02-23 13:46:05 +0000175 inline int GetInt();
Steve Blocka7e24c12009-10-30 11:49:00 +0000176
Steve Blockd0582a62009-12-15 09:54:21 +0000177 bool AtEOF() {
178 return position_ == length_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000179 }
180
Leon Clarked91b9f72010-01-27 17:25:45 +0000181 int position() { return position_; }
Leon Clarkee46be812010-01-19 14:06:41 +0000182
Steve Blocka7e24c12009-10-30 11:49:00 +0000183 private:
Steve Blockd0582a62009-12-15 09:54:21 +0000184 const byte* data_;
185 int length_;
186 int position_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000187};
188
189
Ben Murdoch85b71792012-04-11 18:30:58 +0100190// It is very common to have a reference to objects at certain offsets in the
191// heap. These offsets have been determined experimentally. We code
192// references to such objects in a single byte that encodes the way the pointer
193// is written (only plain pointers allowed), the space number and the offset.
194// This only works for objects in the first page of a space. Don't use this for
195// things in newspace since it bypasses the write barrier.
196
197static const int k64 = (sizeof(uintptr_t) - 4) / 4;
198
199#define COMMON_REFERENCE_PATTERNS(f) \
200 f(kNumberOfSpaces, 2, (11 - k64)) \
201 f((kNumberOfSpaces + 1), 2, 0) \
202 f((kNumberOfSpaces + 2), 2, (142 - 16 * k64)) \
203 f((kNumberOfSpaces + 3), 2, (74 - 15 * k64)) \
204 f((kNumberOfSpaces + 4), 2, 5) \
205 f((kNumberOfSpaces + 5), 1, 135) \
206 f((kNumberOfSpaces + 6), 2, (228 - 39 * k64))
207
Steve Blockd0582a62009-12-15 09:54:21 +0000208#define COMMON_RAW_LENGTHS(f) \
209 f(1, 1) \
210 f(2, 2) \
211 f(3, 3) \
212 f(4, 4) \
213 f(5, 5) \
214 f(6, 6) \
215 f(7, 7) \
216 f(8, 8) \
217 f(9, 12) \
218 f(10, 16) \
219 f(11, 20) \
220 f(12, 24) \
221 f(13, 28) \
222 f(14, 32) \
223 f(15, 36)
224
Leon Clarked91b9f72010-01-27 17:25:45 +0000225// The Serializer/Deserializer class is a common superclass for Serializer and
226// Deserializer which is used to store common constants and methods used by
227// both.
228class SerializerDeserializer: public ObjectVisitor {
229 public:
Ben Murdoch257744e2011-11-30 15:57:28 +0000230 static void Iterate(ObjectVisitor* visitor);
231 static void SetSnapshotCacheSize(int size);
Leon Clarked91b9f72010-01-27 17:25:45 +0000232
Steve Blockd0582a62009-12-15 09:54:21 +0000233 protected:
Leon Clarkef7060e22010-06-03 12:02:55 +0100234 // Where the pointed-to object can be found:
235 enum Where {
236 kNewObject = 0, // Object is next in snapshot.
237 // 1-8 One per space.
238 kRootArray = 0x9, // Object is found in root array.
239 kPartialSnapshotCache = 0xa, // Object is in the cache.
240 kExternalReference = 0xb, // Pointer to an external reference.
Ben Murdoch85b71792012-04-11 18:30:58 +0100241 // 0xc-0xf Free.
Leon Clarkef7060e22010-06-03 12:02:55 +0100242 kBackref = 0x10, // Object is described relative to end.
243 // 0x11-0x18 One per space.
Ben Murdoch85b71792012-04-11 18:30:58 +0100244 // 0x19-0x1f Common backref offsets.
Leon Clarkef7060e22010-06-03 12:02:55 +0100245 kFromStart = 0x20, // Object is described relative to start.
246 // 0x21-0x28 One per space.
247 // 0x29-0x2f Free.
Ben Murdoch85b71792012-04-11 18:30:58 +0100248 // 0x30-0x3f Used by misc tags below.
Leon Clarkef7060e22010-06-03 12:02:55 +0100249 kPointedToMask = 0x3f
Steve Blockd0582a62009-12-15 09:54:21 +0000250 };
Leon Clarkef7060e22010-06-03 12:02:55 +0100251
252 // How to code the pointer to the object.
253 enum HowToCode {
254 kPlain = 0, // Straight pointer.
255 // What this means depends on the architecture:
256 kFromCode = 0x40, // A pointer inlined in code.
257 kHowToCodeMask = 0x40
258 };
259
260 // Where to point within the object.
261 enum WhereToPoint {
262 kStartOfObject = 0,
263 kFirstInstruction = 0x80,
264 kWhereToPointMask = 0x80
265 };
266
267 // Misc.
268 // Raw data to be copied from the snapshot.
Ben Murdoch257744e2011-11-30 15:57:28 +0000269 static const int kRawData = 0x30;
Leon Clarkef7060e22010-06-03 12:02:55 +0100270 // Some common raw lengths: 0x31-0x3f
271 // A tag emitted at strategic points in the snapshot to delineate sections.
272 // If the deserializer does not find these at the expected moments then it
273 // is an indication that the snapshot and the VM do not fit together.
274 // Examine the build process for architecture, version or configuration
275 // mismatches.
Ben Murdoch257744e2011-11-30 15:57:28 +0000276 static const int kSynchronize = 0x70;
Leon Clarkef7060e22010-06-03 12:02:55 +0100277 // Used for the source code of the natives, which is in the executable, but
278 // is referred to from external strings in the snapshot.
Ben Murdoch257744e2011-11-30 15:57:28 +0000279 static const int kNativesStringResource = 0x71;
280 static const int kNewPage = 0x72;
Ben Murdoch85b71792012-04-11 18:30:58 +0100281 // 0x73-0x7f Free.
282 // 0xb0-0xbf Free.
283 // 0xf0-0xff Free.
Leon Clarkef7060e22010-06-03 12:02:55 +0100284
285
Ben Murdoch257744e2011-11-30 15:57:28 +0000286 static const int kLargeData = LAST_SPACE;
287 static const int kLargeCode = kLargeData + 1;
288 static const int kLargeFixedArray = kLargeCode + 1;
289 static const int kNumberOfSpaces = kLargeFixedArray + 1;
290 static const int kAnyOldSpace = -1;
Steve Blockd0582a62009-12-15 09:54:21 +0000291
292 // A bitmask for getting the space out of an instruction.
Ben Murdoch257744e2011-11-30 15:57:28 +0000293 static const int kSpaceMask = 15;
Steve Blockd0582a62009-12-15 09:54:21 +0000294
Ben Murdoch257744e2011-11-30 15:57:28 +0000295 static inline bool SpaceIsLarge(int space) { return space >= kLargeData; }
296 static inline bool SpaceIsPaged(int space) {
Steve Blockd0582a62009-12-15 09:54:21 +0000297 return space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE;
298 }
299};
300
301
Andrei Popescu31002712010-02-23 13:46:05 +0000302int SnapshotByteSource::GetInt() {
303 // A little unwind to catch the really small ints.
304 int snapshot_byte = Get();
305 if ((snapshot_byte & 0x80) == 0) {
306 return snapshot_byte;
307 }
308 int accumulator = (snapshot_byte & 0x7f) << 7;
309 while (true) {
310 snapshot_byte = Get();
311 if ((snapshot_byte & 0x80) == 0) {
312 return accumulator | snapshot_byte;
313 }
314 accumulator = (accumulator | (snapshot_byte & 0x7f)) << 7;
315 }
316 UNREACHABLE();
317 return accumulator;
318}
319
320
321void SnapshotByteSource::CopyRaw(byte* to, int number_of_bytes) {
322 memcpy(to, data_ + position_, number_of_bytes);
323 position_ += number_of_bytes;
324}
325
Steve Blockd0582a62009-12-15 09:54:21 +0000326
Steve Blocka7e24c12009-10-30 11:49:00 +0000327// A Deserializer reads a snapshot and reconstructs the Object graph it defines.
Leon Clarked91b9f72010-01-27 17:25:45 +0000328class Deserializer: public SerializerDeserializer {
Steve Blocka7e24c12009-10-30 11:49:00 +0000329 public:
Steve Blockd0582a62009-12-15 09:54:21 +0000330 // Create a deserializer from a snapshot byte source.
331 explicit Deserializer(SnapshotByteSource* source);
Steve Blocka7e24c12009-10-30 11:49:00 +0000332
Leon Clarked91b9f72010-01-27 17:25:45 +0000333 virtual ~Deserializer();
Steve Blocka7e24c12009-10-30 11:49:00 +0000334
335 // Deserialize the snapshot into an empty heap.
336 void Deserialize();
Leon Clarkee46be812010-01-19 14:06:41 +0000337
338 // Deserialize a single object and the objects reachable from it.
339 void DeserializePartial(Object** root);
340
Ben Murdoch85b71792012-04-11 18:30:58 +0100341#ifdef DEBUG
342 virtual void Synchronize(const char* tag);
343#endif
344
Steve Blocka7e24c12009-10-30 11:49:00 +0000345 private:
346 virtual void VisitPointers(Object** start, Object** end);
Steve Blocka7e24c12009-10-30 11:49:00 +0000347
Steve Blockd0582a62009-12-15 09:54:21 +0000348 virtual void VisitExternalReferences(Address* start, Address* end) {
349 UNREACHABLE();
350 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000351
Steve Blockd0582a62009-12-15 09:54:21 +0000352 virtual void VisitRuntimeEntry(RelocInfo* rinfo) {
353 UNREACHABLE();
354 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000355
Ben Murdoch85b71792012-04-11 18:30:58 +0100356 void ReadChunk(Object** start, Object** end, int space, Address address);
Steve Blockd0582a62009-12-15 09:54:21 +0000357 HeapObject* GetAddressFromStart(int space);
358 inline HeapObject* GetAddressFromEnd(int space);
359 Address Allocate(int space_number, Space* space, int size);
360 void ReadObject(int space_number, Space* space, Object** write_back);
Steve Blocka7e24c12009-10-30 11:49:00 +0000361
Steve Block44f0eee2011-05-26 01:26:41 +0100362 // Cached current isolate.
363 Isolate* isolate_;
364
Steve Blockd0582a62009-12-15 09:54:21 +0000365 // Keep track of the pages in the paged spaces.
366 // (In large object space we are keeping track of individual objects
367 // rather than pages.) In new space we just need the address of the
368 // first object and the others will flow from that.
Leon Clarked91b9f72010-01-27 17:25:45 +0000369 List<Address> pages_[SerializerDeserializer::kNumberOfSpaces];
Steve Blocka7e24c12009-10-30 11:49:00 +0000370
Steve Blockd0582a62009-12-15 09:54:21 +0000371 SnapshotByteSource* source_;
Steve Blockd0582a62009-12-15 09:54:21 +0000372 // This is the address of the next object that will be allocated in each
373 // space. It is used to calculate the addresses of back-references.
374 Address high_water_[LAST_SPACE + 1];
375 // This is the address of the most recent object that was allocated. It
376 // is used to set the location of the new page when we encounter a
377 // START_NEW_PAGE_SERIALIZATION tag.
378 Address last_object_address_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000379
Steve Block44f0eee2011-05-26 01:26:41 +0100380 ExternalReferenceDecoder* external_reference_decoder_;
381
Steve Blocka7e24c12009-10-30 11:49:00 +0000382 DISALLOW_COPY_AND_ASSIGN(Deserializer);
383};
384
Steve Blockd0582a62009-12-15 09:54:21 +0000385
386class SnapshotByteSink {
387 public:
388 virtual ~SnapshotByteSink() { }
389 virtual void Put(int byte, const char* description) = 0;
390 virtual void PutSection(int byte, const char* description) {
391 Put(byte, description);
392 }
393 void PutInt(uintptr_t integer, const char* description);
Leon Clarkee46be812010-01-19 14:06:41 +0000394 virtual int Position() = 0;
Steve Blockd0582a62009-12-15 09:54:21 +0000395};
396
397
Leon Clarked91b9f72010-01-27 17:25:45 +0000398// Mapping objects to their location after deserialization.
399// This is used during building, but not at runtime by V8.
400class SerializationAddressMapper {
401 public:
402 SerializationAddressMapper()
403 : serialization_map_(new HashMap(&SerializationMatchFun)),
404 no_allocation_(new AssertNoAllocation()) { }
405
406 ~SerializationAddressMapper() {
407 delete serialization_map_;
408 delete no_allocation_;
409 }
410
411 bool IsMapped(HeapObject* obj) {
412 return serialization_map_->Lookup(Key(obj), Hash(obj), false) != NULL;
413 }
414
415 int MappedTo(HeapObject* obj) {
416 ASSERT(IsMapped(obj));
417 return static_cast<int>(reinterpret_cast<intptr_t>(
418 serialization_map_->Lookup(Key(obj), Hash(obj), false)->value));
419 }
420
421 void AddMapping(HeapObject* obj, int to) {
422 ASSERT(!IsMapped(obj));
423 HashMap::Entry* entry =
424 serialization_map_->Lookup(Key(obj), Hash(obj), true);
425 entry->value = Value(to);
426 }
427
428 private:
Ben Murdoch257744e2011-11-30 15:57:28 +0000429 static bool SerializationMatchFun(void* key1, void* key2) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000430 return key1 == key2;
431 }
432
Ben Murdoch257744e2011-11-30 15:57:28 +0000433 static uint32_t Hash(HeapObject* obj) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000434 return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
435 }
436
Ben Murdoch257744e2011-11-30 15:57:28 +0000437 static void* Key(HeapObject* obj) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000438 return reinterpret_cast<void*>(obj->address());
439 }
440
Ben Murdoch257744e2011-11-30 15:57:28 +0000441 static void* Value(int v) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000442 return reinterpret_cast<void*>(v);
443 }
444
445 HashMap* serialization_map_;
446 AssertNoAllocation* no_allocation_;
447 DISALLOW_COPY_AND_ASSIGN(SerializationAddressMapper);
448};
449
450
Steve Block44f0eee2011-05-26 01:26:41 +0100451// There can be only one serializer per V8 process.
Ben Murdoch257744e2011-11-30 15:57:28 +0000452class Serializer : public SerializerDeserializer {
Steve Blockd0582a62009-12-15 09:54:21 +0000453 public:
454 explicit Serializer(SnapshotByteSink* sink);
Andrei Popescu31002712010-02-23 13:46:05 +0000455 ~Serializer();
Steve Blockd0582a62009-12-15 09:54:21 +0000456 void VisitPointers(Object** start, Object** end);
Leon Clarkee46be812010-01-19 14:06:41 +0000457 // You can call this after serialization to find out how much space was used
458 // in each space.
459 int CurrentAllocationAddress(int space) {
460 if (SpaceIsLarge(space)) return large_object_total_;
461 return fullness_[space];
462 }
Steve Blockd0582a62009-12-15 09:54:21 +0000463
Ben Murdoch257744e2011-11-30 15:57:28 +0000464 static void Enable() {
Steve Blockd0582a62009-12-15 09:54:21 +0000465 if (!serialization_enabled_) {
466 ASSERT(!too_late_to_enable_now_);
467 }
468 serialization_enabled_ = true;
469 }
470
Ben Murdoch257744e2011-11-30 15:57:28 +0000471 static void Disable() { serialization_enabled_ = false; }
Steve Blockd0582a62009-12-15 09:54:21 +0000472 // Call this when you have made use of the fact that there is no serialization
473 // going on.
Ben Murdoch257744e2011-11-30 15:57:28 +0000474 static void TooLateToEnableNow() { too_late_to_enable_now_ = true; }
475 static bool enabled() { return serialization_enabled_; }
Leon Clarked91b9f72010-01-27 17:25:45 +0000476 SerializationAddressMapper* address_mapper() { return &address_mapper_; }
Ben Murdoch85b71792012-04-11 18:30:58 +0100477#ifdef DEBUG
478 virtual void Synchronize(const char* tag);
479#endif
Steve Blockd0582a62009-12-15 09:54:21 +0000480
Leon Clarked91b9f72010-01-27 17:25:45 +0000481 protected:
Ben Murdoch257744e2011-11-30 15:57:28 +0000482 static const int kInvalidRootIndex = -1;
Ben Murdoch85b71792012-04-11 18:30:58 +0100483 virtual int RootIndex(HeapObject* heap_object) = 0;
Leon Clarked91b9f72010-01-27 17:25:45 +0000484 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) = 0;
485
Steve Blockd0582a62009-12-15 09:54:21 +0000486 class ObjectSerializer : public ObjectVisitor {
487 public:
488 ObjectSerializer(Serializer* serializer,
489 Object* o,
490 SnapshotByteSink* sink,
Leon Clarkef7060e22010-06-03 12:02:55 +0100491 HowToCode how_to_code,
492 WhereToPoint where_to_point)
Steve Blockd0582a62009-12-15 09:54:21 +0000493 : serializer_(serializer),
494 object_(HeapObject::cast(o)),
495 sink_(sink),
Leon Clarkef7060e22010-06-03 12:02:55 +0100496 reference_representation_(how_to_code + where_to_point),
Steve Blockd0582a62009-12-15 09:54:21 +0000497 bytes_processed_so_far_(0) { }
498 void Serialize();
499 void VisitPointers(Object** start, Object** end);
500 void VisitExternalReferences(Address* start, Address* end);
501 void VisitCodeTarget(RelocInfo* target);
Steve Block791712a2010-08-27 10:21:07 +0100502 void VisitCodeEntry(Address entry_address);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100503 void VisitGlobalPropertyCell(RelocInfo* rinfo);
Steve Blockd0582a62009-12-15 09:54:21 +0000504 void VisitRuntimeEntry(RelocInfo* reloc);
505 // Used for seralizing the external strings that hold the natives source.
506 void VisitExternalAsciiString(
507 v8::String::ExternalAsciiStringResource** resource);
508 // We can't serialize a heap with external two byte strings.
509 void VisitExternalTwoByteString(
510 v8::String::ExternalStringResource** resource) {
511 UNREACHABLE();
512 }
513
514 private:
515 void OutputRawData(Address up_to);
516
517 Serializer* serializer_;
518 HeapObject* object_;
519 SnapshotByteSink* sink_;
Leon Clarkef7060e22010-06-03 12:02:55 +0100520 int reference_representation_;
Steve Blockd0582a62009-12-15 09:54:21 +0000521 int bytes_processed_so_far_;
522 };
523
Leon Clarked91b9f72010-01-27 17:25:45 +0000524 virtual void SerializeObject(Object* o,
Leon Clarkef7060e22010-06-03 12:02:55 +0100525 HowToCode how_to_code,
526 WhereToPoint where_to_point) = 0;
Leon Clarked91b9f72010-01-27 17:25:45 +0000527 void SerializeReferenceToPreviousObject(
528 int space,
529 int address,
Leon Clarkef7060e22010-06-03 12:02:55 +0100530 HowToCode how_to_code,
531 WhereToPoint where_to_point);
Steve Blockd0582a62009-12-15 09:54:21 +0000532 void InitializeAllocators();
533 // This will return the space for an object. If the object is in large
534 // object space it may return kLargeCode or kLargeFixedArray in order
535 // to indicate to the deserializer what kind of large object allocation
536 // to make.
Ben Murdoch257744e2011-11-30 15:57:28 +0000537 static int SpaceOfObject(HeapObject* object);
Steve Blockd0582a62009-12-15 09:54:21 +0000538 // This just returns the space of the object. It will return LO_SPACE
539 // for all large objects since you can't check the type of the object
540 // once the map has been used for the serialization address.
Ben Murdoch257744e2011-11-30 15:57:28 +0000541 static int SpaceOfAlreadySerializedObject(HeapObject* object);
Steve Blockd0582a62009-12-15 09:54:21 +0000542 int Allocate(int space, int size, bool* new_page_started);
Steve Blockd0582a62009-12-15 09:54:21 +0000543 int EncodeExternalReference(Address addr) {
544 return external_reference_encoder_->Encode(addr);
545 }
546
547 // Keep track of the fullness of each space in order to generate
548 // relative addresses for back references. Large objects are
549 // just numbered sequentially since relative addresses make no
550 // sense in large object space.
551 int fullness_[LAST_SPACE + 1];
552 SnapshotByteSink* sink_;
553 int current_root_index_;
554 ExternalReferenceEncoder* external_reference_encoder_;
Ben Murdoch257744e2011-11-30 15:57:28 +0000555 static bool serialization_enabled_;
Steve Blockd0582a62009-12-15 09:54:21 +0000556 // Did we already make use of the fact that serialization was not enabled?
Ben Murdoch257744e2011-11-30 15:57:28 +0000557 static bool too_late_to_enable_now_;
Leon Clarkee46be812010-01-19 14:06:41 +0000558 int large_object_total_;
Leon Clarked91b9f72010-01-27 17:25:45 +0000559 SerializationAddressMapper address_mapper_;
Steve Blockd0582a62009-12-15 09:54:21 +0000560
561 friend class ObjectSerializer;
562 friend class Deserializer;
563
564 DISALLOW_COPY_AND_ASSIGN(Serializer);
565};
566
Leon Clarked91b9f72010-01-27 17:25:45 +0000567
568class PartialSerializer : public Serializer {
569 public:
570 PartialSerializer(Serializer* startup_snapshot_serializer,
571 SnapshotByteSink* sink)
572 : Serializer(sink),
573 startup_serializer_(startup_snapshot_serializer) {
574 }
575
576 // Serialize the objects reachable from a single object pointer.
577 virtual void Serialize(Object** o);
578 virtual void SerializeObject(Object* o,
Leon Clarkef7060e22010-06-03 12:02:55 +0100579 HowToCode how_to_code,
580 WhereToPoint where_to_point);
Leon Clarked91b9f72010-01-27 17:25:45 +0000581
582 protected:
Ben Murdoch85b71792012-04-11 18:30:58 +0100583 virtual int RootIndex(HeapObject* o);
Leon Clarked91b9f72010-01-27 17:25:45 +0000584 virtual int PartialSnapshotCacheIndex(HeapObject* o);
585 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
Andrei Popescu31002712010-02-23 13:46:05 +0000586 // Scripts should be referred only through shared function infos. We can't
587 // allow them to be part of the partial snapshot because they contain a
588 // unique ID, and deserializing several partial snapshots containing script
589 // would cause dupes.
590 ASSERT(!o->IsScript());
Steve Block6ded16b2010-05-10 14:33:55 +0100591 return o->IsString() || o->IsSharedFunctionInfo() ||
Iain Merrick75681382010-08-19 15:07:18 +0100592 o->IsHeapNumber() || o->IsCode() ||
Ben Murdoch85b71792012-04-11 18:30:58 +0100593 o->IsSerializedScopeInfo() ||
Steve Block44f0eee2011-05-26 01:26:41 +0100594 o->map() == HEAP->fixed_cow_array_map();
Leon Clarked91b9f72010-01-27 17:25:45 +0000595 }
596
597 private:
598 Serializer* startup_serializer_;
599 DISALLOW_COPY_AND_ASSIGN(PartialSerializer);
600};
601
602
603class StartupSerializer : public Serializer {
604 public:
605 explicit StartupSerializer(SnapshotByteSink* sink) : Serializer(sink) {
606 // Clear the cache of objects used by the partial snapshot. After the
607 // strong roots have been serialized we can create a partial snapshot
Ben Murdoch85b71792012-04-11 18:30:58 +0100608 // which will repopulate the cache with objects neede by that partial
Leon Clarked91b9f72010-01-27 17:25:45 +0000609 // snapshot.
Steve Block44f0eee2011-05-26 01:26:41 +0100610 Isolate::Current()->set_serialize_partial_snapshot_cache_length(0);
Leon Clarked91b9f72010-01-27 17:25:45 +0000611 }
612 // Serialize the current state of the heap. The order is:
613 // 1) Strong references.
614 // 2) Partial snapshot cache.
Ben Murdoch85b71792012-04-11 18:30:58 +0100615 // 3) Weak references (eg the symbol table).
Leon Clarked91b9f72010-01-27 17:25:45 +0000616 virtual void SerializeStrongReferences();
617 virtual void SerializeObject(Object* o,
Leon Clarkef7060e22010-06-03 12:02:55 +0100618 HowToCode how_to_code,
619 WhereToPoint where_to_point);
Leon Clarked91b9f72010-01-27 17:25:45 +0000620 void SerializeWeakReferences();
621 void Serialize() {
622 SerializeStrongReferences();
623 SerializeWeakReferences();
624 }
625
626 private:
Ben Murdoch85b71792012-04-11 18:30:58 +0100627 virtual int RootIndex(HeapObject* o) { return kInvalidRootIndex; }
Leon Clarked91b9f72010-01-27 17:25:45 +0000628 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
629 return false;
630 }
631};
632
Andrei Popescu31002712010-02-23 13:46:05 +0000633
Steve Blocka7e24c12009-10-30 11:49:00 +0000634} } // namespace v8::internal
635
636#endif // V8_SERIALIZE_H_