| Index: src/heap/mark-compact.cc
|
| diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc
|
| index 2a464744e20cf120a90196bca277b66e6dac03a8..468a0e8bfdd57a0399c749cf9fa677f36b272672 100644
|
| --- a/src/heap/mark-compact.cc
|
| +++ b/src/heap/mark-compact.cc
|
| @@ -51,7 +51,7 @@ STATIC_ASSERT(Heap::kMinObjectSizeInWords >= 2);
|
| #ifdef VERIFY_HEAP
|
| namespace {
|
|
|
| -class MarkingVerifier : public ObjectVisitor {
|
| +class MarkingVerifier : public ObjectVisitor, public RootVisitor {
|
| public:
|
| virtual void Run() = 0;
|
|
|
| @@ -60,6 +60,16 @@ class MarkingVerifier : public ObjectVisitor {
|
|
|
| virtual MarkingState marking_state(MemoryChunk* chunk) = 0;
|
|
|
| + virtual void VerifyPointers(Object** start, Object** end) = 0;
|
| +
|
| + void VisitPointers(Object** start, Object** end) override {
|
| + VerifyPointers(start, end);
|
| + }
|
| +
|
| + void VisitRootPointers(Root root, Object** start, Object** end) override {
|
| + VerifyPointers(start, end);
|
| + }
|
| +
|
| void VerifyRoots(VisitMode mode);
|
| void VerifyMarkingOnPage(const Page& page, const MarkingState& state,
|
| Address start, Address end);
|
| @@ -152,7 +162,7 @@ class FullMarkingVerifier : public MarkingVerifier {
|
| return MarkingState::Internal(object);
|
| }
|
|
|
| - void VisitPointers(Object** start, Object** end) override {
|
| + void VerifyPointers(Object** start, Object** end) override {
|
| for (Object** current = start; current < end; current++) {
|
| if ((*current)->IsHeapObject()) {
|
| HeapObject* object = HeapObject::cast(*current);
|
| @@ -195,7 +205,7 @@ class YoungGenerationMarkingVerifier : public MarkingVerifier {
|
| VerifyMarking(heap_->new_space());
|
| }
|
|
|
| - void VisitPointers(Object** start, Object** end) override {
|
| + void VerifyPointers(Object** start, Object** end) override {
|
| for (Object** current = start; current < end; current++) {
|
| if ((*current)->IsHeapObject()) {
|
| HeapObject* object = HeapObject::cast(*current);
|
| @@ -206,11 +216,22 @@ class YoungGenerationMarkingVerifier : public MarkingVerifier {
|
| }
|
| };
|
|
|
| -class EvacuationVerifier : public ObjectVisitor {
|
| +class EvacuationVerifier : public ObjectVisitor, public RootVisitor {
|
| public:
|
| virtual void Run() = 0;
|
|
|
| void VisitPointers(Object** start, Object** end) override {
|
| + VerifyPointers(start, end);
|
| + }
|
| +
|
| + void VisitRootPointers(Root root, Object** start, Object** end) override {
|
| + VerifyPointers(start, end);
|
| + }
|
| +
|
| + protected:
|
| + explicit EvacuationVerifier(Heap* heap) : heap_(heap) {}
|
| +
|
| + void VerifyPointers(Object** start, Object** end) {
|
| for (Object** current = start; current < end; current++) {
|
| if ((*current)->IsHeapObject()) {
|
| HeapObject* object = HeapObject::cast(*current);
|
| @@ -219,9 +240,6 @@ class EvacuationVerifier : public ObjectVisitor {
|
| }
|
| }
|
|
|
| - protected:
|
| - explicit EvacuationVerifier(Heap* heap) : heap_(heap) {}
|
| -
|
| void VerifyRoots(VisitMode mode);
|
| void VerifyEvacuationOnPage(Address start, Address end);
|
| void VerifyEvacuation(NewSpace* new_space);
|
| @@ -1357,17 +1375,26 @@ class CodeMarkingVisitor : public ThreadVisitor {
|
| MarkCompactCollector* collector_;
|
| };
|
|
|
| -
|
| -class SharedFunctionInfoMarkingVisitor : public ObjectVisitor {
|
| +class SharedFunctionInfoMarkingVisitor : public ObjectVisitor,
|
| + public RootVisitor {
|
| public:
|
| explicit SharedFunctionInfoMarkingVisitor(MarkCompactCollector* collector)
|
| : collector_(collector) {}
|
|
|
| void VisitPointers(Object** start, Object** end) override {
|
| - for (Object** p = start; p < end; p++) VisitPointer(p);
|
| + for (Object** p = start; p < end; p++) MarkObject(p);
|
| + }
|
| +
|
| + void VisitPointer(Object** slot) override { MarkObject(slot); }
|
| +
|
| + void VisitRootPointers(Root root, Object** start, Object** end) override {
|
| + for (Object** p = start; p < end; p++) MarkObject(p);
|
| }
|
|
|
| - void VisitPointer(Object** slot) override {
|
| + void VisitRootPointer(Root root, Object** slot) override { MarkObject(slot); }
|
| +
|
| + private:
|
| + void MarkObject(Object** slot) {
|
| Object* obj = *slot;
|
| if (obj->IsSharedFunctionInfo()) {
|
| SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(obj);
|
| @@ -1375,8 +1402,6 @@ class SharedFunctionInfoMarkingVisitor : public ObjectVisitor {
|
| collector_->MarkObject(shared);
|
| }
|
| }
|
| -
|
| - private:
|
| MarkCompactCollector* collector_;
|
| };
|
|
|
| @@ -1421,21 +1446,19 @@ void MarkCompactCollector::PrepareForCodeFlushing() {
|
| ProcessMarkingDeque();
|
| }
|
|
|
| -class MinorMarkCompactCollector::RootMarkingVisitor : public ObjectVisitor {
|
| +class MinorMarkCompactCollector::RootMarkingVisitor : public RootVisitor {
|
| public:
|
| explicit RootMarkingVisitor(MinorMarkCompactCollector* collector)
|
| : collector_(collector) {}
|
|
|
| - void VisitPointer(Object** p) override { MarkObjectByPointer(p); }
|
| + void VisitRootPointer(Root root, Object** p) override {
|
| + MarkObjectByPointer(p);
|
| + }
|
|
|
| - void VisitPointers(Object** start, Object** end) override {
|
| + void VisitRootPointers(Root root, Object** start, Object** end) override {
|
| for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
|
| }
|
|
|
| - // Skip the weak next code link in a code object, which is visited in
|
| - // ProcessTopOptimizedFrame.
|
| - void VisitNextCodeLink(Object** p) override {}
|
| -
|
| private:
|
| void MarkObjectByPointer(Object** p) {
|
| if (!(*p)->IsHeapObject()) return;
|
| @@ -1460,7 +1483,10 @@ class MinorMarkCompactCollector::RootMarkingVisitor : public ObjectVisitor {
|
| };
|
|
|
| // Visitor class for marking heap roots.
|
| -class MarkCompactCollector::RootMarkingVisitor : public ObjectVisitor {
|
| +// TODO(ulan): Remove ObjectVisitor base class after fixing marking of
|
| +// the string table and the top optimized code.
|
| +class MarkCompactCollector::RootMarkingVisitor : public ObjectVisitor,
|
| + public RootVisitor {
|
| public:
|
| explicit RootMarkingVisitor(Heap* heap)
|
| : collector_(heap->mark_compact_collector()) {}
|
| @@ -1471,6 +1497,14 @@ class MarkCompactCollector::RootMarkingVisitor : public ObjectVisitor {
|
| for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
|
| }
|
|
|
| + void VisitRootPointer(Root root, Object** p) override {
|
| + MarkObjectByPointer(p);
|
| + }
|
| +
|
| + void VisitRootPointers(Root root, Object** start, Object** end) override {
|
| + for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
|
| + }
|
| +
|
| // Skip the weak next code link in a code object, which is visited in
|
| // ProcessTopOptimizedFrame.
|
| void VisitNextCodeLink(Object** p) override {}
|
| @@ -1502,38 +1536,25 @@ class MarkCompactCollector::RootMarkingVisitor : public ObjectVisitor {
|
| MarkCompactCollector* collector_;
|
| };
|
|
|
| -
|
| -// Helper class for pruning the string table.
|
| -template <bool finalize_external_strings, bool record_slots>
|
| -class StringTableCleaner : public ObjectVisitor {
|
| +class InternalizedStringTableCleaner : public ObjectVisitor {
|
| public:
|
| - StringTableCleaner(Heap* heap, HeapObject* table)
|
| - : heap_(heap), pointers_removed_(0), table_(table) {
|
| - DCHECK(!record_slots || table != nullptr);
|
| - }
|
| + InternalizedStringTableCleaner(Heap* heap, HeapObject* table)
|
| + : heap_(heap), pointers_removed_(0), table_(table) {}
|
|
|
| void VisitPointers(Object** start, Object** end) override {
|
| // Visit all HeapObject pointers in [start, end).
|
| MarkCompactCollector* collector = heap_->mark_compact_collector();
|
| + Object* the_hole = heap_->the_hole_value();
|
| for (Object** p = start; p < end; p++) {
|
| Object* o = *p;
|
| if (o->IsHeapObject()) {
|
| HeapObject* heap_object = HeapObject::cast(o);
|
| if (ObjectMarking::IsWhite(heap_object,
|
| MarkingState::Internal(heap_object))) {
|
| - if (finalize_external_strings) {
|
| - if (o->IsExternalString()) {
|
| - heap_->FinalizeExternalString(String::cast(*p));
|
| - } else {
|
| - // The original external string may have been internalized.
|
| - DCHECK(o->IsThinString());
|
| - }
|
| - } else {
|
| - pointers_removed_++;
|
| - }
|
| + pointers_removed_++;
|
| // Set the entry to the_hole_value (as deleted).
|
| - *p = heap_->the_hole_value();
|
| - } else if (record_slots) {
|
| + *p = the_hole;
|
| + } else {
|
| // StringTable contains only old space strings.
|
| DCHECK(!heap_->InNewSpace(o));
|
| collector->RecordSlot(table_, p, o);
|
| @@ -1543,7 +1564,6 @@ class StringTableCleaner : public ObjectVisitor {
|
| }
|
|
|
| int PointersRemoved() {
|
| - DCHECK(!finalize_external_strings);
|
| return pointers_removed_;
|
| }
|
|
|
| @@ -1553,8 +1573,35 @@ class StringTableCleaner : public ObjectVisitor {
|
| HeapObject* table_;
|
| };
|
|
|
| -typedef StringTableCleaner<false, true> InternalizedStringTableCleaner;
|
| -typedef StringTableCleaner<true, false> ExternalStringTableCleaner;
|
| +class ExternalStringTableCleaner : public RootVisitor {
|
| + public:
|
| + explicit ExternalStringTableCleaner(Heap* heap) : heap_(heap) {}
|
| +
|
| + void VisitRootPointers(Root root, Object** start, Object** end) override {
|
| + // Visit all HeapObject pointers in [start, end).
|
| + Object* the_hole = heap_->the_hole_value();
|
| + for (Object** p = start; p < end; p++) {
|
| + Object* o = *p;
|
| + if (o->IsHeapObject()) {
|
| + HeapObject* heap_object = HeapObject::cast(o);
|
| + if (ObjectMarking::IsWhite(heap_object,
|
| + MarkingState::Internal(heap_object))) {
|
| + if (o->IsExternalString()) {
|
| + heap_->FinalizeExternalString(String::cast(*p));
|
| + } else {
|
| + // The original external string may have been internalized.
|
| + DCHECK(o->IsThinString());
|
| + }
|
| + // Set the entry to the_hole_value (as deleted).
|
| + *p = the_hole;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + private:
|
| + Heap* heap_;
|
| +};
|
|
|
| // Implementation of WeakObjectRetainer for mark compact GCs. All marked objects
|
| // are retained.
|
| @@ -2151,7 +2198,7 @@ void MarkCompactCollector::ProcessMarkingDeque() {
|
| // Mark all objects reachable (transitively) from objects on the marking
|
| // stack including references only considered in the atomic marking pause.
|
| void MarkCompactCollector::ProcessEphemeralMarking(
|
| - ObjectVisitor* visitor, bool only_process_harmony_weak_collections) {
|
| + bool only_process_harmony_weak_collections) {
|
| DCHECK(marking_deque()->IsEmpty() && !marking_deque()->overflowed());
|
| bool work_to_do = true;
|
| while (work_to_do) {
|
| @@ -2179,7 +2226,8 @@ void MarkCompactCollector::ProcessEphemeralMarking(
|
| CHECK_EQ(0, heap()->local_embedder_heap_tracer()->NumberOfWrappersToTrace());
|
| }
|
|
|
| -void MarkCompactCollector::ProcessTopOptimizedFrame(ObjectVisitor* visitor) {
|
| +void MarkCompactCollector::ProcessTopOptimizedFrame(
|
| + RootMarkingVisitor* visitor) {
|
| for (StackFrameIterator it(isolate(), isolate()->thread_local_top());
|
| !it.done(); it.Advance()) {
|
| if (it.frame()->type() == StackFrame::JAVA_SCRIPT) {
|
| @@ -2409,7 +2457,7 @@ void MinorMarkCompactCollector::MarkLiveObjects() {
|
|
|
| {
|
| TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK_WEAK);
|
| - heap()->VisitEncounteredWeakCollections(&root_visitor);
|
| + heap()->IterateEncounteredWeakCollections(&root_visitor);
|
| ProcessMarkingDeque();
|
| }
|
|
|
| @@ -2510,7 +2558,7 @@ void MarkCompactCollector::MarkLiveObjects() {
|
| {
|
| TRACE_GC(heap()->tracer(),
|
| GCTracer::Scope::MC_MARK_WEAK_CLOSURE_EPHEMERAL);
|
| - ProcessEphemeralMarking(&root_visitor, false);
|
| + ProcessEphemeralMarking(false);
|
| }
|
|
|
| // The objects reachable from the roots, weak maps or object groups
|
| @@ -2543,7 +2591,7 @@ void MarkCompactCollector::MarkLiveObjects() {
|
| // processed and no weakly reachable node can discover new objects groups.
|
| {
|
| TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE_HARMONY);
|
| - ProcessEphemeralMarking(&root_visitor, true);
|
| + ProcessEphemeralMarking(true);
|
| {
|
| TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_EPILOGUE);
|
| heap()->local_embedder_heap_tracer()->TraceEpilogue();
|
| @@ -2567,7 +2615,7 @@ void MarkCompactCollector::ClearNonLiveReferences() {
|
| string_table->IterateElements(&internalized_visitor);
|
| string_table->ElementsRemoved(internalized_visitor.PointersRemoved());
|
|
|
| - ExternalStringTableCleaner external_visitor(heap(), nullptr);
|
| + ExternalStringTableCleaner external_visitor(heap());
|
| heap()->external_string_table_.IterateAll(&external_visitor);
|
| heap()->external_string_table_.CleanUpAll();
|
| }
|
| @@ -3038,9 +3086,11 @@ static inline SlotCallbackResult UpdateSlot(Object** slot) {
|
| return REMOVE_SLOT;
|
| }
|
|
|
| -// Visitor for updating pointers from live objects in old spaces to new space.
|
| +// Visitor for updating root pointers and to-space pointers.
|
| // It does not expect to encounter pointers to dead objects.
|
| -class PointersUpdatingVisitor : public ObjectVisitor {
|
| +// TODO(ulan): Remove code object specific functions. This visitor
|
| +// nevers visits code objects.
|
| +class PointersUpdatingVisitor : public ObjectVisitor, public RootVisitor {
|
| public:
|
| void VisitPointer(Object** p) override { UpdateSlot(p); }
|
|
|
| @@ -3048,6 +3098,12 @@ class PointersUpdatingVisitor : public ObjectVisitor {
|
| for (Object** p = start; p < end; p++) UpdateSlot(p);
|
| }
|
|
|
| + void VisitRootPointer(Root root, Object** p) override { UpdateSlot(p); }
|
| +
|
| + void VisitRootPointers(Root root, Object** start, Object** end) override {
|
| + for (Object** p = start; p < end; p++) UpdateSlot(p);
|
| + }
|
| +
|
| void VisitCell(RelocInfo* rinfo) override {
|
| UpdateTypedSlotHelper::UpdateCell(rinfo, UpdateSlot);
|
| }
|
| @@ -3909,13 +3965,13 @@ void UpdateToSpacePointersInParallel(Heap* heap, base::Semaphore* semaphore) {
|
| void MarkCompactCollector::UpdatePointersAfterEvacuation() {
|
| TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS);
|
|
|
| - PointersUpdatingVisitor updating_visitor;
|
|
|
| {
|
| TRACE_GC(heap()->tracer(),
|
| GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW);
|
| UpdateToSpacePointersInParallel(heap_, &page_parallel_job_semaphore_);
|
| // Update roots.
|
| + PointersUpdatingVisitor updating_visitor;
|
| heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE);
|
| UpdatePointersInParallel<OLD_TO_NEW>(heap_, &page_parallel_job_semaphore_);
|
| }
|
|
|