📄 mark-compact.cc.svn-base
字号:
#endif }};void MarkCompactCollector::UpdatePointers() {#ifdef DEBUG ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); state_ = UPDATE_POINTERS;#endif UpdatingVisitor updating_visitor; Heap::IterateRoots(&updating_visitor); GlobalHandles::IterateWeakRoots(&updating_visitor); int live_maps = IterateLiveObjects(Heap::map_space(), &UpdatePointersInOldObject); int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(), &UpdatePointersInOldObject); int live_data_olds = IterateLiveObjects(Heap::old_data_space(), &UpdatePointersInOldObject); int live_codes = IterateLiveObjects(Heap::code_space(), &UpdatePointersInOldObject); int live_news = IterateLiveObjects(Heap::new_space(), &UpdatePointersInNewObject); // Large objects do not move, the map word can be updated directly. LargeObjectIterator it(Heap::lo_space()); while (it.has_next()) UpdatePointersInNewObject(it.next()); USE(live_maps); USE(live_pointer_olds); USE(live_data_olds); USE(live_codes); 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_news == live_young_objects_); if (FLAG_verify_global_gc) VerifyHeapAfterUpdatingPointers();#endif}int MarkCompactCollector::UpdatePointersInNewObject(HeapObject* obj) { // Keep old map pointers Map* old_map = obj->map(); ASSERT(old_map->IsHeapObject()); Address forwarded = GetForwardingAddressInOldSpace(old_map); ASSERT(Heap::map_space()->Contains(old_map)); ASSERT(Heap::map_space()->Contains(forwarded));#ifdef DEBUG if (FLAG_gc_verbose) { PrintF("update %p : %p -> %p\n", obj->address(), old_map->address(), forwarded); }#endif // Update the map pointer. obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(forwarded))); // We have to compute the object size relying on the old map because // map objects are not relocated yet. int obj_size = obj->SizeFromMap(old_map); // Update pointers in the object body. UpdatingVisitor updating_visitor; obj->IterateBody(old_map->instance_type(), obj_size, &updating_visitor); return obj_size;}int MarkCompactCollector::UpdatePointersInOldObject(HeapObject* obj) { // Decode the map pointer. MapWord encoding = obj->map_word(); Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr))); // At this point, the first word of map_addr is also encoded, cannot // cast it to Map* using Map::cast. Map* map = reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr)); int obj_size = obj->SizeFromMap(map); InstanceType type = map->instance_type(); // Update map pointer. Address new_map_addr = GetForwardingAddressInOldSpace(map); int offset = encoding.DecodeOffset(); obj->set_map_word(MapWord::EncodeAddress(new_map_addr, offset));#ifdef DEBUG if (FLAG_gc_verbose) { PrintF("update %p : %p -> %p\n", obj->address(), map_addr, new_map_addr); }#endif // Update pointers in the object body. UpdatingVisitor updating_visitor; obj->IterateBody(type, obj_size, &updating_visitor); return obj_size;}Address MarkCompactCollector::GetForwardingAddressInOldSpace(HeapObject* obj) { // Object should either in old or map space. MapWord encoding = obj->map_word(); // Offset to the first live object's forwarding address. int offset = encoding.DecodeOffset(); Address obj_addr = obj->address(); // Find the first live object's forwarding address. Page* p = Page::FromAddress(obj_addr); Address first_forwarded = p->mc_first_forwarded; // Page start address of forwarded address. Page* forwarded_page = Page::FromAddress(first_forwarded); int forwarded_offset = forwarded_page->Offset(first_forwarded); // Find end of allocation of in the page of first_forwarded. Address mc_top = forwarded_page->mc_relocation_top; int mc_top_offset = forwarded_page->Offset(mc_top); // Check if current object's forward pointer is in the same page // as the first live object's forwarding pointer if (forwarded_offset + offset < mc_top_offset) { // In the same page. return first_forwarded + offset; } // Must be in the next page, NOTE: this may cross chunks. Page* next_page = forwarded_page->next_page(); ASSERT(next_page->is_valid()); offset -= (mc_top_offset - forwarded_offset); offset += Page::kObjectStartOffset; ASSERT_PAGE_OFFSET(offset); ASSERT(next_page->OffsetToAddress(offset) < next_page->mc_relocation_top); return next_page->OffsetToAddress(offset);}#ifdef DEBUGvoid MarkCompactCollector::VerifyHeapAfterUpdatingPointers() { ASSERT(state_ == UPDATE_POINTERS); AllSpaces spaces; while (Space* space = spaces.next()) space->Verify(); PagedSpaces paged_spaces; while (PagedSpace* space = paged_spaces.next()) VerifyPageHeaders(space);}#endif// ----------------------------------------------------------------------------// Phase 4: Relocate objectsvoid MarkCompactCollector::RelocateObjects() {#ifdef DEBUG ASSERT(state_ == UPDATE_POINTERS); state_ = RELOCATE_OBJECTS;#endif // Relocates objects, always relocate map objects first. Relocating // objects in other space relies on map objects to get object size. int live_maps = IterateLiveObjects(Heap::map_space(), &RelocateMapObject); int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(), &RelocateOldPointerObject); int live_data_olds = IterateLiveObjects(Heap::old_data_space(), &RelocateOldDataObject); int live_codes = IterateLiveObjects(Heap::code_space(), &RelocateCodeObject); int live_news = IterateLiveObjects(Heap::new_space(), &RelocateNewObject); USE(live_maps); USE(live_data_olds); USE(live_pointer_olds); USE(live_codes); 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_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 Heap::new_space()->Flip(); // Sets age_mark to bottom in to space Address mark = Heap::new_space()->bottom(); Heap::new_space()->set_age_mark(mark); Heap::new_space()->MCCommitRelocationInfo();#ifdef DEBUG // It is safe to write to the remembered sets as remembered sets on a // page-by-page basis after committing the m-c forwarding pointer. Page::set_rset_state(Page::IN_USE);#endif PagedSpaces spaces; while (PagedSpace* space = spaces.next()) space->MCCommitRelocationInfo();#ifdef DEBUG if (FLAG_verify_global_gc) VerifyHeapAfterRelocatingObjects();#endif}int MarkCompactCollector::ConvertCodeICTargetToAddress(HeapObject* obj) { if (obj->IsCode()) { Code::cast(obj)->ConvertICTargetsFromObjectToAddress(); } return obj->Size();}int MarkCompactCollector::RelocateMapObject(HeapObject* obj) { // decode map pointer (forwarded address) MapWord encoding = obj->map_word(); Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr))); // Get forwarding address before resetting map pointer Address new_addr = GetForwardingAddressInOldSpace(obj); // recover map pointer 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) { memmove(new_addr, old_addr, Map::kSize); // copy contents }#ifdef DEBUG if (FLAG_gc_verbose) { PrintF("relocate %p -> %p\n", old_addr, new_addr); }#endif return Map::kSize;}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))); // 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); }#endif return obj_size;}int MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj, OldSpace* space) { // decode map pointer (forwarded address) 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 Address new_addr = GetForwardingAddressInOldSpace(obj); int obj_size = RelocateOldObject(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 } ASSERT(!HeapObject::FromAddress(new_addr)->IsCode()); return obj_size;}int MarkCompactCollector::RelocateOldPointerObject(HeapObject* obj) { return RelocateOldNonCodeObject(obj, Heap::old_pointer_space());}int MarkCompactCollector::RelocateOldDataObject(HeapObject* obj) { return RelocateOldNonCodeObject(obj, Heap::old_data_space());}int MarkCompactCollector::RelocateCodeObject(HeapObject* obj) { // decode map pointer (forwarded address) MapWord encoding = obj->map_word(); Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr))); // Get forwarding address before resetting map pointer Address new_addr = GetForwardingAddressInOldSpace(obj); int obj_size = RelocateOldObject(obj, Heap::code_space(), new_addr, map_addr); // 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 } HeapObject* copied_to = HeapObject::FromAddress(new_addr); if (copied_to->IsCode()) { // may also update inline cache target. Code::cast(copied_to)->Relocate(new_addr - old_addr); // Notify the logger that compile code has moved. LOG(CodeMoveEvent(old_addr, new_addr)); } return obj_size;}#ifdef DEBUGclass VerifyCopyingVisitor: public ObjectVisitor { public: void VisitPointers(Object** start, Object** end) { for (Object** p = start; p < end; p++) { MarkCompactCollector::VerifyCopyingObjects(p); } }};#endifint MarkCompactCollector::RelocateNewObject(HeapObject* obj) { int obj_size = obj->Size(); // Get forwarding address Address old_addr = obj->address(); int offset = Heap::new_space()->ToSpaceOffsetForAddress(old_addr); Address new_addr = Memory::Address_at(Heap::new_space()->FromSpaceLow() + offset); 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); } // New and old addresses cannot overlap. memcpy(reinterpret_cast<void*>(new_addr), reinterpret_cast<void*>(old_addr), obj_size);#ifdef DEBUG if (FLAG_gc_verbose) { PrintF("relocate %p -> %p\n", old_addr, new_addr); } if (FLAG_verify_global_gc) { VerifyCopyingVisitor v; HeapObject* copied_to = HeapObject::FromAddress(new_addr); copied_to->Iterate(&v); }#endif return obj_size;}#ifdef DEBUGvoid MarkCompactCollector::VerifyHeapAfterRelocatingObjects() { ASSERT(state_ == RELOCATE_OBJECTS); Heap::new_space()->Verify(); PagedSpaces spaces; while (PagedSpace* space = spaces.next()) { space->Verify(); PageIterator it(space, PageIterator::PAGES_IN_USE); while (it.has_next()) { Page* p = it.next(); ASSERT_PAGE_OFFSET(p->Offset(p->AllocationTop())); } }}#endif#ifdef DEBUGvoid MarkCompactCollector::VerifyCopyingObjects(Object** p) { if (!(*p)->IsHeapObject()) return; ASSERT(!Heap::InToSpace(*p));}#endif // DEBUG// -----------------------------------------------------------------------------// Phase 5: rebuild remembered setsvoid MarkCompactCollector::RebuildRSets() {#ifdef DEBUG ASSERT(state_ == RELOCATE_OBJECTS); state_ = REBUILD_RSETS;#endif Heap::RebuildRSets();}} } // namespace v8::internal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -