Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: src/heap/mark-compact.cc

Issue 2439063002: [heap] Refactor marking deque. (Closed)
Patch Set: Stop incremental marking if it is in sweeping state Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/heap/mark-compact.h ('k') | test/cctest/heap/test-mark-compact.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 page_parallel_job_semaphore_(0), 51 page_parallel_job_semaphore_(0),
52 #ifdef DEBUG 52 #ifdef DEBUG
53 state_(IDLE), 53 state_(IDLE),
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),
62 marking_deque_memory_committed_(0),
63 code_flusher_(nullptr), 61 code_flusher_(nullptr),
64 sweeper_(heap) { 62 sweeper_(heap) {
65 } 63 }
66 64
67 #ifdef VERIFY_HEAP 65 #ifdef VERIFY_HEAP
68 class VerifyMarkingVisitor : public ObjectVisitor { 66 class VerifyMarkingVisitor : public ObjectVisitor {
69 public: 67 public:
70 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {} 68 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {}
71 69
72 void VisitPointers(Object** start, Object** end) override { 70 void VisitPointers(Object** start, Object** end) override {
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 heap->IterateStrongRoots(&visitor, VISIT_ALL); 231 heap->IterateStrongRoots(&visitor, VISIT_ALL);
234 } 232 }
235 #endif // VERIFY_HEAP 233 #endif // VERIFY_HEAP
236 234
237 235
238 void MarkCompactCollector::SetUp() { 236 void MarkCompactCollector::SetUp() {
239 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); 237 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
240 DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0); 238 DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
241 DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0); 239 DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0);
242 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); 240 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
243 241 marking_deque()->SetUp();
244 EnsureMarkingDequeIsReserved();
245 EnsureMarkingDequeIsCommitted(kMinMarkingDequeSize);
246 242
247 if (FLAG_flush_code) { 243 if (FLAG_flush_code) {
248 code_flusher_ = new CodeFlusher(isolate()); 244 code_flusher_ = new CodeFlusher(isolate());
249 if (FLAG_trace_code_flushing) { 245 if (FLAG_trace_code_flushing) {
250 PrintF("[code-flushing is now on]\n"); 246 PrintF("[code-flushing is now on]\n");
251 } 247 }
252 } 248 }
253 } 249 }
254 250
255 251
256 void MarkCompactCollector::TearDown() { 252 void MarkCompactCollector::TearDown() {
257 AbortCompaction(); 253 AbortCompaction();
258 delete marking_deque_memory_; 254 marking_deque()->TearDown();
259 delete code_flusher_; 255 delete code_flusher_;
260 } 256 }
261 257
262 258
263 void MarkCompactCollector::AddEvacuationCandidate(Page* p) { 259 void MarkCompactCollector::AddEvacuationCandidate(Page* p) {
264 DCHECK(!p->NeverEvacuate()); 260 DCHECK(!p->NeverEvacuate());
265 p->MarkEvacuationCandidate(); 261 p->MarkEvacuationCandidate();
266 evacuation_candidates_.Add(p); 262 evacuation_candidates_.Add(p);
267 } 263 }
268 264
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 state_ = PREPARE_GC; 772 state_ = PREPARE_GC;
777 #endif 773 #endif
778 774
779 DCHECK(!FLAG_never_compact || !FLAG_always_compact); 775 DCHECK(!FLAG_never_compact || !FLAG_always_compact);
780 776
781 if (sweeping_in_progress()) { 777 if (sweeping_in_progress()) {
782 // Instead of waiting we could also abort the sweeper threads here. 778 // Instead of waiting we could also abort the sweeper threads here.
783 EnsureSweepingCompleted(); 779 EnsureSweepingCompleted();
784 } 780 }
785 781
782 if (heap()->incremental_marking()->IsSweeping()) {
783 heap()->incremental_marking()->Stop();
784 }
785
786 // If concurrent unmapping tasks are still running, we should wait for 786 // If concurrent unmapping tasks are still running, we should wait for
787 // them here. 787 // them here.
788 heap()->memory_allocator()->unmapper()->WaitUntilCompleted(); 788 heap()->memory_allocator()->unmapper()->WaitUntilCompleted();
789 789
790 // Clear marking bits if incremental marking is aborted. 790 // Clear marking bits if incremental marking is aborted.
791 if (was_marked_incrementally_ && heap_->ShouldAbortIncrementalMarking()) { 791 if (was_marked_incrementally_ && heap_->ShouldAbortIncrementalMarking()) {
792 heap()->incremental_marking()->Stop(); 792 heap()->incremental_marking()->Stop();
793 heap()->incremental_marking()->AbortBlackAllocation(); 793 heap()->incremental_marking()->AbortBlackAllocation();
794 ClearMarkbits(); 794 ClearMarkbits();
795 AbortWeakCollections(); 795 AbortWeakCollections();
796 AbortWeakCells(); 796 AbortWeakCells();
797 AbortTransitionArrays(); 797 AbortTransitionArrays();
798 AbortCompaction(); 798 AbortCompaction();
799 if (heap_->UsingEmbedderHeapTracer()) { 799 if (heap_->UsingEmbedderHeapTracer()) {
800 heap_->embedder_heap_tracer()->AbortTracing(); 800 heap_->embedder_heap_tracer()->AbortTracing();
801 } 801 }
802 marking_deque()->Clear();
802 was_marked_incrementally_ = false; 803 was_marked_incrementally_ = false;
803 } 804 }
804 805
805 if (!was_marked_incrementally_) { 806 if (!was_marked_incrementally_) {
806 if (heap_->UsingEmbedderHeapTracer()) { 807 if (heap_->UsingEmbedderHeapTracer()) {
807 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_PROLOGUE); 808 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_PROLOGUE);
808 heap_->embedder_heap_tracer()->TracePrologue( 809 heap_->embedder_heap_tracer()->TracePrologue(
809 heap_->embedder_reachable_reference_reporter()); 810 heap_->embedder_reachable_reference_reporter());
810 } 811 }
811 } 812 }
(...skipping 1287 matching lines...) Expand 10 before | Expand all | Expand 10 after
2099 Code* code = it.frame()->LookupCode(); 2100 Code* code = it.frame()->LookupCode();
2100 if (!code->CanDeoptAt(it.frame()->pc())) { 2101 if (!code->CanDeoptAt(it.frame()->pc())) {
2101 Code::BodyDescriptor::IterateBody(code, visitor); 2102 Code::BodyDescriptor::IterateBody(code, visitor);
2102 } 2103 }
2103 ProcessMarkingDeque(); 2104 ProcessMarkingDeque();
2104 return; 2105 return;
2105 } 2106 }
2106 } 2107 }
2107 } 2108 }
2108 2109
2109 2110 void MarkingDeque::SetUp() {
2110 void MarkCompactCollector::EnsureMarkingDequeIsReserved() { 2111 backing_store_ = new base::VirtualMemory(kMaxSize);
2111 DCHECK(!marking_deque()->in_use()); 2112 backing_store_committed_size_ = 0;
2112 if (marking_deque_memory_ == NULL) { 2113 if (backing_store_ == nullptr) {
2113 marking_deque_memory_ = new base::VirtualMemory(kMaxMarkingDequeSize); 2114 V8::FatalProcessOutOfMemory("MarkingDeque::SetUp");
2114 marking_deque_memory_committed_ = 0;
2115 }
2116 if (marking_deque_memory_ == NULL) {
2117 V8::FatalProcessOutOfMemory("EnsureMarkingDequeIsReserved");
2118 } 2115 }
2119 } 2116 }
2120 2117
2118 void MarkingDeque::TearDown() { delete backing_store_; }
2121 2119
2122 void MarkCompactCollector::EnsureMarkingDequeIsCommitted(size_t max_size) { 2120 void MarkingDeque::StartUsing() {
2123 // If the marking deque is too small, we try to allocate a bigger one. 2121 if (in_use_) {
2124 // If that fails, make do with a smaller one. 2122 // This can happen in mark-compact GC if the incremental marker already
2125 CHECK(!marking_deque()->in_use()); 2123 // started using the marking deque.
2126 for (size_t size = max_size; size >= kMinMarkingDequeSize; size >>= 1) { 2124 return;
2127 base::VirtualMemory* memory = marking_deque_memory_;
2128 size_t currently_committed = marking_deque_memory_committed_;
2129
2130 if (currently_committed == size) return;
2131
2132 if (currently_committed > size) {
2133 bool success = marking_deque_memory_->Uncommit(
2134 reinterpret_cast<Address>(marking_deque_memory_->address()) + size,
2135 currently_committed - size);
2136 if (success) {
2137 marking_deque_memory_committed_ = size;
2138 return;
2139 }
2140 UNREACHABLE();
2141 }
2142
2143 bool success = memory->Commit(
2144 reinterpret_cast<Address>(memory->address()) + currently_committed,
2145 size - currently_committed,
2146 false); // Not executable.
2147 if (success) {
2148 marking_deque_memory_committed_ = size;
2149 return;
2150 }
2151 } 2125 }
2152 V8::FatalProcessOutOfMemory("EnsureMarkingDequeIsCommitted"); 2126 in_use_ = true;
2127 EnsureCommitted();
2128 array_ = reinterpret_cast<HeapObject**>(backing_store_->address());
2129 size_t size = FLAG_force_marking_deque_overflows
2130 ? 64 * kPointerSize
2131 : backing_store_committed_size_;
2132 DCHECK(
2133 base::bits::IsPowerOfTwo32(static_cast<uint32_t>(size / kPointerSize)));
2134 mask_ = static_cast<int>((size / kPointerSize) - 1);
2135 top_ = bottom_ = 0;
2136 overflowed_ = false;
2153 } 2137 }
2154 2138
2155 2139 void MarkingDeque::StopUsing() {
2156 void MarkCompactCollector::InitializeMarkingDeque() { 2140 DCHECK(IsEmpty());
2157 DCHECK(!marking_deque()->in_use()); 2141 DCHECK(!overflowed_);
2158 DCHECK(marking_deque_memory_committed_ > 0); 2142 top_ = bottom_ = mask_ = 0;
2159 Address addr = static_cast<Address>(marking_deque_memory_->address()); 2143 Uncommit();
2160 size_t size = marking_deque_memory_committed_;
2161 if (FLAG_force_marking_deque_overflows) size = 64 * kPointerSize;
2162 marking_deque()->Initialize(addr, addr + size);
2163 }
2164
2165
2166 void MarkingDeque::Initialize(Address low, Address high) {
2167 DCHECK(!in_use_);
2168 HeapObject** obj_low = reinterpret_cast<HeapObject**>(low);
2169 HeapObject** obj_high = reinterpret_cast<HeapObject**>(high);
2170 array_ = obj_low;
2171 mask_ = base::bits::RoundDownToPowerOfTwo32(
2172 static_cast<uint32_t>(obj_high - obj_low)) -
2173 1;
2174 top_ = bottom_ = 0;
2175 overflowed_ = false;
2176 in_use_ = true;
2177 }
2178
2179
2180 void MarkingDeque::Uninitialize(bool aborting) {
2181 if (!aborting) {
2182 DCHECK(IsEmpty());
2183 DCHECK(!overflowed_);
2184 }
2185 DCHECK(in_use_);
2186 top_ = bottom_ = 0xdecbad;
2187 in_use_ = false; 2144 in_use_ = false;
2188 } 2145 }
2189 2146
2147 void MarkingDeque::Clear() {
2148 DCHECK(in_use_);
2149 top_ = bottom_ = 0;
2150 overflowed_ = false;
2151 }
2152
2153 void MarkingDeque::Uncommit() {
2154 DCHECK(in_use_);
2155 bool success = backing_store_->Uncommit(backing_store_->address(),
2156 backing_store_committed_size_);
2157 backing_store_committed_size_ = 0;
2158 CHECK(success);
2159 }
2160
2161 void MarkingDeque::EnsureCommitted() {
2162 DCHECK(in_use_);
2163 if (backing_store_committed_size_ > 0) return;
2164
2165 for (size_t size = kMaxSize; size >= kMinSize; size /= 2) {
2166 if (backing_store_->Commit(backing_store_->address(), size, false)) {
2167 backing_store_committed_size_ = size;
2168 break;
2169 }
2170 }
2171 if (backing_store_committed_size_ == 0) {
2172 V8::FatalProcessOutOfMemory("MarkingDeque::EnsureCommitted");
2173 }
2174 }
2175
2190 class MarkCompactCollector::ObjectStatsVisitor 2176 class MarkCompactCollector::ObjectStatsVisitor
2191 : public MarkCompactCollector::HeapObjectVisitor { 2177 : public MarkCompactCollector::HeapObjectVisitor {
2192 public: 2178 public:
2193 ObjectStatsVisitor(Heap* heap, ObjectStats* live_stats, 2179 ObjectStatsVisitor(Heap* heap, ObjectStats* live_stats,
2194 ObjectStats* dead_stats) 2180 ObjectStats* dead_stats)
2195 : live_collector_(heap, live_stats), dead_collector_(heap, dead_stats) { 2181 : live_collector_(heap, live_stats), dead_collector_(heap, dead_stats) {
2196 DCHECK_NOT_NULL(live_stats); 2182 DCHECK_NOT_NULL(live_stats);
2197 DCHECK_NOT_NULL(dead_stats); 2183 DCHECK_NOT_NULL(dead_stats);
2198 // Global objects are roots and thus recorded as live. 2184 // Global objects are roots and thus recorded as live.
2199 live_collector_.CollectGlobalStatistics(); 2185 live_collector_.CollectGlobalStatistics();
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2253 // and switches to a different marking system. JS interrupts interfere 2239 // and switches to a different marking system. JS interrupts interfere
2254 // with the C stack limit check. 2240 // with the C stack limit check.
2255 PostponeInterruptsScope postpone(isolate()); 2241 PostponeInterruptsScope postpone(isolate());
2256 2242
2257 { 2243 {
2258 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_FINISH_INCREMENTAL); 2244 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_FINISH_INCREMENTAL);
2259 IncrementalMarking* incremental_marking = heap_->incremental_marking(); 2245 IncrementalMarking* incremental_marking = heap_->incremental_marking();
2260 if (was_marked_incrementally_) { 2246 if (was_marked_incrementally_) {
2261 incremental_marking->Finalize(); 2247 incremental_marking->Finalize();
2262 } else { 2248 } else {
2263 // Abort any pending incremental activities e.g. incremental sweeping. 2249 CHECK(incremental_marking->IsStopped());
2264 incremental_marking->Stop();
2265 if (marking_deque()->in_use()) {
2266 marking_deque()->Uninitialize(true);
2267 }
2268 } 2250 }
2269 } 2251 }
2270 2252
2271 #ifdef DEBUG 2253 #ifdef DEBUG
2272 DCHECK(state_ == PREPARE_GC); 2254 DCHECK(state_ == PREPARE_GC);
2273 state_ = MARK_LIVE_OBJECTS; 2255 state_ = MARK_LIVE_OBJECTS;
2274 #endif 2256 #endif
2275 2257
2276 EnsureMarkingDequeIsCommittedAndInitialize( 2258 marking_deque()->StartUsing();
2277 MarkCompactCollector::kMaxMarkingDequeSize);
2278 2259
2279 { 2260 {
2280 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_PREPARE_CODE_FLUSH); 2261 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_PREPARE_CODE_FLUSH);
2281 PrepareForCodeFlushing(); 2262 PrepareForCodeFlushing();
2282 } 2263 }
2283 2264
2284 RootMarkingVisitor root_visitor(heap()); 2265 RootMarkingVisitor root_visitor(heap());
2285 2266
2286 { 2267 {
2287 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_ROOTS); 2268 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_ROOTS);
(...skipping 1623 matching lines...) Expand 10 before | Expand all | Expand 10 after
3911 // The target is always in old space, we don't have to record the slot in 3892 // The target is always in old space, we don't have to record the slot in
3912 // the old-to-new remembered set. 3893 // the old-to-new remembered set.
3913 DCHECK(!heap()->InNewSpace(target)); 3894 DCHECK(!heap()->InNewSpace(target));
3914 RecordRelocSlot(host, &rinfo, target); 3895 RecordRelocSlot(host, &rinfo, target);
3915 } 3896 }
3916 } 3897 }
3917 } 3898 }
3918 3899
3919 } // namespace internal 3900 } // namespace internal
3920 } // namespace v8 3901 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap/mark-compact.h ('k') | test/cctest/heap/test-mark-compact.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698