Index: src/serialize.cc |
=================================================================== |
--- src/serialize.cc (revision 3302) |
+++ src/serialize.cc (working copy) |
@@ -44,350 +44,6 @@ |
namespace v8 { |
namespace internal { |
-// 32-bit encoding: a RelativeAddress must be able to fit in a |
-// pointer: it is encoded as an Address with (from LS to MS bits): |
-// - 2 bits identifying this as a HeapObject. |
-// - 4 bits to encode the AllocationSpace (including special values for |
-// code and fixed arrays in LO space) |
-// - 27 bits identifying a word in the space, in one of three formats: |
-// - paged spaces: 16 bits of page number, 11 bits of word offset in page |
-// - NEW space: 27 bits of word offset |
-// - LO space: 27 bits of page number |
- |
-const int kSpaceShift = kHeapObjectTagSize; |
-const int kSpaceBits = 4; |
-const int kSpaceMask = (1 << kSpaceBits) - 1; |
- |
-const int kOffsetShift = kSpaceShift + kSpaceBits; |
-const int kOffsetBits = 11; |
-const int kOffsetMask = (1 << kOffsetBits) - 1; |
- |
-const int kPageShift = kOffsetShift + kOffsetBits; |
-const int kPageBits = 32 - (kOffsetBits + kSpaceBits + kHeapObjectTagSize); |
-const int kPageMask = (1 << kPageBits) - 1; |
- |
-const int kPageAndOffsetShift = kOffsetShift; |
-const int kPageAndOffsetBits = kPageBits + kOffsetBits; |
-const int kPageAndOffsetMask = (1 << kPageAndOffsetBits) - 1; |
- |
-// These values are special allocation space tags used for |
-// serialization. |
-// Mark the pages executable on platforms that support it. |
-const int kLargeCode = LAST_SPACE + 1; |
-// Allocate extra remembered-set bits. |
-const int kLargeFixedArray = LAST_SPACE + 2; |
- |
- |
-static inline AllocationSpace GetSpace(Address addr) { |
- const intptr_t encoded = reinterpret_cast<intptr_t>(addr); |
- int space_number = (static_cast<int>(encoded >> kSpaceShift) & kSpaceMask); |
- if (space_number > LAST_SPACE) space_number = LO_SPACE; |
- return static_cast<AllocationSpace>(space_number); |
-} |
- |
- |
-static inline bool IsLargeExecutableObject(Address addr) { |
- const intptr_t encoded = reinterpret_cast<intptr_t>(addr); |
- const int space_number = |
- (static_cast<int>(encoded >> kSpaceShift) & kSpaceMask); |
- return (space_number == kLargeCode); |
-} |
- |
- |
-static inline bool IsLargeFixedArray(Address addr) { |
- const intptr_t encoded = reinterpret_cast<intptr_t>(addr); |
- const int space_number = |
- (static_cast<int>(encoded >> kSpaceShift) & kSpaceMask); |
- return (space_number == kLargeFixedArray); |
-} |
- |
- |
-static inline int PageIndex(Address addr) { |
- const intptr_t encoded = reinterpret_cast<intptr_t>(addr); |
- return static_cast<int>(encoded >> kPageShift) & kPageMask; |
-} |
- |
- |
-static inline int PageOffset(Address addr) { |
- const intptr_t encoded = reinterpret_cast<intptr_t>(addr); |
- const int offset = static_cast<int>(encoded >> kOffsetShift) & kOffsetMask; |
- return offset << kObjectAlignmentBits; |
-} |
- |
- |
-static inline int NewSpaceOffset(Address addr) { |
- const intptr_t encoded = reinterpret_cast<intptr_t>(addr); |
- const int page_offset = |
- static_cast<int>(encoded >> kPageAndOffsetShift) & kPageAndOffsetMask; |
- return page_offset << kObjectAlignmentBits; |
-} |
- |
- |
-static inline int LargeObjectIndex(Address addr) { |
- const intptr_t encoded = reinterpret_cast<intptr_t>(addr); |
- return static_cast<int>(encoded >> kPageAndOffsetShift) & kPageAndOffsetMask; |
-} |
- |
- |
-// A RelativeAddress encodes a heap address that is independent of |
-// the actual memory addresses in real heap. The general case (for the |
-// OLD, CODE and MAP spaces) is as a (space id, page number, page offset) |
-// triple. The NEW space has page number == 0, because there are no |
-// pages. The LARGE_OBJECT space has page offset = 0, since there is |
-// exactly one object per page. RelativeAddresses are encodable as |
-// Addresses, so that they can replace the map() pointers of |
-// HeapObjects. The encoded Addresses are also encoded as HeapObjects |
-// and allow for marking (is_marked() see mark(), clear_mark()...) as |
-// used by the Mark-Compact collector. |
- |
-class RelativeAddress { |
- public: |
- RelativeAddress(AllocationSpace space, |
- int page_index, |
- int page_offset) |
- : space_(space), page_index_(page_index), page_offset_(page_offset) { |
- // Assert that the space encoding (plus the two pseudo-spaces for |
- // special large objects) fits in the available bits. |
- ASSERT(((LAST_SPACE + 2) & ~kSpaceMask) == 0); |
- ASSERT(space <= LAST_SPACE && space >= 0); |
- } |
- |
- // Return the encoding of 'this' as an Address. Decode with constructor. |
- Address Encode() const; |
- |
- AllocationSpace space() const { |
- if (space_ > LAST_SPACE) return LO_SPACE; |
- return static_cast<AllocationSpace>(space_); |
- } |
- int page_index() const { return page_index_; } |
- int page_offset() const { return page_offset_; } |
- |
- bool in_paged_space() const { |
- return space_ == CODE_SPACE || |
- space_ == OLD_POINTER_SPACE || |
- space_ == OLD_DATA_SPACE || |
- space_ == MAP_SPACE || |
- space_ == CELL_SPACE; |
- } |
- |
- void next_address(int offset) { page_offset_ += offset; } |
- void next_page(int init_offset = 0) { |
- page_index_++; |
- page_offset_ = init_offset; |
- } |
- |
-#ifdef DEBUG |
- void Verify(); |
-#endif |
- |
- void set_to_large_code_object() { |
- ASSERT(space_ == LO_SPACE); |
- space_ = kLargeCode; |
- } |
- void set_to_large_fixed_array() { |
- ASSERT(space_ == LO_SPACE); |
- space_ = kLargeFixedArray; |
- } |
- |
- |
- private: |
- int space_; |
- int page_index_; |
- int page_offset_; |
-}; |
- |
- |
-Address RelativeAddress::Encode() const { |
- ASSERT(page_index_ >= 0); |
- int word_offset = 0; |
- int result = 0; |
- switch (space_) { |
- case MAP_SPACE: |
- case CELL_SPACE: |
- case OLD_POINTER_SPACE: |
- case OLD_DATA_SPACE: |
- case CODE_SPACE: |
- ASSERT_EQ(0, page_index_ & ~kPageMask); |
- word_offset = page_offset_ >> kObjectAlignmentBits; |
- ASSERT_EQ(0, word_offset & ~kOffsetMask); |
- result = (page_index_ << kPageShift) | (word_offset << kOffsetShift); |
- break; |
- case NEW_SPACE: |
- ASSERT_EQ(0, page_index_); |
- word_offset = page_offset_ >> kObjectAlignmentBits; |
- ASSERT_EQ(0, word_offset & ~kPageAndOffsetMask); |
- result = word_offset << kPageAndOffsetShift; |
- break; |
- case LO_SPACE: |
- case kLargeCode: |
- case kLargeFixedArray: |
- ASSERT_EQ(0, page_offset_); |
- ASSERT_EQ(0, page_index_ & ~kPageAndOffsetMask); |
- result = page_index_ << kPageAndOffsetShift; |
- break; |
- } |
- // OR in AllocationSpace and kHeapObjectTag |
- ASSERT_EQ(0, space_ & ~kSpaceMask); |
- result |= (space_ << kSpaceShift) | kHeapObjectTag; |
- return reinterpret_cast<Address>(result); |
-} |
- |
- |
-#ifdef DEBUG |
-void RelativeAddress::Verify() { |
- ASSERT(page_offset_ >= 0 && page_index_ >= 0); |
- switch (space_) { |
- case MAP_SPACE: |
- case CELL_SPACE: |
- case OLD_POINTER_SPACE: |
- case OLD_DATA_SPACE: |
- case CODE_SPACE: |
- ASSERT(Page::kObjectStartOffset <= page_offset_ && |
- page_offset_ <= Page::kPageSize); |
- break; |
- case NEW_SPACE: |
- ASSERT(page_index_ == 0); |
- break; |
- case LO_SPACE: |
- case kLargeCode: |
- case kLargeFixedArray: |
- ASSERT(page_offset_ == 0); |
- break; |
- } |
-} |
-#endif |
- |
-enum GCTreatment { |
- DataObject, // Object that cannot contain a reference to new space. |
- PointerObject, // Object that can contain a reference to new space. |
- CodeObject // Object that contains executable code. |
-}; |
- |
-// A SimulatedHeapSpace simulates the allocation of objects in a page in |
-// the heap. It uses linear allocation - that is, it doesn't simulate the |
-// use of a free list. This simulated |
-// allocation must exactly match that done by Heap. |
- |
-class SimulatedHeapSpace { |
- public: |
- // The default constructor initializes to an invalid state. |
- SimulatedHeapSpace(): current_(LAST_SPACE, -1, -1) {} |
- |
- // Sets 'this' to the first address in 'space' that would be |
- // returned by allocation in an empty heap. |
- void InitEmptyHeap(AllocationSpace space); |
- |
- // Sets 'this' to the next address in 'space' that would be returned |
- // by allocation in the current heap. Intended only for testing |
- // serialization and deserialization in the current address space. |
- void InitCurrentHeap(AllocationSpace space); |
- |
- // Returns the RelativeAddress where the next |
- // object of 'size' bytes will be allocated, and updates 'this' to |
- // point to the next free address beyond that object. |
- RelativeAddress Allocate(int size, GCTreatment special_gc_treatment); |
- |
- private: |
- RelativeAddress current_; |
-}; |
- |
- |
-void SimulatedHeapSpace::InitEmptyHeap(AllocationSpace space) { |
- switch (space) { |
- case MAP_SPACE: |
- case CELL_SPACE: |
- case OLD_POINTER_SPACE: |
- case OLD_DATA_SPACE: |
- case CODE_SPACE: |
- current_ = RelativeAddress(space, 0, Page::kObjectStartOffset); |
- break; |
- case NEW_SPACE: |
- case LO_SPACE: |
- current_ = RelativeAddress(space, 0, 0); |
- break; |
- } |
-} |
- |
- |
-void SimulatedHeapSpace::InitCurrentHeap(AllocationSpace space) { |
- switch (space) { |
- case MAP_SPACE: |
- case CELL_SPACE: |
- case OLD_POINTER_SPACE: |
- case OLD_DATA_SPACE: |
- case CODE_SPACE: { |
- PagedSpace* ps; |
- if (space == MAP_SPACE) { |
- ps = Heap::map_space(); |
- } else if (space == CELL_SPACE) { |
- ps = Heap::cell_space(); |
- } else if (space == OLD_POINTER_SPACE) { |
- ps = Heap::old_pointer_space(); |
- } else if (space == OLD_DATA_SPACE) { |
- ps = Heap::old_data_space(); |
- } else { |
- ASSERT(space == CODE_SPACE); |
- ps = Heap::code_space(); |
- } |
- Address top = ps->top(); |
- Page* top_page = Page::FromAllocationTop(top); |
- int page_index = 0; |
- PageIterator it(ps, PageIterator::PAGES_IN_USE); |
- while (it.has_next()) { |
- if (it.next() == top_page) break; |
- page_index++; |
- } |
- current_ = RelativeAddress(space, |
- page_index, |
- top_page->Offset(top)); |
- break; |
- } |
- case NEW_SPACE: |
- current_ = RelativeAddress(space, |
- 0, |
- static_cast<int>(Heap::NewSpaceTop() |
- - Heap::NewSpaceStart())); |
- break; |
- case LO_SPACE: |
- int page_index = 0; |
- for (LargeObjectIterator it(Heap::lo_space()); it.has_next(); it.next()) { |
- page_index++; |
- } |
- current_ = RelativeAddress(space, page_index, 0); |
- break; |
- } |
-} |
- |
- |
-RelativeAddress SimulatedHeapSpace::Allocate(int size, |
- GCTreatment special_gc_treatment) { |
-#ifdef DEBUG |
- current_.Verify(); |
-#endif |
- int alloc_size = OBJECT_SIZE_ALIGN(size); |
- if (current_.in_paged_space() && |
- current_.page_offset() + alloc_size > Page::kPageSize) { |
- ASSERT(alloc_size <= Page::kMaxHeapObjectSize); |
- current_.next_page(Page::kObjectStartOffset); |
- } |
- RelativeAddress result = current_; |
- if (current_.space() == LO_SPACE) { |
- current_.next_page(); |
- if (special_gc_treatment == CodeObject) { |
- result.set_to_large_code_object(); |
- } else if (special_gc_treatment == PointerObject) { |
- result.set_to_large_fixed_array(); |
- } |
- } else { |
- current_.next_address(alloc_size); |
- } |
-#ifdef DEBUG |
- current_.Verify(); |
- result.Verify(); |
-#endif |
- return result; |
-} |
- |
// ----------------------------------------------------------------------------- |
// Coding of external references. |
@@ -829,953 +485,11 @@ |
} |
-//------------------------------------------------------------------------------ |
-// Implementation of Serializer |
- |
- |
-// Helper class to write the bytes of the serialized heap. |
- |
-class SnapshotWriter { |
- public: |
- SnapshotWriter() { |
- len_ = 0; |
- max_ = 8 << 10; // 8K initial size |
- str_ = NewArray<byte>(max_); |
- } |
- |
- ~SnapshotWriter() { |
- DeleteArray(str_); |
- } |
- |
- void GetBytes(byte** str, int* len) { |
- *str = NewArray<byte>(len_); |
- memcpy(*str, str_, len_); |
- *len = len_; |
- } |
- |
- void Reserve(int bytes, int pos); |
- |
- void PutC(char c) { |
- InsertC(c, len_); |
- } |
- |
- void PutInt(int i) { |
- InsertInt(i, len_); |
- } |
- |
- void PutAddress(Address p) { |
- PutBytes(reinterpret_cast<byte*>(&p), sizeof(p)); |
- } |
- |
- void PutBytes(const byte* a, int size) { |
- InsertBytes(a, len_, size); |
- } |
- |
- void PutString(const char* s) { |
- InsertString(s, len_); |
- } |
- |
- int InsertC(char c, int pos) { |
- Reserve(1, pos); |
- str_[pos] = c; |
- len_++; |
- return pos + 1; |
- } |
- |
- int InsertInt(int i, int pos) { |
- return InsertBytes(reinterpret_cast<byte*>(&i), pos, sizeof(i)); |
- } |
- |
- int InsertBytes(const byte* a, int pos, int size) { |
- Reserve(size, pos); |
- memcpy(&str_[pos], a, size); |
- len_ += size; |
- return pos + size; |
- } |
- |
- int InsertString(const char* s, int pos); |
- |
- int length() { return len_; } |
- |
- Address position() { return reinterpret_cast<Address>(&str_[len_]); } |
- |
- private: |
- byte* str_; // the snapshot |
- int len_; // the current length of str_ |
- int max_; // the allocated size of str_ |
-}; |
- |
- |
-void SnapshotWriter::Reserve(int bytes, int pos) { |
- CHECK(0 <= pos && pos <= len_); |
- while (len_ + bytes >= max_) { |
- max_ *= 2; |
- byte* old = str_; |
- str_ = NewArray<byte>(max_); |
- memcpy(str_, old, len_); |
- DeleteArray(old); |
- } |
- if (pos < len_) { |
- byte* old = str_; |
- str_ = NewArray<byte>(max_); |
- memcpy(str_, old, pos); |
- memcpy(str_ + pos + bytes, old + pos, len_ - pos); |
- DeleteArray(old); |
- } |
-} |
- |
-int SnapshotWriter::InsertString(const char* s, int pos) { |
- int size = StrLength(s); |
- pos = InsertC('[', pos); |
- pos = InsertInt(size, pos); |
- pos = InsertC(']', pos); |
- return InsertBytes(reinterpret_cast<const byte*>(s), pos, size); |
-} |
- |
- |
-class ReferenceUpdater: public ObjectVisitor { |
- public: |
- ReferenceUpdater(HeapObject* obj, Serializer* serializer) |
- : obj_address_(obj->address()), |
- serializer_(serializer), |
- reference_encoder_(serializer->reference_encoder_), |
- offsets_(8), |
- addresses_(8), |
- offsets_32_bit_(0), |
- data_32_bit_(0) { |
- } |
- |
- virtual void VisitPointers(Object** start, Object** end) { |
- for (Object** p = start; p < end; ++p) { |
- if ((*p)->IsHeapObject()) { |
- offsets_.Add( |
- static_cast<int>(reinterpret_cast<Address>(p) - obj_address_)); |
- Address a = serializer_->GetSavedAddress(HeapObject::cast(*p)); |
- addresses_.Add(a); |
- } |
- } |
- } |
- |
- virtual void VisitCodeTarget(RelocInfo* rinfo) { |
- ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); |
- Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
- Address encoded_target = serializer_->GetSavedAddress(target); |
- // All calls and jumps are to code objects that encode into 32 bits. |
- offsets_32_bit_.Add( |
- static_cast<int>(rinfo->target_address_address() - obj_address_)); |
- uint32_t small_target = |
- static_cast<uint32_t>(reinterpret_cast<uintptr_t>(encoded_target)); |
- ASSERT(reinterpret_cast<uintptr_t>(encoded_target) == small_target); |
- data_32_bit_.Add(small_target); |
- } |
- |
- |
- virtual void VisitExternalReferences(Address* start, Address* end) { |
- for (Address* p = start; p < end; ++p) { |
- uint32_t code = reference_encoder_->Encode(*p); |
- CHECK(*p == NULL ? code == 0 : code != 0); |
- offsets_.Add( |
- static_cast<int>(reinterpret_cast<Address>(p) - obj_address_)); |
- addresses_.Add(reinterpret_cast<Address>(code)); |
- } |
- } |
- |
- virtual void VisitRuntimeEntry(RelocInfo* rinfo) { |
- Address target = rinfo->target_address(); |
- uint32_t encoding = reference_encoder_->Encode(target); |
- CHECK(target == NULL ? encoding == 0 : encoding != 0); |
- offsets_.Add( |
- static_cast<int>(rinfo->target_address_address() - obj_address_)); |
- addresses_.Add(reinterpret_cast<Address>(encoding)); |
- } |
- |
- void Update(Address start_address) { |
- for (int i = 0; i < offsets_.length(); i++) { |
- memcpy(start_address + offsets_[i], &addresses_[i], sizeof(Address)); |
- } |
- for (int i = 0; i < offsets_32_bit_.length(); i++) { |
- memcpy(start_address + offsets_32_bit_[i], &data_32_bit_[i], |
- sizeof(uint32_t)); |
- } |
- } |
- |
- private: |
- Address obj_address_; |
- Serializer* serializer_; |
- ExternalReferenceEncoder* reference_encoder_; |
- List<int> offsets_; |
- List<Address> addresses_; |
- // Some updates are 32-bit even on a 64-bit platform. |
- // We keep a separate list of them on 64-bit platforms. |
- List<int> offsets_32_bit_; |
- List<uint32_t> data_32_bit_; |
-}; |
- |
- |
-// Helper functions for a map of encoded heap object addresses. |
-static uint32_t HeapObjectHash(HeapObject* key) { |
- uint32_t low32bits = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)); |
- return low32bits >> 2; |
-} |
- |
- |
-static bool MatchHeapObject(void* key1, void* key2) { |
- return key1 == key2; |
-} |
- |
- |
-Serializer::Serializer() |
- : global_handles_(4), |
- saved_addresses_(MatchHeapObject) { |
- root_ = true; |
- roots_ = 0; |
- objects_ = 0; |
- reference_encoder_ = NULL; |
- writer_ = new SnapshotWriter(); |
- for (int i = 0; i <= LAST_SPACE; i++) { |
- allocator_[i] = new SimulatedHeapSpace(); |
- } |
-} |
- |
- |
-Serializer::~Serializer() { |
- for (int i = 0; i <= LAST_SPACE; i++) { |
- delete allocator_[i]; |
- } |
- if (reference_encoder_) delete reference_encoder_; |
- delete writer_; |
-} |
- |
- |
bool Serializer::serialization_enabled_ = false; |
bool Serializer::too_late_to_enable_now_ = false; |
-#ifdef DEBUG |
-static const int kMaxTagLength = 32; |
- |
-void Serializer::Synchronize(const char* tag) { |
- if (FLAG_debug_serialization) { |
- int length = StrLength(tag); |
- ASSERT(length <= kMaxTagLength); |
- writer_->PutC('S'); |
- writer_->PutInt(length); |
- writer_->PutBytes(reinterpret_cast<const byte*>(tag), length); |
- } |
-} |
-#endif |
- |
- |
-void Serializer::InitializeAllocators() { |
- for (int i = 0; i <= LAST_SPACE; i++) { |
- allocator_[i]->InitEmptyHeap(static_cast<AllocationSpace>(i)); |
- } |
-} |
- |
- |
-bool Serializer::IsVisited(HeapObject* obj) { |
- HashMap::Entry* entry = |
- saved_addresses_.Lookup(obj, HeapObjectHash(obj), false); |
- return entry != NULL; |
-} |
- |
- |
-Address Serializer::GetSavedAddress(HeapObject* obj) { |
- HashMap::Entry* entry = |
- saved_addresses_.Lookup(obj, HeapObjectHash(obj), false); |
- ASSERT(entry != NULL); |
- return reinterpret_cast<Address>(entry->value); |
-} |
- |
- |
-void Serializer::SaveAddress(HeapObject* obj, Address addr) { |
- HashMap::Entry* entry = |
- saved_addresses_.Lookup(obj, HeapObjectHash(obj), true); |
- entry->value = addr; |
-} |
- |
- |
-void Serializer::Serialize() { |
- // No active threads. |
- CHECK_EQ(NULL, ThreadState::FirstInUse()); |
- // No active or weak handles. |
- CHECK(HandleScopeImplementer::instance()->blocks()->is_empty()); |
- CHECK_EQ(0, GlobalHandles::NumberOfWeakHandles()); |
- // We need a counter function during serialization to resolve the |
- // references to counters in the code on the heap. |
- CHECK(StatsTable::HasCounterFunction()); |
- CHECK(enabled()); |
- InitializeAllocators(); |
- reference_encoder_ = new ExternalReferenceEncoder(); |
- PutHeader(); |
- Heap::IterateRoots(this, VISIT_ONLY_STRONG); |
- PutLog(); |
- PutContextStack(); |
- Disable(); |
-} |
- |
- |
-void Serializer::Finalize(byte** str, int* len) { |
- writer_->GetBytes(str, len); |
-} |
- |
- |
-// Serialize objects by writing them into the stream. |
- |
-void Serializer::VisitPointers(Object** start, Object** end) { |
- bool root = root_; |
- root_ = false; |
- for (Object** p = start; p < end; ++p) { |
- bool serialized; |
- Address a = Encode(*p, &serialized); |
- if (root) { |
- roots_++; |
- // If the object was not just serialized, |
- // write its encoded address instead. |
- if (!serialized) PutEncodedAddress(a); |
- } |
- } |
- root_ = root; |
-} |
- |
- |
-void Serializer::VisitCodeTarget(RelocInfo* rinfo) { |
- ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); |
- Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
- bool serialized; |
- Encode(target, &serialized); |
-} |
- |
- |
-class GlobalHandlesRetriever: public ObjectVisitor { |
- public: |
- explicit GlobalHandlesRetriever(List<Object**>* handles) |
- : global_handles_(handles) {} |
- |
- virtual void VisitPointers(Object** start, Object** end) { |
- for (; start != end; ++start) { |
- global_handles_->Add(start); |
- } |
- } |
- |
- private: |
- List<Object**>* global_handles_; |
-}; |
- |
- |
-void Serializer::PutFlags() { |
- writer_->PutC('F'); |
- List<const char*>* argv = FlagList::argv(); |
- writer_->PutInt(argv->length()); |
- writer_->PutC('['); |
- for (int i = 0; i < argv->length(); i++) { |
- if (i > 0) writer_->PutC('|'); |
- writer_->PutString((*argv)[i]); |
- DeleteArray((*argv)[i]); |
- } |
- writer_->PutC(']'); |
- flags_end_ = writer_->length(); |
- delete argv; |
-} |
- |
- |
-void Serializer::PutHeader() { |
- PutFlags(); |
- writer_->PutC('D'); |
-#ifdef DEBUG |
- writer_->PutC(FLAG_debug_serialization ? '1' : '0'); |
-#else |
- writer_->PutC('0'); |
-#endif |
-#ifdef V8_NATIVE_REGEXP |
- writer_->PutC('N'); |
-#else // Interpreted regexp |
- writer_->PutC('I'); |
-#endif |
- // Write sizes of paged memory spaces. Allocate extra space for the old |
- // and code spaces, because objects in new space will be promoted to them. |
- writer_->PutC('S'); |
- writer_->PutC('['); |
- writer_->PutInt(Heap::old_pointer_space()->Size() + |
- Heap::new_space()->Size()); |
- writer_->PutC('|'); |
- writer_->PutInt(Heap::old_data_space()->Size() + Heap::new_space()->Size()); |
- writer_->PutC('|'); |
- writer_->PutInt(Heap::code_space()->Size() + Heap::new_space()->Size()); |
- writer_->PutC('|'); |
- writer_->PutInt(Heap::map_space()->Size()); |
- writer_->PutC('|'); |
- writer_->PutInt(Heap::cell_space()->Size()); |
- writer_->PutC(']'); |
- // Write global handles. |
- writer_->PutC('G'); |
- writer_->PutC('['); |
- GlobalHandlesRetriever ghr(&global_handles_); |
- GlobalHandles::IterateStrongRoots(&ghr); |
- for (int i = 0; i < global_handles_.length(); i++) { |
- writer_->PutC('N'); |
- } |
- writer_->PutC(']'); |
-} |
- |
- |
-void Serializer::PutLog() { |
-#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (FLAG_log_code) { |
- Logger::TearDown(); |
- int pos = writer_->InsertC('L', flags_end_); |
- bool exists; |
- Vector<const char> log = ReadFile(FLAG_logfile, &exists); |
- writer_->InsertString(log.start(), pos); |
- log.Dispose(); |
- } |
-#endif |
-} |
- |
- |
-static int IndexOf(const List<Object**>& list, Object** element) { |
- for (int i = 0; i < list.length(); i++) { |
- if (list[i] == element) return i; |
- } |
- return -1; |
-} |
- |
- |
-void Serializer::PutGlobalHandleStack(const List<Handle<Object> >& stack) { |
- writer_->PutC('['); |
- writer_->PutInt(stack.length()); |
- for (int i = stack.length() - 1; i >= 0; i--) { |
- writer_->PutC('|'); |
- int gh_index = IndexOf(global_handles_, stack[i].location()); |
- CHECK_GE(gh_index, 0); |
- writer_->PutInt(gh_index); |
- } |
- writer_->PutC(']'); |
-} |
- |
- |
-void Serializer::PutContextStack() { |
- List<Context*> contexts(2); |
- while (HandleScopeImplementer::instance()->HasSavedContexts()) { |
- Context* context = |
- HandleScopeImplementer::instance()->RestoreContext(); |
- contexts.Add(context); |
- } |
- for (int i = contexts.length() - 1; i >= 0; i--) { |
- HandleScopeImplementer::instance()->SaveContext(contexts[i]); |
- } |
- writer_->PutC('C'); |
- writer_->PutC('['); |
- writer_->PutInt(contexts.length()); |
- if (!contexts.is_empty()) { |
- Object** start = reinterpret_cast<Object**>(&contexts.first()); |
- VisitPointers(start, start + contexts.length()); |
- } |
- writer_->PutC(']'); |
-} |
- |
-void Serializer::PutEncodedAddress(Address addr) { |
- writer_->PutC('P'); |
- writer_->PutAddress(addr); |
-} |
- |
- |
-Address Serializer::Encode(Object* o, bool* serialized) { |
- *serialized = false; |
- if (o->IsSmi()) { |
- return reinterpret_cast<Address>(o); |
- } else { |
- HeapObject* obj = HeapObject::cast(o); |
- if (IsVisited(obj)) { |
- return GetSavedAddress(obj); |
- } else { |
- // First visit: serialize the object. |
- *serialized = true; |
- return PutObject(obj); |
- } |
- } |
-} |
- |
- |
-Address Serializer::PutObject(HeapObject* obj) { |
- Map* map = obj->map(); |
- InstanceType type = map->instance_type(); |
- int size = obj->SizeFromMap(map); |
- |
- // Simulate the allocation of obj to predict where it will be |
- // allocated during deserialization. |
- Address addr = Allocate(obj).Encode(); |
- |
- SaveAddress(obj, addr); |
- |
- if (type == CODE_TYPE) { |
- LOG(CodeMoveEvent(obj->address(), addr)); |
- } |
- |
- // Write out the object prologue: type, size, and simulated address of obj. |
- writer_->PutC('['); |
- CHECK_EQ(0, static_cast<int>(size & kObjectAlignmentMask)); |
- writer_->PutInt(type); |
- writer_->PutInt(size >> kObjectAlignmentBits); |
- PutEncodedAddress(addr); // encodes AllocationSpace |
- |
- // Visit all the pointers in the object other than the map. This |
- // will recursively serialize any as-yet-unvisited objects. |
- obj->Iterate(this); |
- |
- // Mark end of recursively embedded objects, start of object body. |
- writer_->PutC('|'); |
- // Write out the raw contents of the object. No compression, but |
- // fast to deserialize. |
- writer_->PutBytes(obj->address(), size); |
- // Update pointers and external references in the written object. |
- ReferenceUpdater updater(obj, this); |
- obj->Iterate(&updater); |
- updater.Update(writer_->position() - size); |
- |
-#ifdef DEBUG |
- if (FLAG_debug_serialization) { |
- // Write out the object epilogue to catch synchronization errors. |
- PutEncodedAddress(addr); |
- writer_->PutC(']'); |
- } |
-#endif |
- |
- objects_++; |
- return addr; |
-} |
- |
- |
-RelativeAddress Serializer::Allocate(HeapObject* obj) { |
- // Find out which AllocationSpace 'obj' is in. |
- AllocationSpace s; |
- bool found = false; |
- for (int i = FIRST_SPACE; !found && i <= LAST_SPACE; i++) { |
- s = static_cast<AllocationSpace>(i); |
- found = Heap::InSpace(obj, s); |
- } |
- CHECK(found); |
- int size = obj->Size(); |
- if (s == NEW_SPACE) { |
- if (size > Heap::MaxObjectSizeInPagedSpace()) { |
- s = LO_SPACE; |
- } else { |
- OldSpace* space = Heap::TargetSpace(obj); |
- ASSERT(space == Heap::old_pointer_space() || |
- space == Heap::old_data_space()); |
- s = (space == Heap::old_pointer_space()) ? |
- OLD_POINTER_SPACE : |
- OLD_DATA_SPACE; |
- } |
- } |
- GCTreatment gc_treatment = DataObject; |
- if (obj->IsFixedArray()) gc_treatment = PointerObject; |
- else if (obj->IsCode()) gc_treatment = CodeObject; |
- return allocator_[s]->Allocate(size, gc_treatment); |
-} |
- |
- |
-//------------------------------------------------------------------------------ |
-// Implementation of Deserializer |
- |
- |
-static const int kInitArraySize = 32; |
- |
- |
-Deserializer::Deserializer(const byte* str, int len) |
- : reader_(str, len), |
- map_pages_(kInitArraySize), |
- cell_pages_(kInitArraySize), |
- old_pointer_pages_(kInitArraySize), |
- old_data_pages_(kInitArraySize), |
- code_pages_(kInitArraySize), |
- large_objects_(kInitArraySize), |
- global_handles_(4) { |
- root_ = true; |
- roots_ = 0; |
- objects_ = 0; |
- reference_decoder_ = NULL; |
-#ifdef DEBUG |
- expect_debug_information_ = false; |
-#endif |
-} |
- |
- |
-Deserializer::~Deserializer() { |
- if (reference_decoder_) delete reference_decoder_; |
-} |
- |
- |
-void Deserializer::ExpectEncodedAddress(Address expected) { |
- Address a = GetEncodedAddress(); |
- USE(a); |
- ASSERT(a == expected); |
-} |
- |
- |
-#ifdef DEBUG |
-void Deserializer::Synchronize(const char* tag) { |
- if (expect_debug_information_) { |
- char buf[kMaxTagLength]; |
- reader_.ExpectC('S'); |
- int length = reader_.GetInt(); |
- ASSERT(length <= kMaxTagLength); |
- reader_.GetBytes(reinterpret_cast<Address>(buf), length); |
- ASSERT_EQ(StrLength(tag), length); |
- ASSERT(strncmp(tag, buf, length) == 0); |
- } |
-} |
-#endif |
- |
- |
-class NoGlobalHandlesChecker : public ObjectVisitor { |
- public: |
- virtual void VisitPointers(Object** start, Object** end) { |
- ASSERT(false); |
- } |
-}; |
- |
- |
-class GlobalHandleDestroyer : public ObjectVisitor { |
- void VisitPointers(Object**start, Object**end) { |
- while (start < end) { |
- GlobalHandles::Destroy(start++); |
- } |
- } |
-}; |
- |
- |
-void Deserializer::Deserialize() { |
- // No global handles. |
- NoGlobalHandlesChecker checker; |
- GlobalHandles::IterateStrongRoots(&checker); |
- // No active threads. |
- ASSERT_EQ(NULL, ThreadState::FirstInUse()); |
- // No active handles. |
- ASSERT(HandleScopeImplementer::instance()->blocks()->is_empty()); |
- reference_decoder_ = new ExternalReferenceDecoder(); |
- // By setting linear allocation only, we forbid the use of free list |
- // allocation which is not predicted by SimulatedAddress. |
- GetHeader(); |
- Heap::IterateRoots(this, VISIT_ONLY_STRONG); |
- GetContextStack(); |
- // Any global handles that have been set up by deserialization are leaked |
- // since noone is keeping track of them. So we discard them now. |
- GlobalHandleDestroyer destroyer; |
- GlobalHandles::IterateStrongRoots(&destroyer); |
-} |
- |
- |
-void Deserializer::VisitPointers(Object** start, Object** end) { |
- bool root = root_; |
- root_ = false; |
- for (Object** p = start; p < end; ++p) { |
- if (root) { |
- roots_++; |
- // Read the next object or pointer from the stream |
- // pointer in the stream. |
- int c = reader_.GetC(); |
- if (c == '[') { |
- *p = GetObject(); // embedded object |
- } else { |
- ASSERT(c == 'P'); // pointer to previously serialized object |
- *p = Resolve(reader_.GetAddress()); |
- } |
- } else { |
- // A pointer internal to a HeapObject that we've already |
- // read: resolve it to a true address (or Smi) |
- *p = Resolve(reinterpret_cast<Address>(*p)); |
- } |
- } |
- root_ = root; |
-} |
- |
- |
-void Deserializer::VisitCodeTarget(RelocInfo* rinfo) { |
- ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); |
- // On all platforms, the encoded code object address is only 32 bits. |
- Address encoded_address = reinterpret_cast<Address>(Memory::uint32_at( |
- reinterpret_cast<Address>(rinfo->target_object_address()))); |
- Code* target_object = reinterpret_cast<Code*>(Resolve(encoded_address)); |
- rinfo->set_target_address(target_object->instruction_start()); |
-} |
- |
- |
-void Deserializer::VisitExternalReferences(Address* start, Address* end) { |
- for (Address* p = start; p < end; ++p) { |
- uint32_t code = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(*p)); |
- *p = reference_decoder_->Decode(code); |
- } |
-} |
- |
- |
-void Deserializer::VisitRuntimeEntry(RelocInfo* rinfo) { |
- uint32_t* pc = reinterpret_cast<uint32_t*>(rinfo->target_address_address()); |
- uint32_t encoding = *pc; |
- Address target = reference_decoder_->Decode(encoding); |
- rinfo->set_target_address(target); |
-} |
- |
- |
-void Deserializer::GetFlags() { |
- reader_.ExpectC('F'); |
- int argc = reader_.GetInt() + 1; |
- char** argv = NewArray<char*>(argc); |
- reader_.ExpectC('['); |
- for (int i = 1; i < argc; i++) { |
- if (i > 1) reader_.ExpectC('|'); |
- argv[i] = reader_.GetString(); |
- } |
- reader_.ExpectC(']'); |
- has_log_ = false; |
- for (int i = 1; i < argc; i++) { |
- if (strcmp("--log_code", argv[i]) == 0) { |
- has_log_ = true; |
- } else if (strcmp("--nouse_ic", argv[i]) == 0) { |
- FLAG_use_ic = false; |
- } else if (strcmp("--debug_code", argv[i]) == 0) { |
- FLAG_debug_code = true; |
- } else if (strcmp("--nolazy", argv[i]) == 0) { |
- FLAG_lazy = false; |
- } |
- DeleteArray(argv[i]); |
- } |
- |
- DeleteArray(argv); |
-} |
- |
- |
-void Deserializer::GetLog() { |
- if (has_log_) { |
- reader_.ExpectC('L'); |
- char* snapshot_log = reader_.GetString(); |
-#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (FLAG_log_code) { |
- LOG(Preamble(snapshot_log)); |
- } |
-#endif |
- DeleteArray(snapshot_log); |
- } |
-} |
- |
- |
-static void InitPagedSpace(PagedSpace* space, |
- int capacity, |
- List<Page*>* page_list) { |
- if (!space->EnsureCapacity(capacity)) { |
- V8::FatalProcessOutOfMemory("InitPagedSpace"); |
- } |
- PageIterator it(space, PageIterator::ALL_PAGES); |
- while (it.has_next()) page_list->Add(it.next()); |
-} |
- |
- |
-void Deserializer::GetHeader() { |
- reader_.ExpectC('D'); |
-#ifdef DEBUG |
- expect_debug_information_ = reader_.GetC() == '1'; |
-#else |
- // In release mode, don't attempt to read a snapshot containing |
- // synchronization tags. |
- if (reader_.GetC() != '0') FATAL("Snapshot contains synchronization tags."); |
-#endif |
-#ifdef V8_NATIVE_REGEXP |
- reader_.ExpectC('N'); |
-#else // Interpreted regexp. |
- reader_.ExpectC('I'); |
-#endif |
- // Ensure sufficient capacity in paged memory spaces to avoid growth |
- // during deserialization. |
- reader_.ExpectC('S'); |
- reader_.ExpectC('['); |
- InitPagedSpace(Heap::old_pointer_space(), |
- reader_.GetInt(), |
- &old_pointer_pages_); |
- reader_.ExpectC('|'); |
- InitPagedSpace(Heap::old_data_space(), reader_.GetInt(), &old_data_pages_); |
- reader_.ExpectC('|'); |
- InitPagedSpace(Heap::code_space(), reader_.GetInt(), &code_pages_); |
- reader_.ExpectC('|'); |
- InitPagedSpace(Heap::map_space(), reader_.GetInt(), &map_pages_); |
- reader_.ExpectC('|'); |
- InitPagedSpace(Heap::cell_space(), reader_.GetInt(), &cell_pages_); |
- reader_.ExpectC(']'); |
- // Create placeholders for global handles later to be fill during |
- // IterateRoots. |
- reader_.ExpectC('G'); |
- reader_.ExpectC('['); |
- int c = reader_.GetC(); |
- while (c != ']') { |
- ASSERT(c == 'N'); |
- global_handles_.Add(GlobalHandles::Create(NULL).location()); |
- c = reader_.GetC(); |
- } |
-} |
- |
- |
-void Deserializer::GetGlobalHandleStack(List<Handle<Object> >* stack) { |
- reader_.ExpectC('['); |
- int length = reader_.GetInt(); |
- for (int i = 0; i < length; i++) { |
- reader_.ExpectC('|'); |
- int gh_index = reader_.GetInt(); |
- stack->Add(global_handles_[gh_index]); |
- } |
- reader_.ExpectC(']'); |
-} |
- |
- |
-void Deserializer::GetContextStack() { |
- reader_.ExpectC('C'); |
- CHECK_EQ(reader_.GetC(), '['); |
- int count = reader_.GetInt(); |
- List<Context*> entered_contexts(count); |
- if (count > 0) { |
- Object** start = reinterpret_cast<Object**>(&entered_contexts.first()); |
- VisitPointers(start, start + count); |
- } |
- reader_.ExpectC(']'); |
- for (int i = 0; i < count; i++) { |
- HandleScopeImplementer::instance()->SaveContext(entered_contexts[i]); |
- } |
-} |
- |
- |
-Address Deserializer::GetEncodedAddress() { |
- reader_.ExpectC('P'); |
- return reader_.GetAddress(); |
-} |
- |
- |
-Object* Deserializer::GetObject() { |
- // Read the prologue: type, size and encoded address. |
- InstanceType type = static_cast<InstanceType>(reader_.GetInt()); |
- int size = reader_.GetInt() << kObjectAlignmentBits; |
- Address a = GetEncodedAddress(); |
- |
- // Get a raw object of the right size in the right space. |
- AllocationSpace space = GetSpace(a); |
- Object* o; |
- if (IsLargeExecutableObject(a)) { |
- o = Heap::lo_space()->AllocateRawCode(size); |
- } else if (IsLargeFixedArray(a)) { |
- o = Heap::lo_space()->AllocateRawFixedArray(size); |
- } else { |
- AllocationSpace retry_space = (space == NEW_SPACE) |
- ? Heap::TargetSpaceId(type) |
- : space; |
- o = Heap::AllocateRaw(size, space, retry_space); |
- } |
- ASSERT(!o->IsFailure()); |
- // Check that the simulation of heap allocation was correct. |
- ASSERT(o == Resolve(a)); |
- |
- // Read any recursively embedded objects. |
- int c = reader_.GetC(); |
- while (c == '[') { |
- GetObject(); |
- c = reader_.GetC(); |
- } |
- ASSERT(c == '|'); |
- |
- HeapObject* obj = reinterpret_cast<HeapObject*>(o); |
- // Read the uninterpreted contents of the object after the map |
- reader_.GetBytes(obj->address(), size); |
-#ifdef DEBUG |
- if (expect_debug_information_) { |
- // Read in the epilogue to check that we're still synchronized |
- ExpectEncodedAddress(a); |
- reader_.ExpectC(']'); |
- } |
-#endif |
- |
- // Resolve the encoded pointers we just read in. |
- // Same as obj->Iterate(this), but doesn't rely on the map pointer being set. |
- VisitPointer(reinterpret_cast<Object**>(obj->address())); |
- obj->IterateBody(type, size, this); |
- |
- if (type == CODE_TYPE) { |
- LOG(CodeMoveEvent(a, obj->address())); |
- } |
- objects_++; |
- return o; |
-} |
- |
- |
-static inline Object* ResolvePaged(int page_index, |
- int page_offset, |
- PagedSpace* space, |
- List<Page*>* page_list) { |
- ASSERT(page_index < page_list->length()); |
- Address address = (*page_list)[page_index]->OffsetToAddress(page_offset); |
- return HeapObject::FromAddress(address); |
-} |
- |
- |
-template<typename T> |
-void ConcatReversed(List<T>* target, const List<T>& source) { |
- for (int i = source.length() - 1; i >= 0; i--) { |
- target->Add(source[i]); |
- } |
-} |
- |
- |
-Object* Deserializer::Resolve(Address encoded) { |
- Object* o = reinterpret_cast<Object*>(encoded); |
- if (o->IsSmi()) return o; |
- |
- // Encoded addresses of HeapObjects always have 'HeapObject' tags. |
- ASSERT(o->IsHeapObject()); |
- switch (GetSpace(encoded)) { |
- // For Map space and Old space, we cache the known Pages in map_pages, |
- // old_pointer_pages and old_data_pages. Even though MapSpace keeps a list |
- // of page addresses, we don't rely on it since GetObject uses AllocateRaw, |
- // and that appears not to update the page list. |
- case MAP_SPACE: |
- return ResolvePaged(PageIndex(encoded), PageOffset(encoded), |
- Heap::map_space(), &map_pages_); |
- case CELL_SPACE: |
- return ResolvePaged(PageIndex(encoded), PageOffset(encoded), |
- Heap::cell_space(), &cell_pages_); |
- case OLD_POINTER_SPACE: |
- return ResolvePaged(PageIndex(encoded), PageOffset(encoded), |
- Heap::old_pointer_space(), &old_pointer_pages_); |
- case OLD_DATA_SPACE: |
- return ResolvePaged(PageIndex(encoded), PageOffset(encoded), |
- Heap::old_data_space(), &old_data_pages_); |
- case CODE_SPACE: |
- return ResolvePaged(PageIndex(encoded), PageOffset(encoded), |
- Heap::code_space(), &code_pages_); |
- case NEW_SPACE: |
- return HeapObject::FromAddress(Heap::NewSpaceStart() + |
- NewSpaceOffset(encoded)); |
- case LO_SPACE: |
- // Cache the known large_objects, allocated one per 'page' |
- int index = LargeObjectIndex(encoded); |
- if (index >= large_objects_.length()) { |
- int new_object_count = |
- Heap::lo_space()->PageCount() - large_objects_.length(); |
- List<Object*> new_objects(new_object_count); |
- LargeObjectIterator it(Heap::lo_space()); |
- for (int i = 0; i < new_object_count; i++) { |
- new_objects.Add(it.next()); |
- } |
-#ifdef DEBUG |
- for (int i = large_objects_.length() - 1; i >= 0; i--) { |
- ASSERT(it.next() == large_objects_[i]); |
- } |
-#endif |
- ConcatReversed(&large_objects_, new_objects); |
- ASSERT(index < large_objects_.length()); |
- } |
- return large_objects_[index]; // s.page_offset() is ignored. |
- } |
- UNREACHABLE(); |
- return NULL; |
-} |
- |
- |
-Deserializer2::Deserializer2(SnapshotByteSource* source) |
+Deserializer::Deserializer(SnapshotByteSource* source) |
: source_(source), |
external_reference_decoder_(NULL) { |
} |
@@ -1784,7 +498,7 @@ |
// 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 Deserializer2::Allocate(int space_index, Space* space, int size) { |
+Address Deserializer::Allocate(int space_index, Space* space, int size) { |
Address address; |
if (!SpaceIsLarge(space_index)) { |
ASSERT(!SpaceIsPaged(space_index) || |
@@ -1825,7 +539,7 @@ |
// This returns the address of an object that has been described in the |
// snapshot as being offset bytes back in a particular space. |
-HeapObject* Deserializer2::GetAddressFromEnd(int space) { |
+HeapObject* Deserializer::GetAddressFromEnd(int space) { |
int offset = source_->GetInt(); |
ASSERT(!SpaceIsLarge(space)); |
offset <<= kObjectAlignmentBits; |
@@ -1835,7 +549,7 @@ |
// This returns the address of an object that has been described in the |
// snapshot as being offset bytes into a particular space. |
-HeapObject* Deserializer2::GetAddressFromStart(int space) { |
+HeapObject* Deserializer::GetAddressFromStart(int space) { |
int offset = source_->GetInt(); |
if (SpaceIsLarge(space)) { |
// Large spaces have one object per 'page'. |
@@ -1854,7 +568,7 @@ |
} |
-void Deserializer2::Deserialize() { |
+void Deserializer::Deserialize() { |
// Don't GC while deserializing - just expand the heap. |
AlwaysAllocateScope always_allocate; |
// Don't use the free lists while deserializing. |
@@ -1874,7 +588,7 @@ |
// This is called on the roots. It is the driver of the deserialization |
// process. It is also called on the body of each function. |
-void Deserializer2::VisitPointers(Object** start, Object** end) { |
+void Deserializer::VisitPointers(Object** start, Object** end) { |
// The space must be new space. Any other space would cause ReadChunk to try |
// to update the remembered using NULL as the address. |
ReadChunk(start, end, NEW_SPACE, NULL); |
@@ -1887,9 +601,9 @@ |
// written very late, which means the ByteArray map is not set up by the |
// time we need to use it to mark the space at the end of a page free (by |
// making it into a byte array). |
-void Deserializer2::ReadObject(int space_number, |
- Space* space, |
- Object** write_back) { |
+void Deserializer::ReadObject(int space_number, |
+ Space* space, |
+ Object** write_back) { |
int size = source_->GetInt() << kObjectAlignmentBits; |
Address address = Allocate(space_number, space, size); |
*write_back = HeapObject::FromAddress(address); |
@@ -1911,10 +625,10 @@ |
case (base_tag) + kLargeFixedArray: /* NOLINT */ |
-void Deserializer2::ReadChunk(Object** current, |
- Object** limit, |
- int space, |
- Address address) { |
+void Deserializer::ReadChunk(Object** current, |
+ Object** limit, |
+ int space, |
+ Address address) { |
while (current < limit) { |
int data = source_->Get(); |
switch (data) { |
@@ -2101,11 +815,11 @@ |
#ifdef DEBUG |
-void Deserializer2::Synchronize(const char* tag) { |
+void Deserializer::Synchronize(const char* tag) { |
int data = source_->Get(); |
// If this assert fails then that indicates that you have a mismatch between |
// the number of GC roots when serializing and deserializing. |
- ASSERT(data == SYNCHRONIZE); |
+ CHECK(data == SYNCHRONIZE); |
Christian Plesner Hansen
2009/11/13 13:43:36
Why is this not an ASSERT? Also CHECK_EQ?
|
do { |
int character = source_->Get(); |
if (character == 0) break; |
@@ -2119,7 +833,7 @@ |
} |
-void Serializer2::Synchronize(const char* tag) { |
+void Serializer::Synchronize(const char* tag) { |
sink_->Put(SYNCHRONIZE, tag); |
int character; |
do { |
@@ -2130,7 +844,7 @@ |
#endif |
-Serializer2::Serializer2(SnapshotByteSink* sink) |
+Serializer::Serializer(SnapshotByteSink* sink) |
: sink_(sink), |
current_root_index_(0), |
external_reference_encoder_(NULL) { |
@@ -2140,7 +854,7 @@ |
} |
-void Serializer2::Serialize() { |
+void Serializer::Serialize() { |
// No active threads. |
CHECK_EQ(NULL, ThreadState::FirstInUse()); |
// No active or weak handles. |
@@ -2154,7 +868,7 @@ |
} |
-void Serializer2::VisitPointers(Object** start, Object** end) { |
+void Serializer::VisitPointers(Object** start, Object** end) { |
for (Object** current = start; current < end; current++) { |
if ((*current)->IsSmi()) { |
sink_->Put(RAW_DATA_SERIALIZATION, "RawData"); |
@@ -2169,7 +883,7 @@ |
} |
-void Serializer2::SerializeObject( |
+void Serializer::SerializeObject( |
Object* o, |
ReferenceRepresentation reference_representation) { |
ASSERT(o->IsHeapObject()); |
@@ -2233,8 +947,8 @@ |
-void Serializer2::ObjectSerializer::Serialize() { |
- int space = Serializer2::SpaceOfObject(object_); |
+void Serializer::ObjectSerializer::Serialize() { |
+ int space = Serializer::SpaceOfObject(object_); |
int size = object_->Size(); |
if (reference_representation_ == TAGGED_REPRESENTATION) { |
@@ -2267,8 +981,8 @@ |
} |
-void Serializer2::ObjectSerializer::VisitPointers(Object** start, |
- Object** end) { |
+void Serializer::ObjectSerializer::VisitPointers(Object** start, |
+ Object** end) { |
Object** current = start; |
while (current < end) { |
while (current < end && (*current)->IsSmi()) current++; |
@@ -2283,8 +997,8 @@ |
} |
-void Serializer2::ObjectSerializer::VisitExternalReferences(Address* start, |
- Address* end) { |
+void Serializer::ObjectSerializer::VisitExternalReferences(Address* start, |
+ Address* end) { |
Address references_start = reinterpret_cast<Address>(start); |
OutputRawData(references_start); |
@@ -2297,7 +1011,7 @@ |
} |
-void Serializer2::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) { |
+void Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) { |
Address target_start = rinfo->target_address_address(); |
OutputRawData(target_start); |
Address target = rinfo->target_address(); |
@@ -2309,7 +1023,7 @@ |
} |
-void Serializer2::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) { |
+void Serializer::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) { |
ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); |
Address target_start = rinfo->target_address_address(); |
OutputRawData(target_start); |
@@ -2319,7 +1033,7 @@ |
} |
-void Serializer2::ObjectSerializer::VisitExternalAsciiString( |
+void Serializer::ObjectSerializer::VisitExternalAsciiString( |
v8::String::ExternalAsciiStringResource** resource_pointer) { |
Address references_start = reinterpret_cast<Address>(resource_pointer); |
OutputRawData(references_start); |
@@ -2346,7 +1060,7 @@ |
} |
-void Serializer2::ObjectSerializer::OutputRawData(Address up_to) { |
+void Serializer::ObjectSerializer::OutputRawData(Address up_to) { |
Address object_start = object_->address(); |
int up_to_offset = static_cast<int>(up_to - object_start); |
int skipped = up_to_offset - bytes_processed_so_far_; |
@@ -2374,7 +1088,7 @@ |
} |
-int Serializer2::SpaceOfObject(HeapObject* object) { |
+int Serializer::SpaceOfObject(HeapObject* object) { |
for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) { |
AllocationSpace s = static_cast<AllocationSpace>(i); |
if (Heap::InSpace(object, s)) { |
@@ -2395,7 +1109,7 @@ |
} |
-int Serializer2::SpaceOfAlreadySerializedObject(HeapObject* object) { |
+int Serializer::SpaceOfAlreadySerializedObject(HeapObject* object) { |
for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) { |
AllocationSpace s = static_cast<AllocationSpace>(i); |
if (Heap::InSpace(object, s)) { |
@@ -2407,7 +1121,7 @@ |
} |
-int Serializer2::Allocate(int space, int size, bool* new_page) { |
+int Serializer::Allocate(int space, int size, bool* new_page) { |
ASSERT(space >= 0 && space < kNumberOfSpaces); |
if (SpaceIsLarge(space)) { |
// In large object space we merely number the objects instead of trying to |