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: |