Chromium Code Reviews| 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 |