diff options
Diffstat (limited to 'src/3rdparty/v8/src/serialize.h')
-rw-r--r-- | src/3rdparty/v8/src/serialize.h | 233 |
1 files changed, 121 insertions, 112 deletions
diff --git a/src/3rdparty/v8/src/serialize.h b/src/3rdparty/v8/src/serialize.h index f50e23e..2041792 100644 --- a/src/3rdparty/v8/src/serialize.h +++ b/src/3rdparty/v8/src/serialize.h @@ -170,13 +170,27 @@ 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() { - return position_ == length_; - } + bool AtEOF(); int position() { return position_; } @@ -187,48 +201,31 @@ 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. class SerializerDeserializer: public ObjectVisitor { public: static void Iterate(ObjectVisitor* visitor); - static void SetSnapshotCacheSize(int size); + + static int nop() { return kNop; } protected: // Where the pointed-to object can be found: enum Where { kNewObject = 0, // Object is next in snapshot. - // 1-8 One per space. + // 1-6 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 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. + 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. kPointedToMask = 0x3f }; @@ -240,17 +237,27 @@ 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, - kFirstInstruction = 0x80, + kInnerPointer = 0x80, // First insn in code object or payload of cell. kWhereToPointMask = 0x80 }; // Misc. - // Raw data to be copied from the snapshot. - static const int kRawData = 0x30; - // Some common raw lengths: 0x31-0x3f + // 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. // 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. @@ -260,64 +267,44 @@ 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 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 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 int CodeForRepeats(int repeats) { ASSERT(repeats >= 1 && repeats <= kMaxRepeats); - return 0x73 + repeats; + return 0x72 + repeats; } static int RepeatsForCode(int byte_code) { ASSERT(byte_code >= kConstantRepeat && byte_code <= 0x7f); - return byte_code - 0x73; + return byte_code - 0x72; } - 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 kRootArrayConstants = 0xa0; + // 0xa0-0xbf Things from the first 32 elements of the root array. static const int kRootArrayNumberOfConstantEncodings = 0x20; - static const int kRootArrayNumberOfLowConstantEncodings = 0x10; static int RootArrayConstantFromByteCode(int byte_code) { - int constant = (byte_code & 0xf) | ((byte_code & 0x40) >> 2); - ASSERT(constant >= 0 && constant < kRootArrayNumberOfConstantEncodings); - return constant; + return byte_code & 0x1f; } - - 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 kNumberOfSpaces = LO_SPACE; static const int kAnyOldSpace = -1; // A bitmask for getting the space out of an instruction. - 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; - } + static const int kSpaceMask = 7; }; int SnapshotByteSource::GetInt() { - // 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; + // 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; } @@ -341,6 +328,12 @@ 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); @@ -359,28 +352,36 @@ class Deserializer: public SerializerDeserializer { // the heap. void ReadChunk( Object** start, Object** end, int space, Address object_address); - 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); + 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); + } + // 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]; - // 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_; + + int reservations_[LAST_SPACE + 1]; + static const intptr_t kUninitializedReservation = -1; ExternalReferenceDecoder* external_reference_decoder_; @@ -462,7 +463,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) { - if (SpaceIsLarge(space)) return large_object_total_; + ASSERT(space < kNumberOfSpaces); return fullness_[space]; } @@ -479,8 +480,11 @@ 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); + void PutRoot(int index, + HeapObject* object, + HowToCode how, + WhereToPoint where, + int skip); protected: static const int kInvalidRootIndex = -1; @@ -504,7 +508,9 @@ class Serializer : public SerializerDeserializer { object_(HeapObject::cast(o)), sink_(sink), reference_representation_(how_to_code + where_to_point), - bytes_processed_so_far_(0) { } + bytes_processed_so_far_(0), + code_object_(o->IsCode()), + code_has_been_output_(false) { } void Serialize(); void VisitPointers(Object** start, Object** end); void VisitEmbeddedPointer(RelocInfo* target); @@ -524,34 +530,36 @@ class Serializer : public SerializerDeserializer { } private: - void OutputRawData(Address up_to); + 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); 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) = 0; + WhereToPoint where_to_point, + int skip) = 0; void SerializeReferenceToPreviousObject( int space, int address, HowToCode how_to_code, - WhereToPoint where_to_point); + WhereToPoint where_to_point, + int skip); void InitializeAllocators(); - // 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. + // This will return the space for an object. static int SpaceOfObject(HeapObject* object); - // 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 Allocate(int space, int size); int EncodeExternalReference(Address addr) { return external_reference_encoder_->Encode(addr); } @@ -560,9 +568,7 @@ class Serializer : public SerializerDeserializer { Isolate* isolate_; // Keep track of the fullness of each space in order to generate - // relative addresses for back references. Large objects are - // just numbered sequentially since relative addresses make no - // sense in large object space. + // relative addresses for back references. int fullness_[LAST_SPACE + 1]; SnapshotByteSink* sink_; int current_root_index_; @@ -570,9 +576,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; @@ -595,7 +601,8 @@ class PartialSerializer : public Serializer { virtual void Serialize(Object** o); virtual void SerializeObject(Object* o, HowToCode how_to_code, - WhereToPoint where_to_point); + WhereToPoint where_to_point, + int skip); protected: virtual int PartialSnapshotCacheIndex(HeapObject* o); @@ -633,11 +640,13 @@ class StartupSerializer : public Serializer { virtual void SerializeStrongReferences(); virtual void SerializeObject(Object* o, HowToCode how_to_code, - WhereToPoint where_to_point); + WhereToPoint where_to_point, + int skip); void SerializeWeakReferences(); void Serialize() { SerializeStrongReferences(); SerializeWeakReferences(); + Pad(); } private: |