diff options
Diffstat (limited to 'deps/v8/src/serialize.h')
-rw-r--r-- | deps/v8/src/serialize.h | 405 |
1 files changed, 115 insertions, 290 deletions
diff --git a/deps/v8/src/serialize.h b/deps/v8/src/serialize.h index cefff78cac..96bd751da9 100644 --- a/deps/v8/src/serialize.h +++ b/deps/v8/src/serialize.h @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// Copyright 2006-2009 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -108,249 +108,6 @@ class ExternalReferenceDecoder { }; -// A Serializer recursively visits objects to construct a serialized -// representation of the Heap stored in a string. Serialization is -// destructive. We use a similar mechanism to the GC to ensure that -// each object is visited once, namely, we modify the map pointer of -// each visited object to contain the relative address in the -// appropriate space where that object will be allocated when the heap -// is deserialized. - - -// Helper classes defined in serialize.cc. -class RelativeAddress; -class SimulatedHeapSpace; -class SnapshotWriter; -class ReferenceUpdater; - - -class Serializer: public ObjectVisitor { - public: - Serializer(); - - virtual ~Serializer(); - - // Serialize the current state of the heap. This operation destroys the - // heap contents and the contents of the roots into the heap. - void Serialize(); - - // Returns the serialized buffer. Ownership is transferred to the - // caller. Only the destructor and getters may be called after this call. - void Finalize(byte** str, int* len); - - int roots() { return roots_; } - int objects() { return objects_; } - -#ifdef DEBUG - // insert "tag" into the serialized stream - virtual void Synchronize(const char* tag); -#endif - - static bool enabled() { return serialization_enabled_; } - - static void Enable() { serialization_enabled_ = true; } - static void Disable() { serialization_enabled_ = false; } - - private: - friend class ReferenceUpdater; - - virtual void VisitPointers(Object** start, Object** end); - virtual void VisitCodeTarget(RelocInfo* rinfo); - bool IsVisited(HeapObject* obj); - - Address GetSavedAddress(HeapObject* obj); - - void SaveAddress(HeapObject* obj, Address addr); - - void PutEncodedAddress(Address addr); - // Write the global flags into the file. - void PutFlags(); - // Write global information into the header of the file. - void PutHeader(); - // Write the contents of the log into the file. - void PutLog(); - // Serialize 'obj', and return its encoded RelativeAddress. - Address PutObject(HeapObject* obj); - // Write a stack of handles to the file bottom first. - void PutGlobalHandleStack(const List<Handle<Object> >& stack); - // Write the context stack into the file. - void PutContextStack(); - - // Return the encoded RelativeAddress where this object will be - // allocated on deserialization. On the first visit of 'o', - // serialize its contents. On return, *serialized will be true iff - // 'o' has just been serialized. - Address Encode(Object* o, bool* serialized); - - // Simulate the allocation of 'obj', returning the address where it will - // be allocated on deserialization - RelativeAddress Allocate(HeapObject* obj); - - void InitializeAllocators(); - - SnapshotWriter* writer_; - bool root_; // serializing a root? - int roots_; // number of roots visited - int objects_; // number of objects serialized - - static bool serialization_enabled_; - - int flags_end_; // The position right after the flags. - - // An array of per-space SimulatedHeapSpaces used as memory allocators. - SimulatedHeapSpace* allocator_[LAST_SPACE+1]; - // A list of global handles at serialization time. - List<Object**> global_handles_; - - ExternalReferenceEncoder* reference_encoder_; - - HashMap saved_addresses_; - - DISALLOW_COPY_AND_ASSIGN(Serializer); -}; - -// Helper class to read the bytes of the serialized heap. - -class SnapshotReader { - public: - SnapshotReader(const byte* str, int len): str_(str), end_(str + len) {} - - void ExpectC(char expected) { - int c = GetC(); - USE(c); - ASSERT(c == expected); - } - - int GetC() { - if (str_ >= end_) return EOF; - return *str_++; - } - - int GetInt() { - int result; - GetBytes(reinterpret_cast<Address>(&result), sizeof(result)); - return result; - } - - Address GetAddress() { - Address result; - GetBytes(reinterpret_cast<Address>(&result), sizeof(result)); - return result; - } - - void GetBytes(Address a, int size) { - ASSERT(str_ + size <= end_); - memcpy(a, str_, size); - str_ += size; - } - - char* GetString() { - ExpectC('['); - int size = GetInt(); - ExpectC(']'); - char* s = NewArray<char>(size + 1); - GetBytes(reinterpret_cast<Address>(s), size); - s[size] = 0; - return s; - } - - private: - const byte* str_; - const byte* end_; -}; - - -// A Deserializer reads a snapshot and reconstructs the Object graph it defines. - - -// 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); - - virtual ~Deserializer(); - - // Read the flags from the header of the file, and set those that - // should be inherited from the snapshot. - void GetFlags(); - - // Read saved profiling information from the file and log it if required. - void GetLog(); - - // Deserialize the snapshot into an empty heap. - void Deserialize(); - - int roots() { return roots_; } - int objects() { return objects_; } - -#ifdef DEBUG - // Check for the presence of "tag" in the serialized stream - virtual void Synchronize(const char* tag); -#endif - - private: - virtual void VisitPointers(Object** start, Object** end); - virtual void VisitCodeTarget(RelocInfo* rinfo); - virtual void VisitExternalReferences(Address* start, Address* end); - virtual void VisitRuntimeEntry(RelocInfo* rinfo); - - Address GetEncodedAddress(); - - // Read other global information (except flags) from the header of the file. - void GetHeader(); - // Read a stack of handles from the file bottom first. - void GetGlobalHandleStack(List<Handle<Object> >* stack); - // Read the context stack from the file. - void GetContextStack(); - - Object* GetObject(); - - // Get the encoded address. In debug mode we make sure - // it matches the given expectations. - void ExpectEncodedAddress(Address expected); - - // Given an encoded address (the result of - // RelativeAddress::Encode), return the object to which it points, - // which will be either an Smi or a HeapObject in the current heap. - Object* Resolve(Address encoded_address); - - SnapshotReader reader_; - bool root_; // Deserializing a root? - int roots_; // number of roots visited - int objects_; // number of objects serialized - - bool has_log_; // The file has log information. - - // Resolve caches the following: - List<Page*> map_pages_; // All pages in the map space. - List<Page*> cell_pages_; // All pages in the cell space. - List<Page*> old_pointer_pages_; // All pages in the old pointer space. - List<Page*> old_data_pages_; // All pages in the old data space. - List<Page*> code_pages_; // All pages in the code space. - List<Object*> large_objects_; // All known large objects. - // A list of global handles at deserialization time. - List<Object**> global_handles_; - - ExternalReferenceDecoder* reference_decoder_; - -#ifdef DEBUG - bool expect_debug_information_; -#endif - - DISALLOW_COPY_AND_ASSIGN(Deserializer); -}; - - class SnapshotByteSource { public: SnapshotByteSource(const byte* array, int length) @@ -363,13 +120,18 @@ class SnapshotByteSource { return data_[position_++]; } + void CopyRaw(byte* to, int number_of_bytes) { + memcpy(to, data_ + position_, number_of_bytes); + position_ += number_of_bytes; + } + 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; + int accumulator = (snapshot_byte & 0x7f) << 7; while (true) { snapshot_byte = Get(); if ((snapshot_byte & 0x80) == 0) { @@ -392,30 +154,72 @@ class SnapshotByteSource { }; -// The SerDes class is a common superclass for Serializer2 and Deserializer2 +// It is very common to have a reference to the object at word 10 in space 2, +// the object at word 5 in space 2 and the object at word 28 in space 4. This +// only works for objects in the first page of a space. +#define COMMON_REFERENCE_PATTERNS(f) \ + f(kNumberOfSpaces, 2, 10) \ + f(kNumberOfSpaces + 1, 2, 5) \ + f(kNumberOfSpaces + 2, 4, 28) \ + f(kNumberOfSpaces + 3, 2, 21) \ + f(kNumberOfSpaces + 4, 2, 98) \ + f(kNumberOfSpaces + 5, 2, 67) \ + f(kNumberOfSpaces + 6, 4, 132) + +#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 SerDes class is a common superclass for Serializer and Deserializer // which is used to store common constants and methods used by both. -// TODO(erikcorry): This should inherit from ObjectVisitor. -class SerDes: public GenericDeserializer { +class SerDes: public ObjectVisitor { protected: enum DataType { - SMI_SERIALIZATION, - RAW_DATA_SERIALIZATION, - OBJECT_SERIALIZATION, - CODE_OBJECT_SERIALIZATION, - BACKREF_SERIALIZATION, - CODE_BACKREF_SERIALIZATION, - EXTERNAL_REFERENCE_SERIALIZATION, - SYNCHRONIZE + RAW_DATA_SERIALIZATION = 0, + // And 15 common raw lengths. + OBJECT_SERIALIZATION = 16, + // One variant per space. + CODE_OBJECT_SERIALIZATION = 25, + // One per space (only code spaces in use). + EXTERNAL_REFERENCE_SERIALIZATION = 34, + EXTERNAL_BRANCH_TARGET_SERIALIZATION = 35, + SYNCHRONIZE = 36, + START_NEW_PAGE_SERIALIZATION = 37, + NATIVES_STRING_RESOURCE = 38, + // Free: 39-47. + BACKREF_SERIALIZATION = 48, + // One per space, must be kSpaceMask aligned. + // Free: 57-63. + REFERENCE_SERIALIZATION = 64, + // One per space and common references. Must be kSpaceMask aligned. + CODE_BACKREF_SERIALIZATION = 80, + // One per space, must be kSpaceMask aligned. + // Free: 89-95. + CODE_REFERENCE_SERIALIZATION = 96 + // One per space, must be kSpaceMask aligned. + // Free: 105-255. }; - // Our Smi encoding is much more efficient for small positive integers than it - // is for negative numbers so we add a bias before encoding and subtract it - // after encoding so that popular small negative Smis are efficiently encoded. - static const int kSmiBias = 16; static const int kLargeData = LAST_SPACE; static const int kLargeCode = kLargeData + 1; static const int kLargeFixedArray = kLargeCode + 1; static const int kNumberOfSpaces = kLargeFixedArray + 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; @@ -425,16 +229,15 @@ class SerDes: public GenericDeserializer { // A Deserializer reads a snapshot and reconstructs the Object graph it defines. -class Deserializer2: public SerDes { +class Deserializer: public SerDes { public: // Create a deserializer from a snapshot byte source. - explicit Deserializer2(SnapshotByteSource* source); + explicit Deserializer(SnapshotByteSource* source); - virtual ~Deserializer2() { } + virtual ~Deserializer() { } // 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 @@ -450,17 +253,11 @@ class Deserializer2: public SerDes { 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); + void ReadChunk(Object** start, Object** end, int space, Address 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); // Keep track of the pages in the paged spaces. // (In large object space we are keeping track of individual objects @@ -470,13 +267,15 @@ class Deserializer2: public SerDes { 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]; + // 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_; - DISALLOW_COPY_AND_ASSIGN(Deserializer2); + DISALLOW_COPY_AND_ASSIGN(Deserializer); }; @@ -484,19 +283,33 @@ class SnapshotByteSink { public: virtual ~SnapshotByteSink() { } virtual void Put(int byte, const char* description) = 0; + virtual void PutSection(int byte, const char* description) { + Put(byte, description); + } void PutInt(uintptr_t integer, const char* description); }; -class Serializer2 : public SerDes { +class Serializer : public SerDes { public: - explicit Serializer2(SnapshotByteSink* sink); + explicit Serializer(SnapshotByteSink* sink); // Serialize the current state of the heap. This operation destroys the // heap contents. void Serialize(); void VisitPointers(Object** start, Object** end); - void GetLog() { } // TODO(erikcorry): Get rid of this. - void Deserialize() { } // TODO(erikcorry): Get rid of this. + + static void Enable() { + if (!serialization_enabled_) { + ASSERT(!too_late_to_enable_now_); + } + serialization_enabled_ = true; + } + + static void Disable() { serialization_enabled_ = false; } + // Call this when you have made use of the fact that there is no serialization + // going on. + static void TooLateToEnableNow() { too_late_to_enable_now_ = true; } + static bool enabled() { return serialization_enabled_; } #ifdef DEBUG virtual void Synchronize(const char* tag); #endif @@ -508,7 +321,7 @@ class Serializer2 : public SerDes { }; class ObjectSerializer : public ObjectVisitor { public: - ObjectSerializer(Serializer2* serializer, + ObjectSerializer(Serializer* serializer, Object* o, SnapshotByteSink* sink, ReferenceRepresentation representation) @@ -521,11 +334,20 @@ class Serializer2 : public SerDes { void VisitPointers(Object** start, Object** end); void VisitExternalReferences(Address* start, Address* end); void VisitCodeTarget(RelocInfo* target); + void VisitRuntimeEntry(RelocInfo* reloc); + // Used for seralizing the external strings that hold the natives source. + void VisitExternalAsciiString( + v8::String::ExternalAsciiStringResource** resource); + // We can't serialize a heap with external two byte strings. + void VisitExternalTwoByteString( + v8::String::ExternalStringResource** resource) { + UNREACHABLE(); + } private: void OutputRawData(Address up_to); - Serializer2* serializer_; + Serializer* serializer_; HeapObject* object_; SnapshotByteSink* sink_; ReferenceRepresentation reference_representation_; @@ -543,7 +365,7 @@ class Serializer2 : public SerDes { // 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 Allocate(int space, int size, bool* new_page_started); int CurrentAllocationAddress(int space) { if (SpaceIsLarge(space)) space = LO_SPACE; return fullness_[space]; @@ -560,11 +382,14 @@ class Serializer2 : public SerDes { SnapshotByteSink* sink_; int current_root_index_; ExternalReferenceEncoder* external_reference_encoder_; + static bool serialization_enabled_; + // Did we already make use of the fact that serialization was not enabled? + static bool too_late_to_enable_now_; friend class ObjectSerializer; - friend class Deserializer2; + friend class Deserializer; - DISALLOW_COPY_AND_ASSIGN(Serializer2); + DISALLOW_COPY_AND_ASSIGN(Serializer); }; } } // namespace v8::internal |