diff options
Diffstat (limited to 'V8Binding/v8/src/mark-compact.cc')
-rw-r--r-- | V8Binding/v8/src/mark-compact.cc | 189 |
1 files changed, 111 insertions, 78 deletions
diff --git a/V8Binding/v8/src/mark-compact.cc b/V8Binding/v8/src/mark-compact.cc index 5e46f2a..6e823b3 100644 --- a/V8Binding/v8/src/mark-compact.cc +++ b/V8Binding/v8/src/mark-compact.cc @@ -56,6 +56,7 @@ int MarkCompactCollector::live_old_data_objects_ = 0; int MarkCompactCollector::live_old_pointer_objects_ = 0; int MarkCompactCollector::live_code_objects_ = 0; int MarkCompactCollector::live_map_objects_ = 0; +int MarkCompactCollector::live_cell_objects_ = 0; int MarkCompactCollector::live_lo_objects_ = 0; #endif @@ -155,6 +156,7 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) { live_old_data_objects_ = 0; live_code_objects_ = 0; live_map_objects_ = 0; + live_cell_objects_ = 0; live_lo_objects_ = 0; #endif } @@ -224,7 +226,9 @@ static inline HeapObject* ShortCircuitConsString(Object** p) { if ((type & kShortcutTypeMask) != kShortcutTypeTag) return object; Object* second = reinterpret_cast<ConsString*>(object)->unchecked_second(); - if (reinterpret_cast<String*>(second) != Heap::empty_string()) return object; + if (second != Heap::raw_unchecked_empty_string()) { + return object; + } // Since we don't have the object's start, it is impossible to update the // remembered set. Therefore, we only replace the string with its left @@ -421,7 +425,7 @@ class SymbolTableCleaner : public ObjectVisitor { } } // Set the entry to null_value (as deleted). - *p = Heap::null_value(); + *p = Heap::raw_unchecked_null_value(); pointers_removed_++; } } @@ -475,7 +479,7 @@ void MarkCompactCollector::MarkDescriptorArray( DescriptorArray* descriptors) { if (descriptors->IsMarked()) return; // Empty descriptor array is marked as a root before any maps are marked. - ASSERT(descriptors != Heap::empty_descriptor_array()); + ASSERT(descriptors != Heap::raw_unchecked_empty_descriptor_array()); SetMark(descriptors); FixedArray* contents = reinterpret_cast<FixedArray*>( @@ -590,7 +594,7 @@ void MarkCompactCollector::MarkSymbolTable() { // and if it is a sliced string or a cons string backed by an // external string (even indirectly), then the external string does // not receive a weak reference callback. - SymbolTable* symbol_table = SymbolTable::cast(Heap::symbol_table()); + SymbolTable* symbol_table = Heap::raw_unchecked_symbol_table(); // Mark the symbol table itself. SetMark(symbol_table); // Explicitly mark the prefix. @@ -708,6 +712,10 @@ void MarkCompactCollector::RefillMarkingStack() { ScanOverflowedObjects(&map_it); if (marking_stack.is_full()) return; + HeapObjectIterator cell_it(Heap::cell_space(), &OverflowObjectSize); + ScanOverflowedObjects(&cell_it); + if (marking_stack.is_full()) return; + LargeObjectIterator lo_it(Heap::lo_space(), &OverflowObjectSize); ScanOverflowedObjects(&lo_it); if (marking_stack.is_full()) return; @@ -780,10 +788,9 @@ void MarkCompactCollector::MarkLiveObjects() { ProcessObjectGroups(root_visitor.stack_visitor()); // Prune the symbol table removing all symbols only pointed to by the - // symbol table. Cannot use SymbolTable::cast here because the symbol + // symbol table. Cannot use symbol_table() here because the symbol // table is marked. - SymbolTable* symbol_table = - reinterpret_cast<SymbolTable*>(Heap::symbol_table()); + SymbolTable* symbol_table = Heap::raw_unchecked_symbol_table(); SymbolTableCleaner v; symbol_table->IterateElements(&v); symbol_table->ElementsRemoved(v.PointersRemoved()); @@ -808,6 +815,9 @@ void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) { } else if (Heap::map_space()->Contains(obj)) { ASSERT(obj->IsMap()); live_map_objects_++; + } else if (Heap::cell_space()->Contains(obj)) { + ASSERT(obj->IsJSGlobalPropertyCell()); + live_cell_objects_++; } else if (Heap::old_pointer_space()->Contains(obj)) { live_old_pointer_objects_++; } else if (Heap::old_data_space()->Contains(obj)) { @@ -967,27 +977,32 @@ inline Object* MCAllocateFromNewSpace(HeapObject* object, int object_size) { // Allocation functions for the paged spaces call the space's MCAllocateRaw. -inline Object* MCAllocateFromOldPointerSpace(HeapObject* object, +inline Object* MCAllocateFromOldPointerSpace(HeapObject* ignore, int object_size) { return Heap::old_pointer_space()->MCAllocateRaw(object_size); } -inline Object* MCAllocateFromOldDataSpace(HeapObject* object, int object_size) { +inline Object* MCAllocateFromOldDataSpace(HeapObject* ignore, int object_size) { return Heap::old_data_space()->MCAllocateRaw(object_size); } -inline Object* MCAllocateFromCodeSpace(HeapObject* object, int object_size) { +inline Object* MCAllocateFromCodeSpace(HeapObject* ignore, int object_size) { return Heap::code_space()->MCAllocateRaw(object_size); } -inline Object* MCAllocateFromMapSpace(HeapObject* object, int object_size) { +inline Object* MCAllocateFromMapSpace(HeapObject* ignore, int object_size) { return Heap::map_space()->MCAllocateRaw(object_size); } +inline Object* MCAllocateFromCellSpace(HeapObject* ignore, int object_size) { + return Heap::cell_space()->MCAllocateRaw(object_size); +} + + // The forwarding address is encoded at the same offset as the current // to-space object, but in from space. inline void EncodeForwardingAddressInNewSpace(HeapObject* old_object, @@ -1142,11 +1157,11 @@ static void SweepSpace(NewSpace* space) { // since their existing map might not be live after the collection. int size = object->Size(); if (size >= ByteArray::kHeaderSize) { - object->set_map(Heap::byte_array_map()); + object->set_map(Heap::raw_unchecked_byte_array_map()); ByteArray::cast(object)->set_length(ByteArray::LengthFor(size)); } else { ASSERT(size == kPointerSize); - object->set_map(Heap::one_word_filler_map()); + object->set_map(Heap::raw_unchecked_one_pointer_filler_map()); } ASSERT(object->Size() == size); } @@ -1196,8 +1211,8 @@ static void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) { // loop. } - // If the last region was not live we need to from free_start to the - // allocation top in the page. + // If the last region was not live we need to deallocate from + // free_start to the allocation top in the page. if (!is_previous_alive) { int free_size = p->AllocationTop() - free_start; if (free_size > 0) { @@ -1241,6 +1256,21 @@ void MarkCompactCollector::DeallocateMapBlock(Address start, } +void MarkCompactCollector::DeallocateCellBlock(Address start, + int size_in_bytes) { + // Free-list elements in cell space are assumed to have a fixed size. + // We break the free block into chunks and add them to the free list + // individually. + int size = Heap::cell_space()->object_size_in_bytes(); + ASSERT(size_in_bytes % size == 0); + Heap::ClearRSetRange(start, size_in_bytes); + Address end = start + size_in_bytes; + for (Address a = start; a < end; a += size) { + Heap::cell_space()->Free(a); + } +} + + void MarkCompactCollector::EncodeForwardingAddresses() { ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); // Objects in the active semispace of the young generation may be @@ -1261,6 +1291,11 @@ void MarkCompactCollector::EncodeForwardingAddresses() { LogNonLiveCodeObject>( Heap::code_space()); + EncodeForwardingAddressesInPagedSpace<MCAllocateFromCellSpace, + IgnoreNonLiveObject>( + Heap::cell_space()); + + // Compute new space next to last after the old and code spaces have been // compacted. Objects in new space can be promoted to old or code space. EncodeForwardingAddressesInNewSpace(); @@ -1279,6 +1314,7 @@ void MarkCompactCollector::EncodeForwardingAddresses() { Heap::old_data_space()->MCWriteRelocationInfoToPage(); Heap::code_space()->MCWriteRelocationInfoToPage(); Heap::map_space()->MCWriteRelocationInfoToPage(); + Heap::cell_space()->MCWriteRelocationInfoToPage(); } @@ -1293,6 +1329,7 @@ void MarkCompactCollector::SweepSpaces() { SweepSpace(Heap::old_pointer_space(), &DeallocateOldPointerBlock); SweepSpace(Heap::old_data_space(), &DeallocateOldDataBlock); SweepSpace(Heap::code_space(), &DeallocateCodeBlock); + SweepSpace(Heap::cell_space(), &DeallocateCellBlock); SweepSpace(Heap::new_space()); SweepSpace(Heap::map_space(), &DeallocateMapBlock); } @@ -1371,15 +1408,16 @@ class UpdatingVisitor: public ObjectVisitor { ASSERT(!Heap::InFromSpace(obj)); if (Heap::new_space()->Contains(obj)) { - Address f_addr = Heap::new_space()->FromSpaceLow() + - Heap::new_space()->ToSpaceOffsetForAddress(old_addr); - new_addr = Memory::Address_at(f_addr); + Address forwarding_pointer_addr = + Heap::new_space()->FromSpaceLow() + + Heap::new_space()->ToSpaceOffsetForAddress(old_addr); + new_addr = Memory::Address_at(forwarding_pointer_addr); #ifdef DEBUG ASSERT(Heap::old_pointer_space()->Contains(new_addr) || Heap::old_data_space()->Contains(new_addr) || - Heap::code_space()->Contains(new_addr) || - Heap::new_space()->FromSpaceContains(new_addr)); + Heap::new_space()->FromSpaceContains(new_addr) || + Heap::lo_space()->Contains(HeapObject::FromAddress(new_addr))); if (Heap::new_space()->FromSpaceContains(new_addr)) { ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <= @@ -1392,32 +1430,19 @@ class UpdatingVisitor: public ObjectVisitor { return; } else { - ASSERT(Heap::old_pointer_space()->Contains(obj) || - Heap::old_data_space()->Contains(obj) || - Heap::code_space()->Contains(obj) || - Heap::map_space()->Contains(obj)); - - new_addr = MarkCompactCollector::GetForwardingAddressInOldSpace(obj); - ASSERT(Heap::old_pointer_space()->Contains(new_addr) || - Heap::old_data_space()->Contains(new_addr) || - Heap::code_space()->Contains(new_addr) || - Heap::map_space()->Contains(new_addr)); - #ifdef DEBUG - if (Heap::old_pointer_space()->Contains(obj)) { - ASSERT(Heap::old_pointer_space()->MCSpaceOffsetForAddress(new_addr) <= - Heap::old_pointer_space()->MCSpaceOffsetForAddress(old_addr)); - } else if (Heap::old_data_space()->Contains(obj)) { - ASSERT(Heap::old_data_space()->MCSpaceOffsetForAddress(new_addr) <= - Heap::old_data_space()->MCSpaceOffsetForAddress(old_addr)); - } else if (Heap::code_space()->Contains(obj)) { - ASSERT(Heap::code_space()->MCSpaceOffsetForAddress(new_addr) <= - Heap::code_space()->MCSpaceOffsetForAddress(old_addr)); - } else { - ASSERT(Heap::map_space()->MCSpaceOffsetForAddress(new_addr) <= - Heap::map_space()->MCSpaceOffsetForAddress(old_addr)); + PagedSpaces spaces; + PagedSpace* original_space = spaces.next(); + while (original_space != NULL) { + if (original_space->Contains(obj)) break; + original_space = spaces.next(); } + ASSERT(original_space != NULL); #endif + new_addr = MarkCompactCollector::GetForwardingAddressInOldSpace(obj); + ASSERT(original_space->Contains(new_addr)); + ASSERT(original_space->MCSpaceOffsetForAddress(new_addr) <= + original_space->MCSpaceOffsetForAddress(old_addr)); } *p = HeapObject::FromAddress(new_addr); @@ -1449,6 +1474,8 @@ void MarkCompactCollector::UpdatePointers() { &UpdatePointersInOldObject); int live_codes = IterateLiveObjects(Heap::code_space(), &UpdatePointersInOldObject); + int live_cells = IterateLiveObjects(Heap::cell_space(), + &UpdatePointersInOldObject); int live_news = IterateLiveObjects(Heap::new_space(), &UpdatePointersInNewObject); @@ -1460,15 +1487,14 @@ void MarkCompactCollector::UpdatePointers() { USE(live_pointer_olds); USE(live_data_olds); USE(live_codes); + USE(live_cells); USE(live_news); - -#ifdef DEBUG ASSERT(live_maps == live_map_objects_); ASSERT(live_data_olds == live_old_data_objects_); ASSERT(live_pointer_olds == live_old_pointer_objects_); ASSERT(live_codes == live_code_objects_); + ASSERT(live_cells == live_cell_objects_); ASSERT(live_news == live_young_objects_); -#endif } @@ -1589,30 +1615,31 @@ void MarkCompactCollector::RelocateObjects() { int live_data_olds = IterateLiveObjects(Heap::old_data_space(), &RelocateOldDataObject); int live_codes = IterateLiveObjects(Heap::code_space(), &RelocateCodeObject); + int live_cells = IterateLiveObjects(Heap::cell_space(), &RelocateCellObject); int live_news = IterateLiveObjects(Heap::new_space(), &RelocateNewObject); USE(live_maps); USE(live_data_olds); USE(live_pointer_olds); USE(live_codes); + USE(live_cells); USE(live_news); -#ifdef DEBUG ASSERT(live_maps == live_map_objects_); ASSERT(live_data_olds == live_old_data_objects_); ASSERT(live_pointer_olds == live_old_pointer_objects_); ASSERT(live_codes == live_code_objects_); + ASSERT(live_cells == live_cell_objects_); ASSERT(live_news == live_young_objects_); -#endif // Notify code object in LO to convert IC target to address // This must happen after lo_space_->Compact LargeObjectIterator it(Heap::lo_space()); while (it.has_next()) { ConvertCodeICTargetToAddress(it.next()); } - // Flips from and to spaces + // Flip from and to spaces Heap::new_space()->Flip(); - // Sets age_mark to bottom in to space + // Set age_mark to bottom in to space Address mark = Heap::new_space()->bottom(); Heap::new_space()->set_age_mark(mark); @@ -1636,7 +1663,7 @@ int MarkCompactCollector::ConvertCodeICTargetToAddress(HeapObject* obj) { int MarkCompactCollector::RelocateMapObject(HeapObject* obj) { - // decode map pointer (forwarded address) + // Recover map pointer. MapWord encoding = obj->map_word(); Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr))); @@ -1644,10 +1671,10 @@ int MarkCompactCollector::RelocateMapObject(HeapObject* obj) { // Get forwarding address before resetting map pointer Address new_addr = GetForwardingAddressInOldSpace(obj); - // recover map pointer + // Reset map pointer. The meta map object may not be copied yet so + // Map::cast does not yet work. obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr))); - // The meta map object may not be copied yet. Address old_addr = obj->address(); if (new_addr != old_addr) { @@ -1664,23 +1691,23 @@ int MarkCompactCollector::RelocateMapObject(HeapObject* obj) { } -static inline int RelocateOldObject(HeapObject* obj, - OldSpace* space, - Address new_addr, - Address map_addr) { - // recover map pointer - obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr))); +static inline int RestoreMap(HeapObject* obj, + PagedSpace* space, + Address new_addr, + Address map_addr) { + // This must be a non-map object, and the function relies on the + // assumption that the Map space is compacted before the other paged + // spaces (see RelocateObjects). + + // Reset map pointer. + obj->set_map(Map::cast(HeapObject::FromAddress(map_addr))); - // This is a non-map object, it relies on the assumption that the Map space - // is compacted before the Old space (see RelocateObjects). int obj_size = obj->Size(); ASSERT_OBJECT_SIZE(obj_size); ASSERT(space->MCSpaceOffsetForAddress(new_addr) <= space->MCSpaceOffsetForAddress(obj->address())); - space->MCAdjustRelocationEnd(new_addr, obj_size); - #ifdef DEBUG if (FLAG_gc_verbose) { PrintF("relocate %p -> %p\n", obj->address(), new_addr); @@ -1692,21 +1719,22 @@ static inline int RelocateOldObject(HeapObject* obj, int MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj, - OldSpace* space) { - // decode map pointer (forwarded address) + PagedSpace* space) { + // Recover map pointer. MapWord encoding = obj->map_word(); Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); ASSERT(Heap::map_space()->Contains(map_addr)); - // Get forwarding address before resetting map pointer + // Get forwarding address before resetting map pointer. Address new_addr = GetForwardingAddressInOldSpace(obj); - int obj_size = RelocateOldObject(obj, space, new_addr, map_addr); + // Reset the map pointer. + int obj_size = RestoreMap(obj, space, new_addr, map_addr); Address old_addr = obj->address(); if (new_addr != old_addr) { - memmove(new_addr, old_addr, obj_size); // copy contents + memmove(new_addr, old_addr, obj_size); // Copy contents } ASSERT(!HeapObject::FromAddress(new_addr)->IsCode()); @@ -1725,8 +1753,13 @@ int MarkCompactCollector::RelocateOldDataObject(HeapObject* obj) { } +int MarkCompactCollector::RelocateCellObject(HeapObject* obj) { + return RelocateOldNonCodeObject(obj, Heap::cell_space()); +} + + int MarkCompactCollector::RelocateCodeObject(HeapObject* obj) { - // decode map pointer (forwarded address) + // Recover map pointer. MapWord encoding = obj->map_word(); Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr))); @@ -1734,23 +1767,23 @@ int MarkCompactCollector::RelocateCodeObject(HeapObject* obj) { // Get forwarding address before resetting map pointer Address new_addr = GetForwardingAddressInOldSpace(obj); - int obj_size = RelocateOldObject(obj, Heap::code_space(), new_addr, map_addr); + // Reset the map pointer. + int obj_size = RestoreMap(obj, Heap::code_space(), new_addr, map_addr); - // convert inline cache target to address using old address + // Convert inline cache target to address using old address. if (obj->IsCode()) { - // convert target to address first related to old_address Code::cast(obj)->ConvertICTargetsFromObjectToAddress(); } Address old_addr = obj->address(); if (new_addr != old_addr) { - memmove(new_addr, old_addr, obj_size); // copy contents + memmove(new_addr, old_addr, obj_size); // Copy contents. } HeapObject* copied_to = HeapObject::FromAddress(new_addr); if (copied_to->IsCode()) { - // may also update inline cache target. + // May also update inline cache target. Code::cast(copied_to)->Relocate(new_addr - old_addr); // Notify the logger that compiled code has moved. LOG(CodeMoveEvent(old_addr, new_addr)); @@ -1770,15 +1803,15 @@ int MarkCompactCollector::RelocateNewObject(HeapObject* obj) { Address new_addr = Memory::Address_at(Heap::new_space()->FromSpaceLow() + offset); +#ifdef DEBUG if (Heap::new_space()->FromSpaceContains(new_addr)) { ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <= Heap::new_space()->ToSpaceOffsetForAddress(old_addr)); } else { - OldSpace* target_space = Heap::TargetSpace(obj); - ASSERT(target_space == Heap::old_pointer_space() || - target_space == Heap::old_data_space()); - target_space->MCAdjustRelocationEnd(new_addr, obj_size); + ASSERT(Heap::TargetSpace(obj) == Heap::old_pointer_space() || + Heap::TargetSpace(obj) == Heap::old_data_space()); } +#endif // New and old addresses cannot overlap. memcpy(reinterpret_cast<void*>(new_addr), |