OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/heap/mark-compact.h" | 5 #include "src/heap/mark-compact.h" |
6 | 6 |
7 #include "src/base/atomicops.h" | 7 #include "src/base/atomicops.h" |
8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
9 #include "src/base/sys-info.h" | 9 #include "src/base/sys-info.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 #endif | 54 #endif |
55 marking_parity_(ODD_MARKING_PARITY), | 55 marking_parity_(ODD_MARKING_PARITY), |
56 was_marked_incrementally_(false), | 56 was_marked_incrementally_(false), |
57 evacuation_(false), | 57 evacuation_(false), |
58 compacting_(false), | 58 compacting_(false), |
59 black_allocation_(false), | 59 black_allocation_(false), |
60 have_code_to_deoptimize_(false), | 60 have_code_to_deoptimize_(false), |
61 marking_deque_memory_(NULL), | 61 marking_deque_memory_(NULL), |
62 marking_deque_memory_committed_(0), | 62 marking_deque_memory_committed_(0), |
63 code_flusher_(nullptr), | 63 code_flusher_(nullptr), |
64 embedder_heap_tracer_(nullptr), | |
65 sweeper_(heap) { | 64 sweeper_(heap) { |
66 } | 65 } |
67 | 66 |
68 #ifdef VERIFY_HEAP | 67 #ifdef VERIFY_HEAP |
69 class VerifyMarkingVisitor : public ObjectVisitor { | 68 class VerifyMarkingVisitor : public ObjectVisitor { |
70 public: | 69 public: |
71 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {} | 70 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {} |
72 | 71 |
73 void VisitPointers(Object** start, Object** end) override { | 72 void VisitPointers(Object** start, Object** end) override { |
74 for (Object** current = start; current < end; current++) { | 73 for (Object** current = start; current < end; current++) { |
(...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
802 // Clear marking bits if incremental marking is aborted. | 801 // Clear marking bits if incremental marking is aborted. |
803 if (was_marked_incrementally_ && heap_->ShouldAbortIncrementalMarking()) { | 802 if (was_marked_incrementally_ && heap_->ShouldAbortIncrementalMarking()) { |
804 heap()->incremental_marking()->Stop(); | 803 heap()->incremental_marking()->Stop(); |
805 heap()->incremental_marking()->AbortBlackAllocation(); | 804 heap()->incremental_marking()->AbortBlackAllocation(); |
806 ClearMarkbits(); | 805 ClearMarkbits(); |
807 AbortWeakCollections(); | 806 AbortWeakCollections(); |
808 AbortWeakCells(); | 807 AbortWeakCells(); |
809 AbortTransitionArrays(); | 808 AbortTransitionArrays(); |
810 AbortCompaction(); | 809 AbortCompaction(); |
811 if (heap_->UsingEmbedderHeapTracer()) { | 810 if (heap_->UsingEmbedderHeapTracer()) { |
812 heap_->mark_compact_collector()->embedder_heap_tracer()->AbortTracing(); | 811 heap_->embedder_heap_tracer()->AbortTracing(); |
813 } | 812 } |
814 was_marked_incrementally_ = false; | 813 was_marked_incrementally_ = false; |
815 } | 814 } |
816 | 815 |
817 if (!was_marked_incrementally_) { | 816 if (!was_marked_incrementally_) { |
818 if (heap_->UsingEmbedderHeapTracer()) { | 817 if (heap_->UsingEmbedderHeapTracer()) { |
819 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_PROLOGUE); | 818 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_PROLOGUE); |
820 heap_->mark_compact_collector()->embedder_heap_tracer()->TracePrologue(); | 819 heap_->embedder_heap_tracer()->TracePrologue( |
| 820 heap_->embedder_reachable_reference_reporter()); |
821 } | 821 } |
822 } | 822 } |
823 | 823 |
824 if (UsingEmbedderHeapTracer()) { | 824 if (heap_->UsingEmbedderHeapTracer()) { |
825 embedder_heap_tracer()->EnterFinalPause(); | 825 heap_->embedder_heap_tracer()->EnterFinalPause(); |
826 } | 826 } |
827 | 827 |
828 // Don't start compaction if we are in the middle of incremental | 828 // Don't start compaction if we are in the middle of incremental |
829 // marking cycle. We did not collect any slots. | 829 // marking cycle. We did not collect any slots. |
830 if (!FLAG_never_compact && !was_marked_incrementally_) { | 830 if (!FLAG_never_compact && !was_marked_incrementally_) { |
831 StartCompaction(NON_INCREMENTAL_COMPACTION); | 831 StartCompaction(NON_INCREMENTAL_COMPACTION); |
832 } | 832 } |
833 | 833 |
834 PagedSpaces spaces(heap()); | 834 PagedSpaces spaces(heap()); |
835 for (PagedSpace* space = spaces.next(); space != NULL; | 835 for (PagedSpace* space = spaces.next(); space != NULL; |
(...skipping 1242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2078 } | 2078 } |
2079 } | 2079 } |
2080 | 2080 |
2081 // Mark all objects reachable (transitively) from objects on the marking | 2081 // Mark all objects reachable (transitively) from objects on the marking |
2082 // stack including references only considered in the atomic marking pause. | 2082 // stack including references only considered in the atomic marking pause. |
2083 void MarkCompactCollector::ProcessEphemeralMarking( | 2083 void MarkCompactCollector::ProcessEphemeralMarking( |
2084 ObjectVisitor* visitor, bool only_process_harmony_weak_collections) { | 2084 ObjectVisitor* visitor, bool only_process_harmony_weak_collections) { |
2085 DCHECK(marking_deque_.IsEmpty() && !marking_deque_.overflowed()); | 2085 DCHECK(marking_deque_.IsEmpty() && !marking_deque_.overflowed()); |
2086 bool work_to_do = true; | 2086 bool work_to_do = true; |
2087 while (work_to_do) { | 2087 while (work_to_do) { |
2088 if (UsingEmbedderHeapTracer()) { | 2088 if (heap_->UsingEmbedderHeapTracer()) { |
2089 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_TRACING); | 2089 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_TRACING); |
2090 RegisterWrappersWithEmbedderHeapTracer(); | 2090 heap_->RegisterWrappersWithEmbedderHeapTracer(); |
2091 embedder_heap_tracer()->AdvanceTracing( | 2091 heap_->embedder_heap_tracer()->AdvanceTracing( |
2092 0, EmbedderHeapTracer::AdvanceTracingActions( | 2092 0, EmbedderHeapTracer::AdvanceTracingActions( |
2093 EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION)); | 2093 EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION)); |
2094 } | 2094 } |
2095 if (!only_process_harmony_weak_collections) { | 2095 if (!only_process_harmony_weak_collections) { |
2096 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_OBJECT_GROUPING); | 2096 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_OBJECT_GROUPING); |
2097 isolate()->global_handles()->IterateObjectGroups( | 2097 isolate()->global_handles()->IterateObjectGroups( |
2098 visitor, &IsUnmarkedHeapObjectWithHeap); | 2098 visitor, &IsUnmarkedHeapObjectWithHeap); |
2099 MarkImplicitRefGroups(&MarkCompactMarkingVisitor::MarkObject); | 2099 MarkImplicitRefGroups(&MarkCompactMarkingVisitor::MarkObject); |
2100 } | 2100 } |
2101 ProcessWeakCollections(); | 2101 ProcessWeakCollections(); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2195 void MarkingDeque::Uninitialize(bool aborting) { | 2195 void MarkingDeque::Uninitialize(bool aborting) { |
2196 if (!aborting) { | 2196 if (!aborting) { |
2197 DCHECK(IsEmpty()); | 2197 DCHECK(IsEmpty()); |
2198 DCHECK(!overflowed_); | 2198 DCHECK(!overflowed_); |
2199 } | 2199 } |
2200 DCHECK(in_use_); | 2200 DCHECK(in_use_); |
2201 top_ = bottom_ = 0xdecbad; | 2201 top_ = bottom_ = 0xdecbad; |
2202 in_use_ = false; | 2202 in_use_ = false; |
2203 } | 2203 } |
2204 | 2204 |
2205 void MarkCompactCollector::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) { | |
2206 DCHECK_NOT_NULL(tracer); | |
2207 CHECK_NULL(embedder_heap_tracer_); | |
2208 embedder_heap_tracer_ = tracer; | |
2209 } | |
2210 | |
2211 bool MarkCompactCollector::RequiresImmediateWrapperProcessing() { | |
2212 const size_t kTooManyWrappers = 16000; | |
2213 return wrappers_to_trace_.size() > kTooManyWrappers; | |
2214 } | |
2215 | |
2216 void MarkCompactCollector::RegisterWrappersWithEmbedderHeapTracer() { | |
2217 DCHECK(UsingEmbedderHeapTracer()); | |
2218 if (wrappers_to_trace_.empty()) { | |
2219 return; | |
2220 } | |
2221 embedder_heap_tracer()->RegisterV8References(wrappers_to_trace_); | |
2222 wrappers_to_trace_.clear(); | |
2223 } | |
2224 | |
2225 void MarkCompactCollector::TracePossibleWrapper(JSObject* js_object) { | |
2226 DCHECK(js_object->WasConstructedFromApiFunction()); | |
2227 if (js_object->GetInternalFieldCount() >= 2 && | |
2228 js_object->GetInternalField(0) && | |
2229 js_object->GetInternalField(0) != heap_->undefined_value() && | |
2230 js_object->GetInternalField(1) != heap_->undefined_value()) { | |
2231 DCHECK(reinterpret_cast<intptr_t>(js_object->GetInternalField(0)) % 2 == 0); | |
2232 wrappers_to_trace_.push_back(std::pair<void*, void*>( | |
2233 reinterpret_cast<void*>(js_object->GetInternalField(0)), | |
2234 reinterpret_cast<void*>(js_object->GetInternalField(1)))); | |
2235 } | |
2236 } | |
2237 | |
2238 class MarkCompactCollector::ObjectStatsVisitor | 2205 class MarkCompactCollector::ObjectStatsVisitor |
2239 : public MarkCompactCollector::HeapObjectVisitor { | 2206 : public MarkCompactCollector::HeapObjectVisitor { |
2240 public: | 2207 public: |
2241 ObjectStatsVisitor(Heap* heap, ObjectStats* live_stats, | 2208 ObjectStatsVisitor(Heap* heap, ObjectStats* live_stats, |
2242 ObjectStats* dead_stats) | 2209 ObjectStats* dead_stats) |
2243 : live_collector_(heap, live_stats), dead_collector_(heap, dead_stats) { | 2210 : live_collector_(heap, live_stats), dead_collector_(heap, dead_stats) { |
2244 DCHECK_NOT_NULL(live_stats); | 2211 DCHECK_NOT_NULL(live_stats); |
2245 DCHECK_NOT_NULL(dead_stats); | 2212 DCHECK_NOT_NULL(dead_stats); |
2246 // Global objects are roots and thus recorded as live. | 2213 // Global objects are roots and thus recorded as live. |
2247 live_collector_.CollectGlobalStatistics(); | 2214 live_collector_.CollectGlobalStatistics(); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2369 } | 2336 } |
2370 | 2337 |
2371 // Repeat Harmony weak maps marking to mark unmarked objects reachable from | 2338 // Repeat Harmony weak maps marking to mark unmarked objects reachable from |
2372 // the weak roots we just marked as pending destruction. | 2339 // the weak roots we just marked as pending destruction. |
2373 // | 2340 // |
2374 // We only process harmony collections, as all object groups have been fully | 2341 // We only process harmony collections, as all object groups have been fully |
2375 // processed and no weakly reachable node can discover new objects groups. | 2342 // processed and no weakly reachable node can discover new objects groups. |
2376 { | 2343 { |
2377 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE_HARMONY); | 2344 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE_HARMONY); |
2378 ProcessEphemeralMarking(&root_visitor, true); | 2345 ProcessEphemeralMarking(&root_visitor, true); |
2379 if (UsingEmbedderHeapTracer()) { | 2346 if (heap_->UsingEmbedderHeapTracer()) { |
2380 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_EPILOGUE); | 2347 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_EPILOGUE); |
2381 embedder_heap_tracer()->TraceEpilogue(); | 2348 heap()->embedder_heap_tracer()->TraceEpilogue(); |
2382 } | 2349 } |
2383 } | 2350 } |
2384 } | 2351 } |
2385 | 2352 |
2386 if (FLAG_print_cumulative_gc_stat) { | 2353 if (FLAG_print_cumulative_gc_stat) { |
2387 heap_->tracer()->AddMarkingTime(heap_->MonotonicallyIncreasingTimeInMs() - | 2354 heap_->tracer()->AddMarkingTime(heap_->MonotonicallyIncreasingTimeInMs() - |
2388 start_time); | 2355 start_time); |
2389 } | 2356 } |
2390 } | 2357 } |
2391 | 2358 |
(...skipping 1650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4042 // The target is always in old space, we don't have to record the slot in | 4009 // The target is always in old space, we don't have to record the slot in |
4043 // the old-to-new remembered set. | 4010 // the old-to-new remembered set. |
4044 DCHECK(!heap()->InNewSpace(target)); | 4011 DCHECK(!heap()->InNewSpace(target)); |
4045 RecordRelocSlot(host, &rinfo, target); | 4012 RecordRelocSlot(host, &rinfo, target); |
4046 } | 4013 } |
4047 } | 4014 } |
4048 } | 4015 } |
4049 | 4016 |
4050 } // namespace internal | 4017 } // namespace internal |
4051 } // namespace v8 | 4018 } // namespace v8 |
OLD | NEW |