| Index: src/serialize.h
|
| diff --git a/src/serialize.h b/src/serialize.h
|
| index 204179285623e3c55e43448a8cafcb04b34ce9de..8beb88e8b21ae110f40eef664ebb4c27db044d40 100644
|
| --- a/src/serialize.h
|
| +++ b/src/serialize.h
|
| @@ -170,27 +170,13 @@ class SnapshotByteSource {
|
| return data_[position_++];
|
| }
|
|
|
| - int32_t GetUnalignedInt() {
|
| -#if defined(V8_HOST_CAN_READ_UNALIGNED) && __BYTE_ORDER == __LITTLE_ENDIAN
|
| - int32_t answer;
|
| - ASSERT(position_ + sizeof(answer) <= length_ + 0u);
|
| - answer = *reinterpret_cast<const int32_t*>(data_ + position_);
|
| -#else
|
| - int32_t answer = data_[position_];
|
| - answer |= data_[position_ + 1] << 8;
|
| - answer |= data_[position_ + 2] << 16;
|
| - answer |= data_[position_ + 3] << 24;
|
| -#endif
|
| - return answer;
|
| - }
|
| -
|
| - void Advance(int by) { position_ += by; }
|
| -
|
| inline void CopyRaw(byte* to, int number_of_bytes);
|
|
|
| inline int GetInt();
|
|
|
| - bool AtEOF();
|
| + bool AtEOF() {
|
| + return position_ == length_;
|
| + }
|
|
|
| int position() { return position_; }
|
|
|
| @@ -201,6 +187,23 @@ class SnapshotByteSource {
|
| };
|
|
|
|
|
| +#define COMMON_RAW_LENGTHS(f) \
|
| + f(1, 1) \
|
| + f(2, 2) \
|
| + f(3, 3) \
|
| + f(4, 4) \
|
| + f(5, 5) \
|
| + f(6, 6) \
|
| + f(7, 7) \
|
| + f(8, 8) \
|
| + f(9, 12) \
|
| + f(10, 16) \
|
| + f(11, 20) \
|
| + f(12, 24) \
|
| + f(13, 28) \
|
| + f(14, 32) \
|
| + f(15, 36)
|
| +
|
| // The Serializer/Deserializer class is a common superclass for Serializer and
|
| // Deserializer which is used to store common constants and methods used by
|
| // both.
|
| @@ -208,24 +211,23 @@ class SerializerDeserializer: public ObjectVisitor {
|
| public:
|
| static void Iterate(ObjectVisitor* visitor);
|
|
|
| - static int nop() { return kNop; }
|
| -
|
| protected:
|
| // Where the pointed-to object can be found:
|
| enum Where {
|
| kNewObject = 0, // Object is next in snapshot.
|
| - // 1-6 One per space.
|
| + // 1-8 One per space.
|
| kRootArray = 0x9, // Object is found in root array.
|
| kPartialSnapshotCache = 0xa, // Object is in the cache.
|
| kExternalReference = 0xb, // Pointer to an external reference.
|
| - kSkip = 0xc, // Skip n bytes.
|
| - kNop = 0xd, // Does nothing, used to pad.
|
| - // 0xe-0xf Free.
|
| - kBackref = 0x10, // Object is described relative to end.
|
| - // 0x11-0x16 One per space.
|
| - kBackrefWithSkip = 0x18, // Object is described relative to end.
|
| - // 0x19-0x1e One per space.
|
| - // 0x20-0x3f Used by misc. tags below.
|
| + kSkip = 0xc, // Skip a pointer sized cell.
|
| + // 0xd-0xf Free.
|
| + kBackref = 0x10, // Object is described relative to end.
|
| + // 0x11-0x18 One per space.
|
| + // 0x19-0x1f Free.
|
| + kFromStart = 0x20, // Object is described relative to start.
|
| + // 0x21-0x28 One per space.
|
| + // 0x29-0x2f Free.
|
| + // 0x30-0x3f Used by misc. tags below.
|
| kPointedToMask = 0x3f
|
| };
|
|
|
| @@ -237,13 +239,6 @@ class SerializerDeserializer: public ObjectVisitor {
|
| kHowToCodeMask = 0x40
|
| };
|
|
|
| - // For kRootArrayConstants
|
| - enum WithSkip {
|
| - kNoSkipDistance = 0,
|
| - kHasSkipDistance = 0x40,
|
| - kWithSkipMask = 0x40
|
| - };
|
| -
|
| // Where to point within the object.
|
| enum WhereToPoint {
|
| kStartOfObject = 0,
|
| @@ -252,12 +247,9 @@ class SerializerDeserializer: public ObjectVisitor {
|
| };
|
|
|
| // Misc.
|
| - // Raw data to be copied from the snapshot. This byte code does not advance
|
| - // the current pointer, which is used for code objects, where we write the
|
| - // entire code in one memcpy, then fix up stuff with kSkip and other byte
|
| - // codes that overwrite data.
|
| - static const int kRawData = 0x20;
|
| - // Some common raw lengths: 0x21-0x3f. These autoadvance the current pointer.
|
| + // Raw data to be copied from the snapshot.
|
| + static const int kRawData = 0x30;
|
| + // Some common raw lengths: 0x31-0x3f
|
| // A tag emitted at strategic points in the snapshot to delineate sections.
|
| // If the deserializer does not find these at the expected moments then it
|
| // is an indication that the snapshot and the VM do not fit together.
|
| @@ -267,44 +259,64 @@ class SerializerDeserializer: public ObjectVisitor {
|
| // Used for the source code of the natives, which is in the executable, but
|
| // is referred to from external strings in the snapshot.
|
| static const int kNativesStringResource = 0x71;
|
| - static const int kRepeat = 0x72;
|
| - static const int kConstantRepeat = 0x73;
|
| - // 0x73-0x7f Repeat last word (subtract 0x72 to get the count).
|
| - static const int kMaxRepeats = 0x7f - 0x72;
|
| + static const int kNewPage = 0x72;
|
| + static const int kRepeat = 0x73;
|
| + static const int kConstantRepeat = 0x74;
|
| + // 0x74-0x7f Repeat last word (subtract 0x73 to get the count).
|
| + static const int kMaxRepeats = 0x7f - 0x73;
|
| static int CodeForRepeats(int repeats) {
|
| ASSERT(repeats >= 1 && repeats <= kMaxRepeats);
|
| - return 0x72 + repeats;
|
| + return 0x73 + repeats;
|
| }
|
| static int RepeatsForCode(int byte_code) {
|
| ASSERT(byte_code >= kConstantRepeat && byte_code <= 0x7f);
|
| - return byte_code - 0x72;
|
| + return byte_code - 0x73;
|
| }
|
| - static const int kRootArrayConstants = 0xa0;
|
| - // 0xa0-0xbf Things from the first 32 elements of the root array.
|
| + static const int kRootArrayLowConstants = 0xb0;
|
| + // 0xb0-0xbf Things from the first 16 elements of the root array.
|
| + static const int kRootArrayHighConstants = 0xf0;
|
| + // 0xf0-0xff Things from the next 16 elements of the root array.
|
| static const int kRootArrayNumberOfConstantEncodings = 0x20;
|
| + static const int kRootArrayNumberOfLowConstantEncodings = 0x10;
|
| static int RootArrayConstantFromByteCode(int byte_code) {
|
| - return byte_code & 0x1f;
|
| + int constant = (byte_code & 0xf) | ((byte_code & 0x40) >> 2);
|
| + ASSERT(constant >= 0 && constant < kRootArrayNumberOfConstantEncodings);
|
| + return constant;
|
| }
|
|
|
| - static const int kNumberOfSpaces = LO_SPACE;
|
| +
|
| + static const int kLargeData = LAST_SPACE;
|
| + static const int kLargeCode = kLargeData + 1;
|
| + static const int kLargeFixedArray = kLargeCode + 1;
|
| + static const int kNumberOfSpaces = kLargeFixedArray + 1;
|
| static const int kAnyOldSpace = -1;
|
|
|
| // A bitmask for getting the space out of an instruction.
|
| - static const int kSpaceMask = 7;
|
| + static const int kSpaceMask = 15;
|
| +
|
| + static inline bool SpaceIsLarge(int space) { return space >= kLargeData; }
|
| + static inline bool SpaceIsPaged(int space) {
|
| + return space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE;
|
| + }
|
| };
|
|
|
|
|
| int SnapshotByteSource::GetInt() {
|
| - // This way of variable-length encoding integers does not suffer from branch
|
| - // mispredictions.
|
| - uint32_t answer = GetUnalignedInt();
|
| - int bytes = answer & 3;
|
| - Advance(bytes);
|
| - uint32_t mask = 0xffffffffu;
|
| - mask >>= 32 - (bytes << 3);
|
| - answer &= mask;
|
| - answer >>= 2;
|
| - return answer;
|
| + // A little unwind to catch the really small ints.
|
| + int snapshot_byte = Get();
|
| + if ((snapshot_byte & 0x80) == 0) {
|
| + return snapshot_byte;
|
| + }
|
| + int accumulator = (snapshot_byte & 0x7f) << 7;
|
| + while (true) {
|
| + snapshot_byte = Get();
|
| + if ((snapshot_byte & 0x80) == 0) {
|
| + return accumulator | snapshot_byte;
|
| + }
|
| + accumulator = (accumulator | (snapshot_byte & 0x7f)) << 7;
|
| + }
|
| + UNREACHABLE();
|
| + return accumulator;
|
| }
|
|
|
|
|
| @@ -328,12 +340,6 @@ class Deserializer: public SerializerDeserializer {
|
| // Deserialize a single object and the objects reachable from it.
|
| void DeserializePartial(Object** root);
|
|
|
| - void set_reservation(int space_number, int reservation) {
|
| - ASSERT(space_number >= 0);
|
| - ASSERT(space_number <= LAST_SPACE);
|
| - reservations_[space_number] = reservation;
|
| - }
|
| -
|
| private:
|
| virtual void VisitPointers(Object** start, Object** end);
|
|
|
| @@ -352,36 +358,28 @@ class Deserializer: public SerializerDeserializer {
|
| // the heap.
|
| void ReadChunk(
|
| Object** start, Object** end, int space, Address object_address);
|
| - void ReadObject(int space_number, Object** write_back);
|
| -
|
| - // This routine both allocates a new object, and also keeps
|
| - // track of where objects have been allocated so that we can
|
| - // fix back references when deserializing.
|
| - Address Allocate(int space_index, int size) {
|
| - Address address = high_water_[space_index];
|
| - high_water_[space_index] = address + size;
|
| - return address;
|
| - }
|
| -
|
| - // This returns the address of an object that has been described in the
|
| - // snapshot as being offset bytes back in a particular space.
|
| - HeapObject* GetAddressFromEnd(int space) {
|
| - int offset = source_->GetInt();
|
| - offset <<= kObjectAlignmentBits;
|
| - return HeapObject::FromAddress(high_water_[space] - offset);
|
| - }
|
| -
|
| + HeapObject* GetAddressFromStart(int space);
|
| + inline HeapObject* GetAddressFromEnd(int space);
|
| + Address Allocate(int space_number, Space* space, int size);
|
| + void ReadObject(int space_number, Space* space, Object** write_back);
|
|
|
| // Cached current isolate.
|
| Isolate* isolate_;
|
|
|
| + // Keep track of the pages in the paged spaces.
|
| + // (In large object space we are keeping track of individual objects
|
| + // rather than pages.) In new space we just need the address of the
|
| + // first object and the others will flow from that.
|
| + List<Address> pages_[SerializerDeserializer::kNumberOfSpaces];
|
| +
|
| SnapshotByteSource* source_;
|
| // This is the address of the next object that will be allocated in each
|
| // space. It is used to calculate the addresses of back-references.
|
| Address high_water_[LAST_SPACE + 1];
|
| -
|
| - int reservations_[LAST_SPACE + 1];
|
| - static const intptr_t kUninitializedReservation = -1;
|
| + // This is the address of the most recent object that was allocated. It
|
| + // is used to set the location of the new page when we encounter a
|
| + // START_NEW_PAGE_SERIALIZATION tag.
|
| + Address last_object_address_;
|
|
|
| ExternalReferenceDecoder* external_reference_decoder_;
|
|
|
| @@ -463,7 +461,7 @@ class Serializer : public SerializerDeserializer {
|
| // You can call this after serialization to find out how much space was used
|
| // in each space.
|
| int CurrentAllocationAddress(int space) {
|
| - ASSERT(space < kNumberOfSpaces);
|
| + if (SpaceIsLarge(space)) return large_object_total_;
|
| return fullness_[space];
|
| }
|
|
|
| @@ -480,11 +478,8 @@ class Serializer : public SerializerDeserializer {
|
| static void TooLateToEnableNow() { too_late_to_enable_now_ = true; }
|
| static bool enabled() { return serialization_enabled_; }
|
| SerializationAddressMapper* address_mapper() { return &address_mapper_; }
|
| - void PutRoot(int index,
|
| - HeapObject* object,
|
| - HowToCode how,
|
| - WhereToPoint where,
|
| - int skip);
|
| + void PutRoot(
|
| + int index, HeapObject* object, HowToCode how, WhereToPoint where);
|
|
|
| protected:
|
| static const int kInvalidRootIndex = -1;
|
| @@ -508,9 +503,7 @@ class Serializer : public SerializerDeserializer {
|
| object_(HeapObject::cast(o)),
|
| sink_(sink),
|
| reference_representation_(how_to_code + where_to_point),
|
| - bytes_processed_so_far_(0),
|
| - code_object_(o->IsCode()),
|
| - code_has_been_output_(false) { }
|
| + bytes_processed_so_far_(0) { }
|
| void Serialize();
|
| void VisitPointers(Object** start, Object** end);
|
| void VisitEmbeddedPointer(RelocInfo* target);
|
| @@ -530,36 +523,34 @@ class Serializer : public SerializerDeserializer {
|
| }
|
|
|
| private:
|
| - enum ReturnSkip { kCanReturnSkipInsteadOfSkipping, kIgnoringReturn };
|
| - // This function outputs or skips the raw data between the last pointer and
|
| - // up to the current position. It optionally can just return the number of
|
| - // bytes to skip instead of performing a skip instruction, in case the skip
|
| - // can be merged into the next instruction.
|
| - int OutputRawData(Address up_to, ReturnSkip return_skip = kIgnoringReturn);
|
| + void OutputRawData(Address up_to);
|
|
|
| Serializer* serializer_;
|
| HeapObject* object_;
|
| SnapshotByteSink* sink_;
|
| int reference_representation_;
|
| int bytes_processed_so_far_;
|
| - bool code_object_;
|
| - bool code_has_been_output_;
|
| };
|
|
|
| virtual void SerializeObject(Object* o,
|
| HowToCode how_to_code,
|
| - WhereToPoint where_to_point,
|
| - int skip) = 0;
|
| + WhereToPoint where_to_point) = 0;
|
| void SerializeReferenceToPreviousObject(
|
| int space,
|
| int address,
|
| HowToCode how_to_code,
|
| - WhereToPoint where_to_point,
|
| - int skip);
|
| + WhereToPoint where_to_point);
|
| void InitializeAllocators();
|
| - // This will return the space for an object.
|
| + // This will return the space for an object. If the object is in large
|
| + // object space it may return kLargeCode or kLargeFixedArray in order
|
| + // to indicate to the deserializer what kind of large object allocation
|
| + // to make.
|
| static int SpaceOfObject(HeapObject* object);
|
| - int Allocate(int space, int size);
|
| + // This just returns the space of the object. It will return LO_SPACE
|
| + // for all large objects since you can't check the type of the object
|
| + // once the map has been used for the serialization address.
|
| + static int SpaceOfAlreadySerializedObject(HeapObject* object);
|
| + int Allocate(int space, int size, bool* new_page_started);
|
| int EncodeExternalReference(Address addr) {
|
| return external_reference_encoder_->Encode(addr);
|
| }
|
| @@ -568,7 +559,9 @@ class Serializer : public SerializerDeserializer {
|
|
|
| Isolate* isolate_;
|
| // Keep track of the fullness of each space in order to generate
|
| - // relative addresses for back references.
|
| + // relative addresses for back references. Large objects are
|
| + // just numbered sequentially since relative addresses make no
|
| + // sense in large object space.
|
| int fullness_[LAST_SPACE + 1];
|
| SnapshotByteSink* sink_;
|
| int current_root_index_;
|
| @@ -576,9 +569,9 @@ class Serializer : public SerializerDeserializer {
|
| static bool serialization_enabled_;
|
| // Did we already make use of the fact that serialization was not enabled?
|
| static bool too_late_to_enable_now_;
|
| + int large_object_total_;
|
| SerializationAddressMapper address_mapper_;
|
| intptr_t root_index_wave_front_;
|
| - void Pad();
|
|
|
| friend class ObjectSerializer;
|
| friend class Deserializer;
|
| @@ -601,8 +594,7 @@ class PartialSerializer : public Serializer {
|
| virtual void Serialize(Object** o);
|
| virtual void SerializeObject(Object* o,
|
| HowToCode how_to_code,
|
| - WhereToPoint where_to_point,
|
| - int skip);
|
| + WhereToPoint where_to_point);
|
|
|
| protected:
|
| virtual int PartialSnapshotCacheIndex(HeapObject* o);
|
| @@ -640,13 +632,11 @@ class StartupSerializer : public Serializer {
|
| virtual void SerializeStrongReferences();
|
| virtual void SerializeObject(Object* o,
|
| HowToCode how_to_code,
|
| - WhereToPoint where_to_point,
|
| - int skip);
|
| + WhereToPoint where_to_point);
|
| void SerializeWeakReferences();
|
| void Serialize() {
|
| SerializeStrongReferences();
|
| SerializeWeakReferences();
|
| - Pad();
|
| }
|
|
|
| private:
|
|
|