170
170
return data_[position_++];
173
int32_t GetUnalignedInt() {
174
#if defined(V8_HOST_CAN_READ_UNALIGNED) && __BYTE_ORDER == __LITTLE_ENDIAN
176
ASSERT(position_ + sizeof(answer) <= length_ + 0u);
177
answer = *reinterpret_cast<const int32_t*>(data_ + position_);
179
int32_t answer = data_[position_];
180
answer |= data_[position_ + 1] << 8;
181
answer |= data_[position_ + 2] << 16;
182
answer |= data_[position_ + 3] << 24;
187
void Advance(int by) { position_ += by; }
173
189
inline void CopyRaw(byte* to, int number_of_bytes);
175
191
inline int GetInt();
178
return position_ == length_;
181
195
int position() { return position_; }
190
// 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.
197
static const int k64 = (sizeof(uintptr_t) - 4) / 4;
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))
208
#define COMMON_RAW_LENGTHS(f) \
225
204
// The Serializer/Deserializer class is a common superclass for Serializer and
226
205
// Deserializer which is used to store common constants and methods used by
228
207
class SerializerDeserializer: public ObjectVisitor {
230
209
static void Iterate(ObjectVisitor* visitor);
231
static void SetSnapshotCacheSize(int size);
211
static int nop() { return kNop; }
234
214
// Where the pointed-to object can be found:
236
216
kNewObject = 0, // Object is next in snapshot.
237
// 1-8 One per space.
217
// 1-6 One per space.
238
218
kRootArray = 0x9, // Object is found in root array.
239
219
kPartialSnapshotCache = 0xa, // Object is in the cache.
240
220
kExternalReference = 0xb, // Pointer to an external reference.
242
kBackref = 0x10, // Object is described relative to end.
243
// 0x11-0x18 One per space.
244
// 0x19-0x1f Common backref offsets.
245
kFromStart = 0x20, // Object is described relative to start.
246
// 0x21-0x28 One per space.
248
// 0x30-0x3f Used by misc tags below.
221
kSkip = 0xc, // Skip n bytes.
222
kNop = 0xd, // Does nothing, used to pad.
224
kBackref = 0x10, // Object is described relative to end.
225
// 0x11-0x16 One per space.
226
kBackrefWithSkip = 0x18, // Object is described relative to end.
227
// 0x19-0x1e One per space.
228
// 0x20-0x3f Used by misc. tags below.
249
229
kPointedToMask = 0x3f
257
237
kHowToCodeMask = 0x40
240
// For kRootArrayConstants
243
kHasSkipDistance = 0x40,
260
247
// Where to point within the object.
261
248
enum WhereToPoint {
262
249
kStartOfObject = 0,
263
kFirstInstruction = 0x80,
250
kInnerPointer = 0x80, // First insn in code object or payload of cell.
264
251
kWhereToPointMask = 0x80
268
// Raw data to be copied from the snapshot.
269
static const int kRawData = 0x30;
270
// Some common raw lengths: 0x31-0x3f
255
// Raw data to be copied from the snapshot. This byte code does not advance
256
// the current pointer, which is used for code objects, where we write the
257
// entire code in one memcpy, then fix up stuff with kSkip and other byte
258
// codes that overwrite data.
259
static const int kRawData = 0x20;
260
// Some common raw lengths: 0x21-0x3f. These autoadvance the current pointer.
271
261
// A tag emitted at strategic points in the snapshot to delineate sections.
272
262
// If the deserializer does not find these at the expected moments then it
273
263
// is an indication that the snapshot and the VM do not fit together.
277
267
// Used for the source code of the natives, which is in the executable, but
278
268
// is referred to from external strings in the snapshot.
279
269
static const int kNativesStringResource = 0x71;
280
static const int kNewPage = 0x72;
286
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;
270
static const int kRepeat = 0x72;
271
static const int kConstantRepeat = 0x73;
272
// 0x73-0x7f Repeat last word (subtract 0x72 to get the count).
273
static const int kMaxRepeats = 0x7f - 0x72;
274
static int CodeForRepeats(int repeats) {
275
ASSERT(repeats >= 1 && repeats <= kMaxRepeats);
276
return 0x72 + repeats;
278
static int RepeatsForCode(int byte_code) {
279
ASSERT(byte_code >= kConstantRepeat && byte_code <= 0x7f);
280
return byte_code - 0x72;
282
static const int kRootArrayConstants = 0xa0;
283
// 0xa0-0xbf Things from the first 32 elements of the root array.
284
static const int kRootArrayNumberOfConstantEncodings = 0x20;
285
static int RootArrayConstantFromByteCode(int byte_code) {
286
return byte_code & 0x1f;
289
static const int kNumberOfSpaces = LO_SPACE;
290
290
static const int kAnyOldSpace = -1;
292
292
// A bitmask for getting the space out of an instruction.
293
static const int kSpaceMask = 15;
295
static inline bool SpaceIsLarge(int space) { return space >= kLargeData; }
296
static inline bool SpaceIsPaged(int space) {
297
return space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE;
293
static const int kSpaceMask = 7;
302
297
int 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;
308
int accumulator = (snapshot_byte & 0x7f) << 7;
310
snapshot_byte = Get();
311
if ((snapshot_byte & 0x80) == 0) {
312
return accumulator | snapshot_byte;
314
accumulator = (accumulator | (snapshot_byte & 0x7f)) << 7;
298
// This way of variable-length encoding integers does not suffer from branch
300
uint32_t answer = GetUnalignedInt();
301
int bytes = answer & 3;
303
uint32_t mask = 0xffffffffu;
304
mask >>= 32 - (bytes << 3);
338
328
// Deserialize a single object and the objects reachable from it.
339
329
void DeserializePartial(Object** root);
342
virtual void Synchronize(const char* tag);
331
void set_reservation(int space_number, int reservation) {
332
ASSERT(space_number >= 0);
333
ASSERT(space_number <= LAST_SPACE);
334
reservations_[space_number] = reservation;
346
338
virtual void VisitPointers(Object** start, Object** end);
356
void ReadChunk(Object** start, Object** end, int space, Address address);
357
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);
348
// Fills in some heap data in an area from start to end (non-inclusive). The
349
// space id is used for the write barrier. The object_address is the address
350
// of the object we are writing into, or NULL if we are not writing into an
351
// object, i.e. if we are writing a series of tagged values that are not on
354
Object** start, Object** end, int space, Address object_address);
355
void ReadObject(int space_number, Object** write_back);
357
// This routine both allocates a new object, and also keeps
358
// track of where objects have been allocated so that we can
359
// fix back references when deserializing.
360
Address Allocate(int space_index, int size) {
361
Address address = high_water_[space_index];
362
high_water_[space_index] = address + size;
366
// This returns the address of an object that has been described in the
367
// snapshot as being offset bytes back in a particular space.
368
HeapObject* GetAddressFromEnd(int space) {
369
int offset = source_->GetInt();
370
offset <<= kObjectAlignmentBits;
371
return HeapObject::FromAddress(high_water_[space] - offset);
362
375
// Cached current isolate.
363
376
Isolate* isolate_;
365
// 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.
369
List<Address> pages_[SerializerDeserializer::kNumberOfSpaces];
371
378
SnapshotByteSource* source_;
372
379
// This is the address of the next object that will be allocated in each
373
380
// space. It is used to calculate the addresses of back-references.
374
381
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_;
383
int reservations_[LAST_SPACE + 1];
384
static const intptr_t kUninitializedReservation = -1;
380
386
ExternalReferenceDecoder* external_reference_decoder_;
474
480
static void TooLateToEnableNow() { too_late_to_enable_now_ = true; }
475
481
static bool enabled() { return serialization_enabled_; }
476
482
SerializationAddressMapper* address_mapper() { return &address_mapper_; }
478
virtual void Synchronize(const char* tag);
483
void PutRoot(int index,
482
490
static const int kInvalidRootIndex = -1;
483
virtual int RootIndex(HeapObject* heap_object) = 0;
492
int RootIndex(HeapObject* heap_object, HowToCode from);
484
493
virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) = 0;
494
intptr_t root_index_wave_front() { return root_index_wave_front_; }
495
void set_root_index_wave_front(intptr_t value) {
496
ASSERT(value >= root_index_wave_front_);
497
root_index_wave_front_ = value;
486
500
class ObjectSerializer : public ObjectVisitor {
494
508
object_(HeapObject::cast(o)),
496
510
reference_representation_(how_to_code + where_to_point),
497
bytes_processed_so_far_(0) { }
511
bytes_processed_so_far_(0),
512
code_object_(o->IsCode()),
513
code_has_been_output_(false) { }
498
514
void Serialize();
499
515
void VisitPointers(Object** start, Object** end);
516
void VisitEmbeddedPointer(RelocInfo* target);
500
517
void VisitExternalReferences(Address* start, Address* end);
518
void VisitExternalReference(RelocInfo* rinfo);
501
519
void VisitCodeTarget(RelocInfo* target);
502
520
void VisitCodeEntry(Address entry_address);
503
521
void VisitGlobalPropertyCell(RelocInfo* rinfo);
515
void OutputRawData(Address up_to);
533
enum ReturnSkip { kCanReturnSkipInsteadOfSkipping, kIgnoringReturn };
534
// This function outputs or skips the raw data between the last pointer and
535
// up to the current position. It optionally can just return the number of
536
// bytes to skip instead of performing a skip instruction, in case the skip
537
// can be merged into the next instruction.
538
int OutputRawData(Address up_to, ReturnSkip return_skip = kIgnoringReturn);
517
540
Serializer* serializer_;
518
541
HeapObject* object_;
519
542
SnapshotByteSink* sink_;
520
543
int reference_representation_;
521
544
int bytes_processed_so_far_;
546
bool code_has_been_output_;
524
549
virtual void SerializeObject(Object* o,
525
550
HowToCode how_to_code,
526
WhereToPoint where_to_point) = 0;
551
WhereToPoint where_to_point,
527
553
void SerializeReferenceToPreviousObject(
530
556
HowToCode how_to_code,
531
WhereToPoint where_to_point);
557
WhereToPoint where_to_point,
532
559
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
560
// This will return the space for an object.
537
561
static int SpaceOfObject(HeapObject* object);
538
// 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.
541
static int SpaceOfAlreadySerializedObject(HeapObject* object);
542
int Allocate(int space, int size, bool* new_page_started);
562
int Allocate(int space, int size);
543
563
int EncodeExternalReference(Address addr) {
544
564
return external_reference_encoder_->Encode(addr);
567
int SpaceAreaSize(int space);
547
570
// 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.
571
// relative addresses for back references.
551
572
int fullness_[LAST_SPACE + 1];
552
573
SnapshotByteSink* sink_;
553
574
int current_root_index_;
555
576
static bool serialization_enabled_;
556
577
// Did we already make use of the fact that serialization was not enabled?
557
578
static bool too_late_to_enable_now_;
558
int large_object_total_;
559
579
SerializationAddressMapper address_mapper_;
580
intptr_t root_index_wave_front_;
561
583
friend class ObjectSerializer;
562
584
friend class Deserializer;
564
587
DISALLOW_COPY_AND_ASSIGN(Serializer);
571
594
SnapshotByteSink* sink)
572
595
: Serializer(sink),
573
596
startup_serializer_(startup_snapshot_serializer) {
597
set_root_index_wave_front(Heap::kStrongRootListLength);
576
600
// Serialize the objects reachable from a single object pointer.
577
601
virtual void Serialize(Object** o);
578
602
virtual void SerializeObject(Object* o,
579
603
HowToCode how_to_code,
580
WhereToPoint where_to_point);
604
WhereToPoint where_to_point,
583
virtual int RootIndex(HeapObject* o);
584
608
virtual int PartialSnapshotCacheIndex(HeapObject* o);
585
609
virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
586
610
// Scripts should be referred only through shared function infos. We can't
605
629
explicit StartupSerializer(SnapshotByteSink* sink) : Serializer(sink) {
606
630
// Clear the cache of objects used by the partial snapshot. After the
607
631
// strong roots have been serialized we can create a partial snapshot
608
// which will repopulate the cache with objects neede by that partial
632
// which will repopulate the cache with objects needed by that partial
610
634
Isolate::Current()->set_serialize_partial_snapshot_cache_length(0);
612
636
// Serialize the current state of the heap. The order is:
613
637
// 1) Strong references.
614
638
// 2) Partial snapshot cache.
615
// 3) Weak references (eg the symbol table).
639
// 3) Weak references (e.g. the symbol table).
616
640
virtual void SerializeStrongReferences();
617
641
virtual void SerializeObject(Object* o,
618
642
HowToCode how_to_code,
619
WhereToPoint where_to_point);
643
WhereToPoint where_to_point,
620
645
void SerializeWeakReferences();
621
646
void Serialize() {
622
647
SerializeStrongReferences();
623
648
SerializeWeakReferences();
627
virtual int RootIndex(HeapObject* o) { return kInvalidRootIndex; }
628
653
virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {