Chromium Code Reviews| Index: src/serialize.h |
| diff --git a/src/serialize.h b/src/serialize.h |
| index 71b274b330e20f535fa2a3bd93389337fdbf2251..76eb34e3d26e07aa4a87a85ea0489a1bfae53bf0 100644 |
| --- a/src/serialize.h |
| +++ b/src/serialize.h |
| @@ -148,11 +148,15 @@ class SerializerDeserializer: public ObjectVisitor { |
| static int nop() { return kNop; } |
| + // No reservation for large object space necessary. |
| + static const int kNumberOfReservedSpaces = LO_SPACE; |
| + static const int kNumberOfSpaces = INVALID_SPACE; |
| + |
| protected: |
| // Where the pointed-to object can be found: |
| enum Where { |
| kNewObject = 0, // Object is next in snapshot. |
| - // 1-6 One per space. |
| + // 1-7 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. |
| @@ -161,9 +165,9 @@ class SerializerDeserializer: public ObjectVisitor { |
| kAttachedReference = 0xe, // Object is described in an attached list. |
| kNop = 0xf, // Does nothing, used to pad. |
| kBackref = 0x10, // Object is described relative to end. |
| - // 0x11-0x16 One per space. |
| + // 0x11-0x17 One per space. |
| kBackrefWithSkip = 0x18, // Object is described relative to end. |
| - // 0x19-0x1e One per space. |
| + // 0x19-0x1f One per space. |
| // 0x20-0x3f Used by misc. tags below. |
| kPointedToMask = 0x3f |
| }; |
| @@ -225,11 +229,11 @@ class SerializerDeserializer: public ObjectVisitor { |
| return byte_code & 0x1f; |
| } |
| - 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 = 7; |
| + STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1); |
| }; |
| @@ -249,10 +253,14 @@ class Deserializer: public SerializerDeserializer { |
| void set_reservation(int space_number, int reservation) { |
| DCHECK(space_number >= 0); |
| - DCHECK(space_number <= LAST_SPACE); |
| + DCHECK(space_number < kNumberOfReservedSpaces); |
| reservations_[space_number] = reservation; |
| } |
| + void set_large_objects_total_size(int size) { |
| + large_objects_total_size_ = size; |
| + } |
| + |
| void FlushICacheForNewCodeObjects(); |
| // Serialized user code reference certain objects that are provided in a list |
| @@ -287,19 +295,33 @@ class Deserializer: public SerializerDeserializer { |
| HeapObject* ProcessNewObjectFromSerializedCode(HeapObject* obj); |
| Object* ProcessBackRefInSerializedCode(Object* obj); |
| - // 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. |
| + // We know the space requirements before deserialization and can |
| + // pre-allocate that reserved space. During deserialization, all we need |
| + // to do is to bump up the pointer for each space in the reserved |
| + // space. This is also used for fixing back references. |
| + // Since multiple large objects cannot be folded into one large object |
| + // space allocation, we have to do an actual allocation when deserializing |
| + // each allocation. Instead of tracking offset for back references, we |
| + // reference large objects by index. |
| Address Allocate(int space_index, int size) { |
| - Address address = high_water_[space_index]; |
| - high_water_[space_index] = address + size; |
| - return address; |
| + if (space_index == LO_SPACE) { |
| + Executability exec = static_cast<Executability>(source_->GetInt()); |
| + HeapObject* obj = isolate_->heap()->ForceAllocateLargeObject(size, exec); |
| + deserialized_large_objects_.Add(obj); |
| + return obj->address(); |
| + } else { |
| + DCHECK(space_index < kNumberOfReservedSpaces); |
| + 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(); |
| + if (space == LO_SPACE) return deserialized_large_objects_[offset]; |
| offset <<= kObjectAlignmentBits; |
| return HeapObject::FromAddress(high_water_[space] - offset); |
| } |
| @@ -313,13 +335,16 @@ class Deserializer: public SerializerDeserializer { |
| 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]; |
| + Address high_water_[kNumberOfReservedSpaces]; |
| - int reservations_[LAST_SPACE + 1]; |
| + int reservations_[kNumberOfReservedSpaces]; |
| static const intptr_t kUninitializedReservation = -1; |
| ExternalReferenceDecoder* external_reference_decoder_; |
| + List<HeapObject*> deserialized_large_objects_; |
| + int large_objects_total_size_; |
| + |
| DISALLOW_COPY_AND_ASSIGN(Deserializer); |
| }; |
| @@ -383,7 +408,8 @@ 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) const { |
| - DCHECK(space < kNumberOfSpaces); |
| + if (space == LO_SPACE) return 0; |
| + DCHECK(space < kNumberOfReservedSpaces); |
| return fullness_[space]; |
| } |
| @@ -396,6 +422,8 @@ class Serializer : public SerializerDeserializer { |
| WhereToPoint where, |
| int skip); |
| + int large_objects_total_size() const { return large_objects_total_size_; } |
| + |
| protected: |
| static const int kInvalidRootIndex = -1; |
| @@ -466,6 +494,7 @@ class Serializer : public SerializerDeserializer { |
| void InitializeAllocators(); |
| // This will return the space for an object. |
| static int SpaceOfObject(HeapObject* object); |
| + int AllocateLargeObject(int size); |
| int Allocate(int space, int size); |
| int EncodeExternalReference(Address addr) { |
| return external_reference_encoder_->Encode(addr); |
| @@ -480,7 +509,7 @@ class Serializer : public SerializerDeserializer { |
| Isolate* isolate_; |
| // Keep track of the fullness of each space in order to generate |
| // relative addresses for back references. |
| - int fullness_[LAST_SPACE + 1]; |
| + int fullness_[kNumberOfReservedSpaces]; |
| SnapshotByteSink* sink_; |
| ExternalReferenceEncoder* external_reference_encoder_; |
| @@ -497,6 +526,8 @@ class Serializer : public SerializerDeserializer { |
| private: |
| CodeAddressMap* code_address_map_; |
| + int seen_large_objects_index_; |
|
mvstanton
2014/09/22 14:32:14
A comment on the meaning of seen_large_objects_ind
|
| + int large_objects_total_size_; |
| DISALLOW_COPY_AND_ASSIGN(Serializer); |
| }; |
| @@ -667,6 +698,10 @@ class SerializedCodeData { |
| return GetHeaderValue(kReservationsOffset + space); |
| } |
| + int GetLargeObjectsTotalSize() const { |
| + return GetHeaderValue(kLargeObjectsTotalSizeOffset); |
| + } |
| + |
| private: |
| void SetHeaderValue(int offset, int value) { |
| reinterpret_cast<int*>(const_cast<byte*>(script_data_->data()))[offset] = |
| @@ -689,10 +724,11 @@ class SerializedCodeData { |
| static const int kCheckSumOffset = 0; |
| static const int kNumCodeStubKeysOffset = 1; |
| static const int kPayloadLengthOffset = 2; |
| - static const int kReservationsOffset = 3; |
| + static const int kLargeObjectsTotalSizeOffset = 3; |
| + static const int kReservationsOffset = 4; |
| - static const int kNumSpaces = PROPERTY_CELL_SPACE - NEW_SPACE + 1; |
| - static const int kHeaderEntries = kReservationsOffset + kNumSpaces; |
| + static const int kHeaderEntries = |
| + kReservationsOffset + SerializerDeserializer::kNumberOfReservedSpaces; |
| static const int kHeaderSize = kHeaderEntries * kIntSize; |
| // Following the header, we store, in sequential order |