| Index: src/mark-compact.cc
|
| diff --git a/src/mark-compact.cc b/src/mark-compact.cc
|
| index d9b0222a4084b810fe6254b43a358882a2b11ec8..f92ecbdc2983c72e89f4644665a4038928c79eaa 100644
|
| --- a/src/mark-compact.cc
|
| +++ b/src/mark-compact.cc
|
| @@ -32,6 +32,7 @@
|
| #include "global-handles.h"
|
| #include "ic-inl.h"
|
| #include "mark-compact.h"
|
| +#include "objects-visiting.h"
|
| #include "stub-cache.h"
|
|
|
| namespace v8 {
|
| @@ -63,6 +64,7 @@ int MarkCompactCollector::live_cell_objects_size_ = 0;
|
| int MarkCompactCollector::live_lo_objects_size_ = 0;
|
| #endif
|
|
|
| +
|
| void MarkCompactCollector::CollectGarbage() {
|
| // Make sure that Prepare() has been called. The individual steps below will
|
| // update the state as they proceed.
|
| @@ -244,14 +246,72 @@ static inline HeapObject* ShortCircuitConsString(Object** p) {
|
| }
|
|
|
|
|
| -// Helper class for marking pointers in HeapObjects.
|
| -class MarkingVisitor : public ObjectVisitor {
|
| +class StaticMarkingVisitor : public StaticVisitorBase {
|
| public:
|
| - void VisitPointer(Object** p) {
|
| + static inline void IterateBody(Map* map, HeapObject* obj) {
|
| + table_.GetVisitor(map)(map, obj);
|
| + }
|
| +
|
| + static void Initialize() {
|
| + table_.Register(kVisitShortcutCandidate,
|
| + &FixedBodyVisitor<StaticMarkingVisitor,
|
| + ConsString::BodyDescriptor,
|
| + void>::Visit);
|
| +
|
| + table_.Register(kVisitConsString,
|
| + &FixedBodyVisitor<StaticMarkingVisitor,
|
| + ConsString::BodyDescriptor,
|
| + void>::Visit);
|
| +
|
| +
|
| + table_.Register(kVisitFixedArray,
|
| + &FlexibleBodyVisitor<StaticMarkingVisitor,
|
| + FixedArray::BodyDescriptor,
|
| + void>::Visit);
|
| +
|
| + table_.Register(kVisitSharedFunctionInfo,
|
| + &FixedBodyVisitor<StaticMarkingVisitor,
|
| + SharedFunctionInfo::BodyDescriptor,
|
| + void>::Visit);
|
| +
|
| + table_.Register(kVisitByteArray, &DataObjectVisitor::Visit);
|
| + table_.Register(kVisitSeqAsciiString, &DataObjectVisitor::Visit);
|
| + table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit);
|
| +
|
| + table_.Register(kVisitOddball,
|
| + &FixedBodyVisitor<StaticMarkingVisitor,
|
| + Oddball::BodyDescriptor,
|
| + void>::Visit);
|
| + table_.Register(kVisitMap,
|
| + &FixedBodyVisitor<StaticMarkingVisitor,
|
| + Map::BodyDescriptor,
|
| + void>::Visit);
|
| +
|
| + table_.Register(kVisitCode, &VisitCode);
|
| +
|
| + table_.Register(kVisitPropertyCell,
|
| + &FixedBodyVisitor<StaticMarkingVisitor,
|
| + JSGlobalPropertyCell::BodyDescriptor,
|
| + void>::Visit);
|
| +
|
| + table_.RegisterSpecializations<DataObjectVisitor,
|
| + kVisitDataObject,
|
| + kVisitDataObjectGeneric>();
|
| +
|
| + table_.RegisterSpecializations<JSObjectVisitor,
|
| + kVisitJSObject,
|
| + kVisitJSObjectGeneric>();
|
| +
|
| + table_.RegisterSpecializations<StructObjectVisitor,
|
| + kVisitStruct,
|
| + kVisitStructGeneric>();
|
| + }
|
| +
|
| + INLINE(static void VisitPointer(Object** p)) {
|
| MarkObjectByPointer(p);
|
| }
|
|
|
| - void VisitPointers(Object** start, Object** end) {
|
| + INLINE(static void VisitPointers(Object** start, Object** end)) {
|
| // Mark all objects pointed to in [start, end).
|
| const int kMinRangeForMarkingRecursion = 64;
|
| if (end - start >= kMinRangeForMarkingRecursion) {
|
| @@ -261,7 +321,7 @@ class MarkingVisitor : public ObjectVisitor {
|
| for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
|
| }
|
|
|
| - void VisitCodeTarget(RelocInfo* rinfo) {
|
| + static inline void VisitCodeTarget(RelocInfo* rinfo) {
|
| ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
|
| Code* code = Code::GetCodeFromTargetAddress(rinfo->target_address());
|
| if (FLAG_cleanup_ics_at_gc && code->is_inline_cache_stub()) {
|
| @@ -273,7 +333,7 @@ class MarkingVisitor : public ObjectVisitor {
|
| }
|
| }
|
|
|
| - void VisitDebugTarget(RelocInfo* rinfo) {
|
| + static inline void VisitDebugTarget(RelocInfo* rinfo) {
|
| ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
|
| rinfo->IsPatchedReturnSequence()) ||
|
| (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
|
| @@ -282,19 +342,15 @@ class MarkingVisitor : public ObjectVisitor {
|
| MarkCompactCollector::MarkObject(code);
|
| }
|
|
|
| - private:
|
| // Mark object pointed to by p.
|
| - void MarkObjectByPointer(Object** p) {
|
| + INLINE(static void MarkObjectByPointer(Object** p)) {
|
| if (!(*p)->IsHeapObject()) return;
|
| HeapObject* object = ShortCircuitConsString(p);
|
| MarkCompactCollector::MarkObject(object);
|
| }
|
|
|
| - // Tells whether the mark sweep collection will perform compaction.
|
| - bool IsCompacting() { return MarkCompactCollector::IsCompacting(); }
|
| -
|
| // Visit an unmarked object.
|
| - void VisitUnmarkedObject(HeapObject* obj) {
|
| + static inline void VisitUnmarkedObject(HeapObject* obj) {
|
| #ifdef DEBUG
|
| ASSERT(Heap::Contains(obj));
|
| ASSERT(!obj->IsMarked());
|
| @@ -303,12 +359,12 @@ class MarkingVisitor : public ObjectVisitor {
|
| MarkCompactCollector::SetMark(obj);
|
| // Mark the map pointer and the body.
|
| MarkCompactCollector::MarkObject(map);
|
| - obj->IterateBody(map->instance_type(), obj->SizeFromMap(map), this);
|
| + IterateBody(map, obj);
|
| }
|
|
|
| // Visit all unmarked objects pointed to by [start, end).
|
| // Returns false if the operation fails (lack of stack space).
|
| - inline bool VisitUnmarkedObjects(Object** start, Object** end) {
|
| + static inline bool VisitUnmarkedObjects(Object** start, Object** end) {
|
| // Return false is we are close to the stack limit.
|
| StackLimitCheck check;
|
| if (check.HasOverflowed()) return false;
|
| @@ -322,6 +378,60 @@ class MarkingVisitor : public ObjectVisitor {
|
| }
|
| return true;
|
| }
|
| +
|
| + static inline void VisitExternalReference(Address* p) { }
|
| + static inline void VisitRuntimeEntry(RelocInfo* rinfo) { }
|
| +
|
| + private:
|
| + class DataObjectVisitor {
|
| + public:
|
| + template<int size>
|
| + static void VisitSpecialized(Map* map, HeapObject* object) {
|
| + }
|
| +
|
| + static void Visit(Map* map, HeapObject* object) {
|
| + }
|
| + };
|
| +
|
| + typedef FlexibleBodyVisitor<StaticMarkingVisitor,
|
| + JSObject::BodyDescriptor,
|
| + void> JSObjectVisitor;
|
| +
|
| + typedef FlexibleBodyVisitor<StaticMarkingVisitor,
|
| + StructBodyDescriptor,
|
| + void> StructObjectVisitor;
|
| +
|
| + static void VisitCode(Map* map, HeapObject* object) {
|
| + reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>();
|
| + }
|
| +
|
| + typedef void (*Callback)(Map* map, HeapObject* object);
|
| +
|
| + static VisitorDispatchTable<Callback> table_;
|
| +};
|
| +
|
| +
|
| +VisitorDispatchTable<StaticMarkingVisitor::Callback>
|
| + StaticMarkingVisitor::table_;
|
| +
|
| +
|
| +class MarkingVisitor : public ObjectVisitor {
|
| + public:
|
| + void VisitPointer(Object** p) {
|
| + StaticMarkingVisitor::VisitPointer(p);
|
| + }
|
| +
|
| + void VisitPointers(Object** start, Object** end) {
|
| + StaticMarkingVisitor::VisitPointers(start, end);
|
| + }
|
| +
|
| + void VisitCodeTarget(RelocInfo* rinfo) {
|
| + StaticMarkingVisitor::VisitCodeTarget(rinfo);
|
| + }
|
| +
|
| + void VisitDebugTarget(RelocInfo* rinfo) {
|
| + StaticMarkingVisitor::VisitDebugTarget(rinfo);
|
| + }
|
| };
|
|
|
|
|
| @@ -336,11 +446,7 @@ class RootMarkingVisitor : public ObjectVisitor {
|
| for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
|
| }
|
|
|
| - MarkingVisitor* stack_visitor() { return &stack_visitor_; }
|
| -
|
| private:
|
| - MarkingVisitor stack_visitor_;
|
| -
|
| void MarkObjectByPointer(Object** p) {
|
| if (!(*p)->IsHeapObject()) return;
|
|
|
| @@ -351,14 +457,14 @@ class RootMarkingVisitor : public ObjectVisitor {
|
| Map* map = object->map();
|
| // Mark the object.
|
| MarkCompactCollector::SetMark(object);
|
| +
|
| // Mark the map pointer and body, and push them on the marking stack.
|
| MarkCompactCollector::MarkObject(map);
|
| - object->IterateBody(map->instance_type(), object->SizeFromMap(map),
|
| - &stack_visitor_);
|
| + StaticMarkingVisitor::IterateBody(map, object);
|
|
|
| // Mark all the objects reachable from the map and body. May leave
|
| // overflowed objects in the heap.
|
| - MarkCompactCollector::EmptyMarkingStack(&stack_visitor_);
|
| + MarkCompactCollector::EmptyMarkingStack();
|
| }
|
| };
|
|
|
| @@ -425,11 +531,12 @@ void MarkCompactCollector::MarkMapContents(Map* map) {
|
| // Mark the Object* fields of the Map.
|
| // Since the descriptor array has been marked already, it is fine
|
| // that one of these fields contains a pointer to it.
|
| - MarkingVisitor visitor; // Has no state or contents.
|
| - visitor.VisitPointers(HeapObject::RawField(map,
|
| - Map::kPointerFieldsBeginOffset),
|
| - HeapObject::RawField(map,
|
| - Map::kPointerFieldsEndOffset));
|
| + Object** start_slot = HeapObject::RawField(map,
|
| + Map::kPointerFieldsBeginOffset);
|
| +
|
| + Object** end_slot = HeapObject::RawField(map, Map::kPointerFieldsEndOffset);
|
| +
|
| + StaticMarkingVisitor::VisitPointers(start_slot, end_slot);
|
| }
|
|
|
|
|
| @@ -529,7 +636,7 @@ void MarkCompactCollector::MarkSymbolTable() {
|
| // Explicitly mark the prefix.
|
| MarkingVisitor marker;
|
| symbol_table->IteratePrefix(&marker);
|
| - ProcessMarkingStack(&marker);
|
| + ProcessMarkingStack();
|
| }
|
|
|
|
|
| @@ -544,7 +651,7 @@ void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) {
|
| // There may be overflowed objects in the heap. Visit them now.
|
| while (marking_stack.overflowed()) {
|
| RefillMarkingStack();
|
| - EmptyMarkingStack(visitor->stack_visitor());
|
| + EmptyMarkingStack();
|
| }
|
| }
|
|
|
| @@ -587,7 +694,7 @@ void MarkCompactCollector::MarkObjectGroups() {
|
| // Before: the marking stack contains zero or more heap object pointers.
|
| // After: the marking stack is empty, and all objects reachable from the
|
| // marking stack have been marked, or are overflowed in the heap.
|
| -void MarkCompactCollector::EmptyMarkingStack(MarkingVisitor* visitor) {
|
| +void MarkCompactCollector::EmptyMarkingStack() {
|
| while (!marking_stack.is_empty()) {
|
| HeapObject* object = marking_stack.Pop();
|
| ASSERT(object->IsHeapObject());
|
| @@ -601,8 +708,8 @@ void MarkCompactCollector::EmptyMarkingStack(MarkingVisitor* visitor) {
|
| map_word.ClearMark();
|
| Map* map = map_word.ToMap();
|
| MarkObject(map);
|
| - object->IterateBody(map->instance_type(), object->SizeFromMap(map),
|
| - visitor);
|
| +
|
| + StaticMarkingVisitor::IterateBody(map, object);
|
| }
|
| }
|
|
|
| @@ -652,22 +759,22 @@ void MarkCompactCollector::RefillMarkingStack() {
|
| // stack. Before: the marking stack contains zero or more heap object
|
| // pointers. After: the marking stack is empty and there are no overflowed
|
| // objects in the heap.
|
| -void MarkCompactCollector::ProcessMarkingStack(MarkingVisitor* visitor) {
|
| - EmptyMarkingStack(visitor);
|
| +void MarkCompactCollector::ProcessMarkingStack() {
|
| + EmptyMarkingStack();
|
| while (marking_stack.overflowed()) {
|
| RefillMarkingStack();
|
| - EmptyMarkingStack(visitor);
|
| + EmptyMarkingStack();
|
| }
|
| }
|
|
|
|
|
| -void MarkCompactCollector::ProcessObjectGroups(MarkingVisitor* visitor) {
|
| +void MarkCompactCollector::ProcessObjectGroups() {
|
| bool work_to_do = true;
|
| ASSERT(marking_stack.is_empty());
|
| while (work_to_do) {
|
| MarkObjectGroups();
|
| work_to_do = !marking_stack.is_empty();
|
| - ProcessMarkingStack(visitor);
|
| + ProcessMarkingStack();
|
| }
|
| }
|
|
|
| @@ -692,7 +799,7 @@ void MarkCompactCollector::MarkLiveObjects() {
|
| // objects are unmarked. Mark objects reachable from object groups
|
| // containing at least one marked object, and continue until no new
|
| // objects are reachable from the object groups.
|
| - ProcessObjectGroups(root_visitor.stack_visitor());
|
| + ProcessObjectGroups();
|
|
|
| // The objects reachable from the roots or object groups are marked,
|
| // yet unreachable objects are unmarked. Mark objects reachable
|
| @@ -705,12 +812,12 @@ void MarkCompactCollector::MarkLiveObjects() {
|
| GlobalHandles::IterateWeakRoots(&root_visitor);
|
| while (marking_stack.overflowed()) {
|
| RefillMarkingStack();
|
| - EmptyMarkingStack(root_visitor.stack_visitor());
|
| + EmptyMarkingStack();
|
| }
|
|
|
| // Repeat the object groups to mark unmarked groups reachable from the
|
| // weak roots.
|
| - ProcessObjectGroups(root_visitor.stack_visitor());
|
| + ProcessObjectGroups();
|
|
|
| // Prune the symbol table removing all symbols only pointed to by the
|
| // symbol table. Cannot use symbol_table() here because the symbol
|
| @@ -1091,16 +1198,35 @@ static void MigrateObject(Address dst,
|
| }
|
|
|
|
|
| +class StaticPointersToNewGenUpdatingVisitor : public
|
| + StaticNewSpaceVisitor<StaticPointersToNewGenUpdatingVisitor> {
|
| + public:
|
| + static inline void VisitPointer(Object** p) {
|
| + if (!(*p)->IsHeapObject()) return;
|
| +
|
| + HeapObject* obj = HeapObject::cast(*p);
|
| + Address old_addr = obj->address();
|
| +
|
| + if (Heap::new_space()->Contains(obj)) {
|
| + ASSERT(Heap::InFromSpace(*p));
|
| + *p = HeapObject::FromAddress(Memory::Address_at(old_addr));
|
| + }
|
| + }
|
| +};
|
| +
|
| +
|
| // Visitor for updating pointers from live objects in old spaces to new space.
|
| // It does not expect to encounter pointers to dead objects.
|
| class PointersToNewGenUpdatingVisitor: public ObjectVisitor {
|
| public:
|
| void VisitPointer(Object** p) {
|
| - UpdatePointer(p);
|
| + StaticPointersToNewGenUpdatingVisitor::VisitPointer(p);
|
| }
|
|
|
| void VisitPointers(Object** start, Object** end) {
|
| - for (Object** p = start; p < end; p++) UpdatePointer(p);
|
| + for (Object** p = start; p < end; p++) {
|
| + StaticPointersToNewGenUpdatingVisitor::VisitPointer(p);
|
| + }
|
| }
|
|
|
| void VisitCodeTarget(RelocInfo* rinfo) {
|
| @@ -1119,19 +1245,6 @@ class PointersToNewGenUpdatingVisitor: public ObjectVisitor {
|
| VisitPointer(&target);
|
| rinfo->set_call_address(Code::cast(target)->instruction_start());
|
| }
|
| -
|
| - private:
|
| - void UpdatePointer(Object** p) {
|
| - if (!(*p)->IsHeapObject()) return;
|
| -
|
| - HeapObject* obj = HeapObject::cast(*p);
|
| - Address old_addr = obj->address();
|
| -
|
| - if (Heap::new_space()->Contains(obj)) {
|
| - ASSERT(Heap::InFromSpace(*p));
|
| - *p = HeapObject::FromAddress(Memory::Address_at(old_addr));
|
| - }
|
| - }
|
| };
|
|
|
|
|
| @@ -1248,15 +1361,12 @@ static void SweepNewSpace(NewSpace* space) {
|
| PointersToNewGenUpdatingVisitor updating_visitor;
|
|
|
| // Update pointers in to space.
|
| - HeapObject* object;
|
| - for (Address current = space->bottom();
|
| - current < space->top();
|
| - current += object->Size()) {
|
| - object = HeapObject::FromAddress(current);
|
| -
|
| - object->IterateBody(object->map()->instance_type(),
|
| - object->Size(),
|
| - &updating_visitor);
|
| + Address current = space->bottom();
|
| + while (current < space->top()) {
|
| + HeapObject* object = HeapObject::FromAddress(current);
|
| + current +=
|
| + StaticPointersToNewGenUpdatingVisitor::IterateBody(object->map(),
|
| + object);
|
| }
|
|
|
| // Update roots.
|
| @@ -1758,7 +1868,9 @@ void MarkCompactCollector::SweepSpaces() {
|
| SweepSpace(Heap::old_data_space(), &DeallocateOldDataBlock);
|
| SweepSpace(Heap::code_space(), &DeallocateCodeBlock);
|
| SweepSpace(Heap::cell_space(), &DeallocateCellBlock);
|
| - SweepNewSpace(Heap::new_space());
|
| + { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE);
|
| + SweepNewSpace(Heap::new_space());
|
| + }
|
| SweepSpace(Heap::map_space(), &DeallocateMapBlock);
|
|
|
| Heap::IterateDirtyRegions(Heap::map_space(),
|
| @@ -2327,4 +2439,11 @@ void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj) {
|
| #endif
|
| }
|
|
|
| +
|
| +void MarkCompactCollector::Initialize() {
|
| + StaticPointersToNewGenUpdatingVisitor::Initialize();
|
| + StaticMarkingVisitor::Initialize();
|
| +}
|
| +
|
| +
|
| } } // namespace v8::internal
|
|
|