Chromium Code Reviews| Index: src/serialize.h |
| =================================================================== |
| --- src/serialize.h (revision 3115) |
| +++ src/serialize.h (working copy) |
| @@ -262,8 +262,19 @@ |
| // A Deserializer reads a snapshot and reconstructs the Object graph it defines. |
| -class Deserializer: public ObjectVisitor { |
| + |
| +// TODO(erikcorry): Get rid of this superclass when we are using the new |
| +// snapshot code exclusively. |
| +class GenericDeserializer: public ObjectVisitor { |
| public: |
| + virtual void GetLog() = 0; |
| + virtual void Deserialize() = 0; |
| +}; |
| + |
| + |
| +// TODO(erikcorry): Get rid of this class. |
| +class Deserializer: public GenericDeserializer { |
| + public: |
| // Create a deserializer. The snapshot is held in str and has size len. |
| Deserializer(const byte* str, int len); |
| @@ -339,6 +350,221 @@ |
| DISALLOW_COPY_AND_ASSIGN(Deserializer); |
| }; |
| + |
| +class SnapshotByteSource { |
| + public: |
| + SnapshotByteSource(const byte* array, int length) |
|
Mads Ager (chromium)
2009/10/26 11:14:05
Please add spaces between the methods in this clas
|
| + : data_(array), length_(length), position_(0) { } |
| + bool HasMore() { return position_ < length_; } |
| + int Get() { |
| + ASSERT(position_ < length_); |
| + return data_[position_++]; |
| + } |
| + int GetInt() { |
| + // A little unwind to catch the really small ints. |
| + int snapshot_byte = Get(); |
| + if ((snapshot_byte & 0x80) == 0) { |
| + return snapshot_byte; |
| + } |
| + uintptr_t 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; |
| + } |
| + return accumulator; |
|
Mads Ager (chromium)
2009/10/26 11:14:05
Put an UNREACHABLE() in front of this return as do
|
| + } |
| + bool AtEOF() { |
| + return position_ == length_; |
| + } |
| + |
| + private: |
| + const byte* data_; |
| + int length_; |
| + int position_; |
| +}; |
| + |
| + |
| +// The SerDes class is a common superclass for Serializer2 and Deserializer2 |
| +// which is used to store common constants and methods used by both. |
| +// TODO(erikcorry): This should inherit from ObjectVisitor. |
| +class SerDes: public GenericDeserializer { |
| + protected: |
| + enum DataType { |
| + SMI_SERIALIZATION, |
| + RAW_DATA_SERIALIZATION, |
| + OBJECT_SERIALIZATION, |
| + CODE_OBJECT_SERIALIZATION, |
| + BACKREF_SERIALIZATION, |
| + CODE_BACKREF_SERIALIZATION, |
| + EXTERNAL_REFERENCE_SERIALIZATION, |
| + SYNCHRONIZE |
| + }; |
| + static const int kSmiBias = 16; |
|
Mads Ager (chromium)
2009/10/26 11:14:05
Could you add a comment about the bias?
|
| + 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 inline bool SpaceIsLarge(int space) { return space >= kLargeData; } |
| + static inline bool SpaceIsPaged(int space) { |
| + return space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE; |
| + } |
| +}; |
| + |
| + |
| + |
| +// A Deserializer reads a snapshot and reconstructs the Object graph it defines. |
| +class Deserializer2: public SerDes { |
| + public: |
| + // Create a deserializer. The snapshot is held in str and has size len. |
|
Mads Ager (chromium)
2009/10/26 11:14:05
Create a deserializer from a byte source? The res
|
| + explicit Deserializer2(SnapshotByteSource* source); |
| + |
| + virtual ~Deserializer2() { } |
| + |
| + // Deserialize the snapshot into an empty heap. |
| + void Deserialize(); |
| + void GetLog() { } // TODO(erikcorry): Get rid of this. |
| +#ifdef DEBUG |
| + virtual void Synchronize(const char* tag); |
| +#endif |
| + |
| + private: |
| + virtual void VisitPointers(Object** start, Object** end); |
| + virtual void VisitExternalReferences(Address* start, Address* end) { |
|
Mads Ager (chromium)
2009/10/26 11:14:05
I would add space before and after the methods tha
|
| + UNREACHABLE(); |
| + } |
| + virtual void VisitRuntimeEntry(RelocInfo* rinfo) { |
| + UNREACHABLE(); |
| + } |
| + int CurrentAllocationAddress(int space) { |
| + // The three different kinds of large objects have different tags in the |
| + // snapshot so the deserializer knows which kind of object to allocate, |
| + // but they share a fullness_ entry. |
| + if (SpaceIsLarge(space)) space = LO_SPACE; |
| + return fullness_[space]; |
| + } |
| + |
| + HeapObject* GetAddress(int space); |
| + Address Allocate(int space, int size); |
| + bool ReadObject(Object** write_back); |
| + |
| + // 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_[SerDes::kNumberOfSpaces]; |
| + |
| + SnapshotByteSource* source_; |
| + ExternalReferenceDecoder* external_reference_decoder_; |
| + // 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. |
| + int fullness_[LAST_SPACE + 1]; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Deserializer2); |
| +}; |
| + |
| + |
| +class SnapshotByteSink { |
| + public: |
| + virtual ~SnapshotByteSink() { } |
| + virtual void Put(int byte, const char* description) = 0; |
| + void PutInt(uintptr_t integer, const char* description) { |
| + const int max_shift = ((kPointerSize * kBitsPerByte) / 7) * 7; |
|
Mads Ager (chromium)
2009/10/26 11:14:05
Move to implementation file?
|
| + for (int shift = max_shift; shift > 0; shift -= 7) { |
| + if (integer >= 1u << shift) { |
| + Put(((integer >> shift) & 0x7f) | 0x80, "intpart"); |
| + } |
| + } |
| + Put(integer & 0x7f, "intlastpart"); |
| + } |
| +}; |
| + |
| + |
| +class Serializer2 : public SerDes { |
| + public: |
| + explicit Serializer2(SnapshotByteSink* sink); |
| + // Serialize the current state of the heap. This operation destroys the |
| + // heap contents. |
| + void Serialize(); |
| + void VisitPointers(Object** start, Object** end); |
| + void Finalize(int* y) {} |
|
Mads Ager (chromium)
2009/10/26 11:14:05
Add a comment? What does Finalize do? What is y?
|
| + void GetLog() { } // TODO(erikcorry): Get rid of this. |
| + void Deserialize() { } // TODO(erikcorry): Get rid of this. |
| +#ifdef DEBUG |
| + virtual void Synchronize(const char* tag); |
| +#endif |
| + |
| + private: |
| + enum ReferenceRepresentation { |
| + TAGGED_REPRESENTATION, // Deserialize as a tagged object reference. |
|
Mads Ager (chromium)
2009/10/26 11:14:05
How about just "Tagged object reference."?
|
| + CODE_TARGET_REPRESENTATION // Deserialize a reference to first instruction. |
|
Mads Ager (chromium)
2009/10/26 11:14:05
How about just "Reference to first instruction in
|
| + }; |
| + class ObjectSerializer : public ObjectVisitor { |
| + public: |
| + ObjectSerializer(Serializer2* serializer, |
| + Object* o, |
| + SnapshotByteSink* sink, |
| + ReferenceRepresentation representation) |
| + : serializer_(serializer), |
| + object_(HeapObject::cast(o)), |
| + sink_(sink), |
| + reference_representation_(representation), |
| + bytes_processed_so_far_(0) { } |
| + void Serialize(); |
| + void VisitPointers(Object** start, Object** end); |
| + void VisitExternalReferences(Address* start, Address* end); |
| + void VisitCodeTarget(RelocInfo* target); |
| + |
| + private: |
| + void OutputRawData(Address up_to); |
| + |
| + Serializer2* serializer_; |
| + HeapObject* object_; |
| + SnapshotByteSink* sink_; |
| + ReferenceRepresentation reference_representation_; |
| + int bytes_processed_so_far_; |
| + }; |
| + |
| + void SerializeObject(Object* o, ReferenceRepresentation representation); |
| + 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. |
| + 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); |
| + int CurrentAllocationAddress(int space) { |
| + if (SpaceIsLarge(space)) space = LO_SPACE; |
| + return fullness_[space]; |
| + } |
| + int EncodeExternalReference(Address addr) { |
| + return external_reference_encoder_->Encode(addr); |
| + } |
| + |
| + // 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. |
| + int fullness_[LAST_SPACE + 1]; |
| + SnapshotByteSink* sink_; |
| + int current_root_index_; |
| + ExternalReferenceEncoder* external_reference_encoder_; |
| + |
| + friend class ObjectSerializer; |
| + friend class Deserializer2; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Serializer2); |
| +}; |
| + |
| } } // namespace v8::internal |
| #endif // V8_SERIALIZE_H_ |