From abede994d9493ecbbb4856f3cfbbc0c3f692b858 Mon Sep 17 00:00:00 2001 From: "mstarzinger@chromium.org" Date: Wed, 25 Jul 2012 15:23:07 +0000 Subject: [PATCH] Refactor incremental marking to use static visitor. This is a refactoring only change that switches incremental marking to use a static object visitor. It also shares the common code between the non-incremental and the incremental marker. Sharing that would require semantical changes will be done later. R=verwaest@chromium.org Review URL: https://chromiumcodereview.appspot.com/10816007 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12193 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/heap.h | 2 +- src/incremental-marking.cc | 162 ++++++++++++++++---------------- src/incremental-marking.h | 4 +- src/mark-compact.cc | 228 ++++++++++----------------------------------- src/mark-compact.h | 2 +- src/objects-visiting-inl.h | 135 ++++++++++++++++++++++++++- src/objects-visiting.h | 68 +++++++++++++- src/objects.cc | 9 +- src/objects.h | 4 - 9 files changed, 333 insertions(+), 281 deletions(-) diff --git a/src/heap.h b/src/heap.h index b7caee7..85a64ec 100644 --- a/src/heap.h +++ b/src/heap.h @@ -2108,7 +2108,7 @@ class Heap { friend class Page; friend class Isolate; friend class MarkCompactCollector; - friend class StaticMarkingVisitor; + friend class MarkCompactMarkingVisitor; friend class MapCompact; DISALLOW_COPY_AND_ASSIGN(Heap); diff --git a/src/incremental-marking.cc b/src/incremental-marking.cc index 93fa544..ebbee25 100644 --- a/src/incremental-marking.cc +++ b/src/incremental-marking.cc @@ -31,6 +31,8 @@ #include "code-stubs.h" #include "compilation-cache.h" +#include "objects-visiting.h" +#include "objects-visiting-inl.h" #include "v8conversions.h" namespace v8 { @@ -160,93 +162,109 @@ void IncrementalMarking::RecordWriteIntoCodeSlow(HeapObject* obj, } -class IncrementalMarkingMarkingVisitor : public ObjectVisitor { +class IncrementalMarkingMarkingVisitor + : public StaticMarkingVisitor { public: - IncrementalMarkingMarkingVisitor(Heap* heap, - IncrementalMarking* incremental_marking) - : heap_(heap), - incremental_marking_(incremental_marking) { + static void Initialize() { + StaticMarkingVisitor::Initialize(); + + table_.Register(kVisitSharedFunctionInfo, &VisitSharedFunctionInfo); + + table_.Register(kVisitJSFunction, &VisitJSFunction); + + table_.Register(kVisitJSRegExp, &VisitJSRegExp); } - void VisitEmbeddedPointer(RelocInfo* rinfo) { + static inline void VisitEmbeddedPointer(Heap* heap, RelocInfo* rinfo) { ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); Object* target = rinfo->target_object(); if (target->NonFailureIsHeapObject()) { - heap_->mark_compact_collector()->RecordRelocSlot(rinfo, target); - MarkObject(target); + heap->mark_compact_collector()->RecordRelocSlot(rinfo, target); + MarkObject(heap, target); } } - void VisitCodeTarget(RelocInfo* rinfo) { + static inline void VisitCodeTarget(Heap* heap, RelocInfo* rinfo) { ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); if (FLAG_cleanup_code_caches_at_gc && target->is_inline_cache_stub() - && (target->ic_age() != heap_->global_ic_age())) { + && (target->ic_age() != heap->global_ic_age())) { IC::Clear(rinfo->pc()); target = Code::GetCodeFromTargetAddress(rinfo->target_address()); } - heap_->mark_compact_collector()->RecordRelocSlot(rinfo, Code::cast(target)); - MarkObject(target); + heap->mark_compact_collector()->RecordRelocSlot(rinfo, Code::cast(target)); + MarkObject(heap, target); } - void VisitDebugTarget(RelocInfo* rinfo) { - ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && - rinfo->IsPatchedReturnSequence()) || - (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && - rinfo->IsPatchedDebugBreakSlotSequence())); - Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); - heap_->mark_compact_collector()->RecordRelocSlot(rinfo, Code::cast(target)); - MarkObject(target); + static void VisitCode(Map* map, HeapObject* object) { + Heap* heap = map->GetHeap(); + Code* code = reinterpret_cast(object); + code->CodeIterateBody(heap); } - void VisitCodeEntry(Address entry_address) { - Object* target = Code::GetObjectFromEntryAddress(entry_address); - heap_->mark_compact_collector()-> - RecordCodeEntrySlot(entry_address, Code::cast(target)); - MarkObject(target); + static void VisitJSWeakMap(Map* map, HeapObject* object) { + Heap* heap = map->GetHeap(); + VisitPointers(heap, + HeapObject::RawField(object, JSWeakMap::kPropertiesOffset), + HeapObject::RawField(object, JSWeakMap::kSize)); } - void VisitSharedFunctionInfo(SharedFunctionInfo* shared) { - if (shared->ic_age() != heap_->global_ic_age()) { - shared->ResetForNewContext(heap_->global_ic_age()); + static void VisitSharedFunctionInfo(Map* map, HeapObject* object) { + Heap* heap = map->GetHeap(); + SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); + if (shared->ic_age() != heap->global_ic_age()) { + shared->ResetForNewContext(heap->global_ic_age()); } - } - - void VisitPointer(Object** p) { + FixedBodyVisitor::Visit(map, object); + } + + static inline void VisitJSFunction(Map* map, HeapObject* object) { + Heap* heap = map->GetHeap(); + // Iterate over all fields in the body but take care in dealing with + // the code entry and skip weak fields. + VisitPointers(heap, + HeapObject::RawField(object, JSFunction::kPropertiesOffset), + HeapObject::RawField(object, JSFunction::kCodeEntryOffset)); + VisitCodeEntry(heap, object->address() + JSFunction::kCodeEntryOffset); + VisitPointers(heap, + HeapObject::RawField(object, + JSFunction::kCodeEntryOffset + kPointerSize), + HeapObject::RawField(object, + JSFunction::kNonWeakFieldsEndOffset)); + } + + INLINE(static void VisitPointer(Heap* heap, Object** p)) { Object* obj = *p; if (obj->NonFailureIsHeapObject()) { - heap_->mark_compact_collector()->RecordSlot(p, p, obj); - MarkObject(obj); + heap->mark_compact_collector()->RecordSlot(p, p, obj); + MarkObject(heap, obj); } } - void VisitPointers(Object** start, Object** end) { + INLINE(static void VisitPointers(Heap* heap, Object** start, Object** end)) { for (Object** p = start; p < end; p++) { Object* obj = *p; if (obj->NonFailureIsHeapObject()) { - heap_->mark_compact_collector()->RecordSlot(start, p, obj); - MarkObject(obj); + heap->mark_compact_collector()->RecordSlot(start, p, obj); + MarkObject(heap, obj); } } } - private: - // Mark object pointed to by p. - INLINE(void MarkObject(Object* obj)) { + INLINE(static void MarkObject(Heap* heap, Object* obj)) { HeapObject* heap_object = HeapObject::cast(obj); MarkBit mark_bit = Marking::MarkBitFrom(heap_object); if (mark_bit.data_only()) { - if (incremental_marking_->MarkBlackOrKeepGrey(mark_bit)) { + if (heap->incremental_marking()->MarkBlackOrKeepGrey(mark_bit)) { MemoryChunk::IncrementLiveBytesFromGC(heap_object->address(), heap_object->Size()); } } else if (Marking::IsWhite(mark_bit)) { - incremental_marking_->WhiteToGreyAndPush(heap_object, mark_bit); + heap->incremental_marking()->WhiteToGreyAndPush(heap_object, mark_bit); } } - - Heap* heap_; - IncrementalMarking* incremental_marking_; }; @@ -290,6 +308,11 @@ class IncrementalMarkingRootMarkingVisitor : public ObjectVisitor { }; +void IncrementalMarking::Initialize() { + IncrementalMarkingMarkingVisitor::Initialize(); +} + + void IncrementalMarking::SetOldSpacePageFlags(MemoryChunk* chunk, bool is_marking, bool is_compacting) { @@ -623,24 +646,6 @@ void IncrementalMarking::UpdateMarkingDequeAfterScavenge() { } -void IncrementalMarking::VisitGlobalContext(Context* ctx, ObjectVisitor* v) { - v->VisitPointers( - HeapObject::RawField( - ctx, Context::MarkCompactBodyDescriptor::kStartOffset), - HeapObject::RawField( - ctx, Context::MarkCompactBodyDescriptor::kEndOffset)); - - MarkCompactCollector* collector = heap_->mark_compact_collector(); - for (int idx = Context::FIRST_WEAK_SLOT; - idx < Context::GLOBAL_CONTEXT_SLOTS; - ++idx) { - Object** slot = - HeapObject::RawField(ctx, FixedArray::OffsetOfElementAt(idx)); - collector->RecordSlot(slot, slot, *slot); - } -} - - void IncrementalMarking::Hurry() { if (state() == MARKING) { double start = 0.0; @@ -652,7 +657,6 @@ void IncrementalMarking::Hurry() { // was stopped. Map* filler_map = heap_->one_pointer_filler_map(); Map* global_context_map = heap_->global_context_map(); - IncrementalMarkingMarkingVisitor marking_visitor(heap_, this); while (!marking_deque_.IsEmpty()) { HeapObject* obj = marking_deque_.Pop(); @@ -663,7 +667,7 @@ void IncrementalMarking::Hurry() { continue; } else if (map == global_context_map) { // Global contexts have weak fields. - VisitGlobalContext(Context::cast(obj), &marking_visitor); + IncrementalMarkingMarkingVisitor::VisitGlobalContext(map, obj); } else if (map->instance_type() == MAP_TYPE) { Map* map = Map::cast(obj); heap_->ClearCacheOnMap(map); @@ -676,12 +680,17 @@ void IncrementalMarking::Hurry() { map->instance_type() >= FIRST_JS_RECEIVER_TYPE) { marker_.MarkMapContents(map); } else { - marking_visitor.VisitPointers( + IncrementalMarkingMarkingVisitor::VisitPointers( + heap_, HeapObject::RawField(map, Map::kPointerFieldsBeginOffset), HeapObject::RawField(map, Map::kPointerFieldsEndOffset)); } } else { - obj->Iterate(&marking_visitor); + MarkBit map_mark_bit = Marking::MarkBitFrom(map); + if (Marking::IsWhite(map_mark_bit)) { + WhiteToGreyAndPush(map, map_mark_bit); + } + IncrementalMarkingMarkingVisitor::IterateBody(map, obj); } MarkBit mark_bit = Marking::MarkBitFrom(obj); @@ -815,7 +824,6 @@ void IncrementalMarking::Step(intptr_t allocated_bytes, } else if (state_ == MARKING) { Map* filler_map = heap_->one_pointer_filler_map(); Map* global_context_map = heap_->global_context_map(); - IncrementalMarkingMarkingVisitor marking_visitor(heap_, this); while (!marking_deque_.IsEmpty() && bytes_to_process > 0) { HeapObject* obj = marking_deque_.Pop(); @@ -840,7 +848,7 @@ void IncrementalMarking::Step(intptr_t allocated_bytes, // when we finish marking. MarkObjectGreyDoNotEnqueue(ctx->normalized_map_cache()); - VisitGlobalContext(ctx, &marking_visitor); + IncrementalMarkingMarkingVisitor::VisitGlobalContext(map, ctx); } else if (map->instance_type() == MAP_TYPE) { Map* map = Map::cast(obj); heap_->ClearCacheOnMap(map); @@ -853,25 +861,13 @@ void IncrementalMarking::Step(intptr_t allocated_bytes, map->instance_type() >= FIRST_JS_RECEIVER_TYPE) { marker_.MarkMapContents(map); } else { - marking_visitor.VisitPointers( + IncrementalMarkingMarkingVisitor::VisitPointers( + heap_, HeapObject::RawField(map, Map::kPointerFieldsBeginOffset), HeapObject::RawField(map, Map::kPointerFieldsEndOffset)); } - } else if (map->instance_type() == JS_FUNCTION_TYPE) { - marking_visitor.VisitPointers( - HeapObject::RawField(obj, JSFunction::kPropertiesOffset), - HeapObject::RawField(obj, JSFunction::kCodeEntryOffset)); - - marking_visitor.VisitCodeEntry( - obj->address() + JSFunction::kCodeEntryOffset); - - marking_visitor.VisitPointers( - HeapObject::RawField(obj, - JSFunction::kCodeEntryOffset + kPointerSize), - HeapObject::RawField(obj, - JSFunction::kNonWeakFieldsEndOffset)); } else { - obj->IterateBody(map->instance_type(), size, &marking_visitor); + IncrementalMarkingMarkingVisitor::IterateBody(map, obj); } MarkBit obj_mark_bit = Marking::MarkBitFrom(obj); diff --git a/src/incremental-marking.h b/src/incremental-marking.h index a9c2321..4cb356d 100644 --- a/src/incremental-marking.h +++ b/src/incremental-marking.h @@ -53,6 +53,8 @@ class IncrementalMarking { explicit IncrementalMarking(Heap* heap); + static void Initialize(); + void TearDown(); State state() { @@ -259,8 +261,6 @@ class IncrementalMarking { void EnsureMarkingDequeIsCommitted(); - void VisitGlobalContext(Context* ctx, ObjectVisitor* v); - Heap* heap_; State state_; diff --git a/src/mark-compact.cc b/src/mark-compact.cc index a62196e..6c16f61 100644 --- a/src/mark-compact.cc +++ b/src/mark-compact.cc @@ -938,12 +938,9 @@ static inline HeapObject* ShortCircuitConsString(Object** p) { } -class StaticMarkingVisitor : public StaticVisitorBase { +class MarkCompactMarkingVisitor + : public StaticMarkingVisitor { public: - static inline void IterateBody(Map* map, HeapObject* obj) { - table_.GetVisitor(map)(map, obj); - } - static void ObjectStatsVisitBase(StaticVisitorBase::VisitorId id, Map* map, HeapObject* obj); @@ -952,7 +949,7 @@ class StaticMarkingVisitor : public StaticVisitorBase { FixedArraySubInstanceType fast_type, FixedArraySubInstanceType dictionary_type); - template + template class ObjectStatsTracker { public: static inline void Visit(Map* map, HeapObject* obj); @@ -977,12 +974,9 @@ class StaticMarkingVisitor : public StaticVisitorBase { } } - static void VisitGlobalPropertyCell(Heap* heap, RelocInfo* rinfo) { - ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL); - JSGlobalPropertyCell* cell = - JSGlobalPropertyCell::cast(rinfo->target_cell()); - MarkBit mark = Marking::MarkBitFrom(cell); - heap->mark_compact_collector()->MarkObject(cell, mark); + INLINE(static void MarkObject(Heap* heap, HeapObject* object)) { + MarkBit mark = Marking::MarkBitFrom(object); + heap->mark_compact_collector()->MarkObject(object, mark); } static inline void VisitEmbeddedPointer(Heap* heap, RelocInfo* rinfo) { @@ -991,8 +985,7 @@ class StaticMarkingVisitor : public StaticVisitorBase { // that there can be no such embedded pointers and add assertion here. HeapObject* object = HeapObject::cast(rinfo->target_object()); heap->mark_compact_collector()->RecordRelocSlot(rinfo, object); - MarkBit mark = Marking::MarkBitFrom(object); - heap->mark_compact_collector()->MarkObject(object, mark); + MarkObject(heap, object); } static inline void VisitCodeTarget(Heap* heap, RelocInfo* rinfo) { @@ -1005,20 +998,8 @@ class StaticMarkingVisitor : public StaticVisitorBase { IC::Clear(rinfo->pc()); target = Code::GetCodeFromTargetAddress(rinfo->target_address()); } - MarkBit code_mark = Marking::MarkBitFrom(target); - heap->mark_compact_collector()->MarkObject(target, code_mark); - heap->mark_compact_collector()->RecordRelocSlot(rinfo, target); - } - - static inline void VisitDebugTarget(Heap* heap, RelocInfo* rinfo) { - ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && - rinfo->IsPatchedReturnSequence()) || - (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && - rinfo->IsPatchedDebugBreakSlotSequence())); - Code* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); - MarkBit code_mark = Marking::MarkBitFrom(target); - heap->mark_compact_collector()->MarkObject(target, code_mark); heap->mark_compact_collector()->RecordRelocSlot(rinfo, target); + MarkObject(heap, target); } // Mark object pointed to by p. @@ -1073,28 +1054,14 @@ class StaticMarkingVisitor : public StaticVisitorBase { return true; } - static inline void VisitExternalReference(Address* p) { } - static inline void VisitExternalReference(RelocInfo* rinfo) { } - static inline void VisitRuntimeEntry(RelocInfo* rinfo) { } - - private: - class DataObjectVisitor { - public: - template - static void VisitSpecialized(Map* map, HeapObject* object) { - } - - static void Visit(Map* map, HeapObject* object) { + static void VisitCode(Map* map, HeapObject* object) { + Heap* heap = map->GetHeap(); + Code* code = reinterpret_cast(object); + if (FLAG_cleanup_code_caches_at_gc) { + code->ClearTypeFeedbackCells(heap); } - }; - - typedef FlexibleBodyVisitor JSObjectVisitor; - - typedef FlexibleBodyVisitor StructObjectVisitor; + code->CodeIterateBody(heap); + } static void VisitJSWeakMap(Map* map, HeapObject* object) { MarkCompactCollector* collector = map->GetHeap()->mark_compact_collector(); @@ -1108,12 +1075,12 @@ class StaticMarkingVisitor : public StaticVisitorBase { // Skip visiting the backing hash table containing the mappings. int object_size = JSWeakMap::BodyDescriptor::SizeOf(map, object); - BodyVisitorBase::IteratePointers( + BodyVisitorBase::IteratePointers( map->GetHeap(), object, JSWeakMap::BodyDescriptor::kStartOffset, JSWeakMap::kTableOffset); - BodyVisitorBase::IteratePointers( + BodyVisitorBase::IteratePointers( map->GetHeap(), object, JSWeakMap::kTableOffset + kPointerSize, @@ -1133,14 +1100,9 @@ class StaticMarkingVisitor : public StaticVisitorBase { ASSERT(MarkCompactCollector::IsMarked(table->map())); } - static void VisitCode(Map* map, HeapObject* object) { - Heap* heap = map->GetHeap(); - Code* code = reinterpret_cast(object); - if (FLAG_cleanup_code_caches_at_gc) { - code->ClearTypeFeedbackCells(heap); - } - code->CodeIterateBody(heap); - } + private: + template + static inline void TrackObjectStatsAndVisit(Map* map, HeapObject* obj); // Code flushing support. @@ -1255,7 +1217,7 @@ class StaticMarkingVisitor : public StaticVisitorBase { static void VisitSharedFunctionInfoGeneric(Map* map, HeapObject* object) { SharedFunctionInfo::cast(object)->BeforeVisitingPointers(); - FixedBodyVisitor::Visit(map, object); } @@ -1323,7 +1285,7 @@ class StaticMarkingVisitor : public StaticVisitorBase { Heap* heap = map->GetHeap(); MarkCompactCollector* collector = heap->mark_compact_collector(); if (!collector->is_code_flushing_enabled()) { - VisitJSRegExpFields(map, object); + VisitJSRegExp(map, object); return; } JSRegExp* re = reinterpret_cast(object); @@ -1331,7 +1293,7 @@ class StaticMarkingVisitor : public StaticVisitorBase { UpdateRegExpCodeAgeAndFlush(heap, re, true); UpdateRegExpCodeAgeAndFlush(heap, re, false); // Visit the fields of the RegExp, including the updated FixedArray. - VisitJSRegExpFields(map, object); + VisitJSRegExp(map, object); } @@ -1370,29 +1332,6 @@ class StaticMarkingVisitor : public StaticVisitorBase { } - static void VisitCodeEntry(Heap* heap, Address entry_address) { - Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address)); - MarkBit mark = Marking::MarkBitFrom(code); - heap->mark_compact_collector()->MarkObject(code, mark); - heap->mark_compact_collector()-> - RecordCodeEntrySlot(entry_address, code); - } - - static void VisitGlobalContext(Map* map, HeapObject* object) { - FixedBodyVisitor::Visit(map, object); - - MarkCompactCollector* collector = map->GetHeap()->mark_compact_collector(); - for (int idx = Context::FIRST_WEAK_SLOT; - idx < Context::GLOBAL_CONTEXT_SLOTS; - ++idx) { - Object** slot = - HeapObject::RawField(object, FixedArray::OffsetOfElementAt(idx)); - collector->RecordSlot(slot, slot, *slot); - } - } - static void VisitJSFunctionAndFlushCode(Map* map, HeapObject* object) { Heap* heap = map->GetHeap(); MarkCompactCollector* collector = heap->mark_compact_collector(); @@ -1474,15 +1413,6 @@ class StaticMarkingVisitor : public StaticVisitorBase { JSFunction::kNonWeakFieldsEndOffset)); } - static inline void VisitJSRegExpFields(Map* map, - HeapObject* object) { - int last_property_offset = - JSRegExp::kSize + kPointerSize * map->inobject_properties(); - VisitPointers(map->GetHeap(), - SLOT_ADDR(object, JSRegExp::kPropertiesOffset), - SLOT_ADDR(object, last_property_offset)); - } - static void VisitSharedFunctionInfoFields(Heap* heap, HeapObject* object, @@ -1500,14 +1430,11 @@ class StaticMarkingVisitor : public StaticVisitorBase { #undef SLOT_ADDR - typedef void (*Callback)(Map* map, HeapObject* object); - - static VisitorDispatchTable table_; static VisitorDispatchTable non_count_table_; }; -void StaticMarkingVisitor::ObjectStatsCountFixedArray( +void MarkCompactMarkingVisitor::ObjectStatsCountFixedArray( FixedArrayBase* fixed_array, FixedArraySubInstanceType fast_type, FixedArraySubInstanceType dictionary_type) { @@ -1528,8 +1455,8 @@ void StaticMarkingVisitor::ObjectStatsCountFixedArray( } -void StaticMarkingVisitor::ObjectStatsVisitBase( - StaticVisitorBase::VisitorId id, Map* map, HeapObject* obj) { +void MarkCompactMarkingVisitor::ObjectStatsVisitBase( + MarkCompactMarkingVisitor::VisitorId id, Map* map, HeapObject* obj) { Heap* heap = map->GetHeap(); int object_size = obj->Size(); heap->RecordObjectStats(map->instance_type(), -1, object_size); @@ -1546,16 +1473,16 @@ void StaticMarkingVisitor::ObjectStatsVisitBase( } -template -void StaticMarkingVisitor::ObjectStatsTracker::Visit( +template +void MarkCompactMarkingVisitor::ObjectStatsTracker::Visit( Map* map, HeapObject* obj) { ObjectStatsVisitBase(id, map, obj); } template<> -class StaticMarkingVisitor::ObjectStatsTracker< - StaticMarkingVisitor::kVisitMap> { +class MarkCompactMarkingVisitor::ObjectStatsTracker< + MarkCompactMarkingVisitor::kVisitMap> { public: static inline void Visit(Map* map, HeapObject* obj) { Heap* heap = map->GetHeap(); @@ -1586,8 +1513,8 @@ class StaticMarkingVisitor::ObjectStatsTracker< template<> -class StaticMarkingVisitor::ObjectStatsTracker< - StaticMarkingVisitor::kVisitCode> { +class MarkCompactMarkingVisitor::ObjectStatsTracker< + MarkCompactMarkingVisitor::kVisitCode> { public: static inline void Visit(Map* map, HeapObject* obj) { Heap* heap = map->GetHeap(); @@ -1600,8 +1527,8 @@ class StaticMarkingVisitor::ObjectStatsTracker< template<> -class StaticMarkingVisitor::ObjectStatsTracker< - StaticMarkingVisitor::kVisitSharedFunctionInfo> { +class MarkCompactMarkingVisitor::ObjectStatsTracker< + MarkCompactMarkingVisitor::kVisitSharedFunctionInfo> { public: static inline void Visit(Map* map, HeapObject* obj) { Heap* heap = map->GetHeap(); @@ -1618,8 +1545,8 @@ class StaticMarkingVisitor::ObjectStatsTracker< template<> -class StaticMarkingVisitor::ObjectStatsTracker< - StaticMarkingVisitor::kVisitFixedArray> { +class MarkCompactMarkingVisitor::ObjectStatsTracker< + MarkCompactMarkingVisitor::kVisitFixedArray> { public: static inline void Visit(Map* map, HeapObject* obj) { Heap* heap = map->GetHeap(); @@ -1635,48 +1562,8 @@ class StaticMarkingVisitor::ObjectStatsTracker< }; -void StaticMarkingVisitor::Initialize() { - table_.Register(kVisitShortcutCandidate, - &FixedBodyVisitor::Visit); - - table_.Register(kVisitConsString, - &FixedBodyVisitor::Visit); - - table_.Register(kVisitSlicedString, - &FixedBodyVisitor::Visit); - - table_.Register(kVisitFixedArray, - &FlexibleBodyVisitor::Visit); - - table_.Register(kVisitGlobalContext, &VisitGlobalContext); - - table_.Register(kVisitFixedDoubleArray, DataObjectVisitor::Visit); - - table_.Register(kVisitByteArray, &DataObjectVisitor::Visit); - table_.Register(kVisitFreeSpace, &DataObjectVisitor::Visit); - table_.Register(kVisitSeqAsciiString, &DataObjectVisitor::Visit); - table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit); - - table_.Register(kVisitJSWeakMap, &VisitJSWeakMap); - - table_.Register(kVisitOddball, - &FixedBodyVisitor::Visit); - table_.Register(kVisitMap, - &FixedBodyVisitor::Visit); - - table_.Register(kVisitCode, &VisitCode); +void MarkCompactMarkingVisitor::Initialize() { + StaticMarkingVisitor::Initialize(); table_.Register(kVisitSharedFunctionInfo, &VisitSharedFunctionInfoAndFlushCode); @@ -1687,23 +1574,6 @@ void StaticMarkingVisitor::Initialize() { table_.Register(kVisitJSRegExp, &VisitRegExpAndFlushCode); - table_.Register(kVisitPropertyCell, - &FixedBodyVisitor::Visit); - - table_.RegisterSpecializations(); - - table_.RegisterSpecializations(); - - table_.RegisterSpecializations(); - if (FLAG_track_gc_object_stats) { // Copy the visitor table to make call-through possible. non_count_table_.CopyFrom(&table_); @@ -1715,10 +1585,8 @@ void StaticMarkingVisitor::Initialize() { } -VisitorDispatchTable - StaticMarkingVisitor::table_; -VisitorDispatchTable - StaticMarkingVisitor::non_count_table_; +VisitorDispatchTable + MarkCompactMarkingVisitor::non_count_table_; class MarkingVisitor : public ObjectVisitor { @@ -1726,11 +1594,11 @@ class MarkingVisitor : public ObjectVisitor { explicit MarkingVisitor(Heap* heap) : heap_(heap) { } void VisitPointer(Object** p) { - StaticMarkingVisitor::VisitPointer(heap_, p); + MarkCompactMarkingVisitor::VisitPointer(heap_, p); } void VisitPointers(Object** start, Object** end) { - StaticMarkingVisitor::VisitPointers(heap_, start, end); + MarkCompactMarkingVisitor::VisitPointers(heap_, start, end); } private: @@ -1889,7 +1757,7 @@ class RootMarkingVisitor : public ObjectVisitor { // Mark the map pointer and body, and push them on the marking stack. MarkBit map_mark = Marking::MarkBitFrom(map); collector_->MarkObject(map, map_mark); - StaticMarkingVisitor::IterateBody(map, object); + MarkCompactMarkingVisitor::IterateBody(map, object); // Mark all the objects reachable from the map and body. May leave // overflowed objects in the heap. @@ -2342,7 +2210,7 @@ void MarkCompactCollector::EmptyMarkingDeque() { MarkBit map_mark = Marking::MarkBitFrom(map); MarkObject(map, map_mark); - StaticMarkingVisitor::IterateBody(map, object); + MarkCompactMarkingVisitor::IterateBody(map, object); } // Process encountered weak maps, mark objects only reachable by those @@ -2481,7 +2349,7 @@ void MarkCompactCollector::MarkLiveObjects() { ASSERT(cell->IsJSGlobalPropertyCell()); if (IsMarked(cell)) { int offset = JSGlobalPropertyCell::kValueOffset; - StaticMarkingVisitor::VisitPointer( + MarkCompactMarkingVisitor::VisitPointer( heap(), reinterpret_cast(cell->address() + offset)); } @@ -2740,7 +2608,8 @@ void MarkCompactCollector::ProcessWeakMaps() { Object** value_slot = HeapObject::RawField(table, FixedArray::OffsetOfElementAt( ObjectHashTable::EntryToValueIndex(i))); - StaticMarkingVisitor::MarkObjectByPointer(this, anchor, value_slot); + MarkCompactMarkingVisitor::MarkObjectByPointer( + this, anchor, value_slot); } } weak_map_obj = weak_map->next(); @@ -4141,7 +4010,8 @@ void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj, void MarkCompactCollector::Initialize() { - StaticMarkingVisitor::Initialize(); + MarkCompactMarkingVisitor::Initialize(); + IncrementalMarking::Initialize(); } diff --git a/src/mark-compact.h b/src/mark-compact.h index ed3def5..b94355b 100644 --- a/src/mark-compact.h +++ b/src/mark-compact.h @@ -636,7 +636,7 @@ class MarkCompactCollector { friend class RootMarkingVisitor; friend class MarkingVisitor; - friend class StaticMarkingVisitor; + friend class MarkCompactMarkingVisitor; friend class CodeMarkingVisitor; friend class SharedFunctionInfoMarkingVisitor; friend class Marker; diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h index 8ba92f7..30a7ad4 100644 --- a/src/objects-visiting-inl.h +++ b/src/objects-visiting-inl.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -93,6 +93,139 @@ void StaticNewSpaceVisitor::Initialize() { } +template +void StaticMarkingVisitor::Initialize() { + table_.Register(kVisitShortcutCandidate, + &FixedBodyVisitor::Visit); + + table_.Register(kVisitConsString, + &FixedBodyVisitor::Visit); + + table_.Register(kVisitSlicedString, + &FixedBodyVisitor::Visit); + + table_.Register(kVisitFixedArray, + &FlexibleBodyVisitor::Visit); + + table_.Register(kVisitFixedDoubleArray, &DataObjectVisitor::Visit); + + table_.Register(kVisitGlobalContext, &VisitGlobalContext); + + table_.Register(kVisitByteArray, &DataObjectVisitor::Visit); + + table_.Register(kVisitFreeSpace, &DataObjectVisitor::Visit); + + table_.Register(kVisitSeqAsciiString, &DataObjectVisitor::Visit); + + table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit); + + table_.Register(kVisitJSWeakMap, &StaticVisitor::VisitJSWeakMap); + + table_.Register(kVisitOddball, + &FixedBodyVisitor::Visit); + + table_.Register(kVisitMap, + &FixedBodyVisitor::Visit); + + table_.Register(kVisitCode, &StaticVisitor::VisitCode); + + // Registration for kVisitSharedFunctionInfo is done by StaticVisitor. + + // Registration for kVisitJSFunction is done by StaticVisitor. + + // Registration for kVisitJSRegExp is done by StaticVisitor. + + table_.Register(kVisitPropertyCell, + &FixedBodyVisitor::Visit); + + table_.template RegisterSpecializations(); + + table_.template RegisterSpecializations(); + + table_.template RegisterSpecializations(); +} + + +template +void StaticMarkingVisitor::VisitCodeEntry( + Heap* heap, Address entry_address) { + Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address)); + heap->mark_compact_collector()->RecordCodeEntrySlot(entry_address, code); + StaticVisitor::MarkObject(heap, code); +} + + +template +void StaticMarkingVisitor::VisitGlobalPropertyCell( + Heap* heap, RelocInfo* rinfo) { + ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL); + JSGlobalPropertyCell* cell = rinfo->target_cell(); + StaticVisitor::MarkObject(heap, cell); +} + + +template +void StaticMarkingVisitor::VisitDebugTarget( + Heap* heap, RelocInfo* rinfo) { + ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && + rinfo->IsPatchedReturnSequence()) || + (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && + rinfo->IsPatchedDebugBreakSlotSequence())); + Code* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); + heap->mark_compact_collector()->RecordRelocSlot(rinfo, target); + StaticVisitor::MarkObject(heap, target); +} + + +template +void StaticMarkingVisitor::VisitGlobalContext( + Map* map, HeapObject* object) { + FixedBodyVisitor::Visit(map, object); + + MarkCompactCollector* collector = map->GetHeap()->mark_compact_collector(); + for (int idx = Context::FIRST_WEAK_SLOT; + idx < Context::GLOBAL_CONTEXT_SLOTS; + ++idx) { + Object** slot = + HeapObject::RawField(object, FixedArray::OffsetOfElementAt(idx)); + collector->RecordSlot(slot, slot, *slot); + } +} + + +template +void StaticMarkingVisitor::VisitJSRegExp( + Map* map, HeapObject* object) { + int last_property_offset = + JSRegExp::kSize + kPointerSize * map->inobject_properties(); + StaticVisitor::VisitPointers(map->GetHeap(), + HeapObject::RawField(object, JSRegExp::kPropertiesOffset), + HeapObject::RawField(object, last_property_offset)); +} + + void Code::CodeIterateBody(ObjectVisitor* v) { int mode_mask = RelocInfo::kCodeTargetMask | RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | diff --git a/src/objects-visiting.h b/src/objects-visiting.h index a84c512..7415101 100644 --- a/src/objects-visiting.h +++ b/src/objects-visiting.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -360,7 +360,71 @@ class StaticNewSpaceVisitor : public StaticVisitorBase { template VisitorDispatchTable::Callback> - StaticNewSpaceVisitor::table_; + StaticNewSpaceVisitor::table_; + + +// Base class for visitors used to transitively mark the entire heap. +// IterateBody returns nothing. +// Certain types of objects might not be handled by this base class and +// no visitor function is registered by the generic initialization. A +// specialized visitor function needs to be provided by the inheriting +// class itself for those cases. +// +// This class is intended to be used in the following way: +// +// class SomeVisitor : public StaticMarkingVisitor { +// ... +// } +// +// This is an example of Curiously recurring template pattern. +template +class StaticMarkingVisitor : public StaticVisitorBase { + public: + static void Initialize(); + + static inline void IterateBody(Map* map, HeapObject* obj) { + table_.GetVisitor(map)(map, obj); + } + + static inline void VisitCodeEntry(Heap* heap, Address entry_address); + static inline void VisitGlobalPropertyCell(Heap* heap, RelocInfo* rinfo); + static inline void VisitDebugTarget(Heap* heap, RelocInfo* rinfo); + static inline void VisitExternalReference(RelocInfo* rinfo) { } + static inline void VisitRuntimeEntry(RelocInfo* rinfo) { } + + // TODO(mstarzinger): This should be made protected once refactoring is done. + static inline void VisitGlobalContext(Map* map, HeapObject* object); + + protected: + static inline void VisitJSRegExp(Map* map, HeapObject* object); + + class DataObjectVisitor { + public: + template + static inline void VisitSpecialized(Map* map, HeapObject* object) { + } + + static inline void Visit(Map* map, HeapObject* object) { + } + }; + + typedef FlexibleBodyVisitor JSObjectVisitor; + + typedef FlexibleBodyVisitor StructObjectVisitor; + + typedef void (*Callback)(Map* map, HeapObject* object); + + static VisitorDispatchTable table_; +}; + + +template +VisitorDispatchTable::Callback> + StaticMarkingVisitor::table_; } } // namespace v8::internal diff --git a/src/objects.cc b/src/objects.cc index 67ff486..4905c04 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1398,8 +1398,7 @@ void HeapObject::IterateBody(InstanceType type, int object_size, case EXTERNAL_DOUBLE_ARRAY_TYPE: break; case SHARED_FUNCTION_INFO_TYPE: { - SharedFunctionInfo* shared = reinterpret_cast(this); - shared->SharedFunctionInfoIterateBody(v); + SharedFunctionInfo::BodyDescriptor::IterateBody(this, v); break; } @@ -7996,12 +7995,6 @@ int SharedFunctionInfo::SearchOptimizedCodeMap(Context* global_context) { } -void SharedFunctionInfo::SharedFunctionInfoIterateBody(ObjectVisitor* v) { - v->VisitSharedFunctionInfo(this); - SharedFunctionInfo::BodyDescriptor::IterateBody(this, v); -} - - #define DECLARE_TAG(ignore1, name, ignore2) name, const char* const VisitorSynchronization::kTags[ VisitorSynchronization::kNumberOfSyncTags] = { diff --git a/src/objects.h b/src/objects.h index 3694955..fa33b81 100644 --- a/src/objects.h +++ b/src/objects.h @@ -5724,8 +5724,6 @@ class SharedFunctionInfo: public HeapObject { static bool CompileLazy(Handle shared, ClearExceptionFlag flag); - void SharedFunctionInfoIterateBody(ObjectVisitor* v); - // Casting. static inline SharedFunctionInfo* cast(Object* obj); @@ -8853,8 +8851,6 @@ class ObjectVisitor BASE_EMBEDDED { // Visit pointer embedded into a code object. virtual void VisitEmbeddedPointer(RelocInfo* rinfo); - virtual void VisitSharedFunctionInfo(SharedFunctionInfo* shared) {} - // Visits a contiguous arrays of external references (references to the C++ // heap) in the half-open range [start, end). Any or all of the values // may be modified on return. -- 2.7.4