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

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

Issue 1133153003: Never uncommit the whole marking deque in case we can't get it back (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Merge Created 5 years, 6 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') | no next file » | 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/v8.h" 5 #include "src/v8.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/code-stubs.h" 9 #include "src/code-stubs.h"
10 #include "src/compilation-cache.h" 10 #include "src/compilation-cache.h"
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 finalize_incremental_marking_(false), 45 finalize_incremental_marking_(false),
46 marking_parity_(ODD_MARKING_PARITY), 46 marking_parity_(ODD_MARKING_PARITY),
47 compacting_(false), 47 compacting_(false),
48 was_marked_incrementally_(false), 48 was_marked_incrementally_(false),
49 sweeping_in_progress_(false), 49 sweeping_in_progress_(false),
50 pending_sweeper_jobs_semaphore_(0), 50 pending_sweeper_jobs_semaphore_(0),
51 evacuation_(false), 51 evacuation_(false),
52 migration_slots_buffer_(NULL), 52 migration_slots_buffer_(NULL),
53 heap_(heap), 53 heap_(heap),
54 marking_deque_memory_(NULL), 54 marking_deque_memory_(NULL),
55 marking_deque_memory_committed_(false), 55 marking_deque_memory_committed_(0),
56 code_flusher_(NULL), 56 code_flusher_(NULL),
57 have_code_to_deoptimize_(false) { 57 have_code_to_deoptimize_(false) {
58 } 58 }
59 59
60 #ifdef VERIFY_HEAP 60 #ifdef VERIFY_HEAP
61 class VerifyMarkingVisitor : public ObjectVisitor { 61 class VerifyMarkingVisitor : public ObjectVisitor {
62 public: 62 public:
63 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {} 63 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {}
64 64
65 void VisitPointers(Object** start, Object** end) { 65 void VisitPointers(Object** start, Object** end) {
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 VerifyEvacuation(heap->new_space()); 219 VerifyEvacuation(heap->new_space());
220 220
221 VerifyEvacuationVisitor visitor; 221 VerifyEvacuationVisitor visitor;
222 heap->IterateStrongRoots(&visitor, VISIT_ALL); 222 heap->IterateStrongRoots(&visitor, VISIT_ALL);
223 } 223 }
224 #endif // VERIFY_HEAP 224 #endif // VERIFY_HEAP
225 225
226 226
227 void MarkCompactCollector::SetUp() { 227 void MarkCompactCollector::SetUp() {
228 free_list_old_space_.Reset(new FreeList(heap_->old_space())); 228 free_list_old_space_.Reset(new FreeList(heap_->old_space()));
229 EnsureMarkingDequeIsCommittedAndInitialize(256 * KB); 229 EnsureMarkingDequeIsReserved();
230 EnsureMarkingDequeIsCommitted(kMinMarkingDequeSize);
230 } 231 }
231 232
232 233
233 void MarkCompactCollector::TearDown() { 234 void MarkCompactCollector::TearDown() {
234 AbortCompaction(); 235 AbortCompaction();
235 delete marking_deque_memory_; 236 delete marking_deque_memory_;
236 } 237 }
237 238
238 239
239 void MarkCompactCollector::AddEvacuationCandidate(Page* p) { 240 void MarkCompactCollector::AddEvacuationCandidate(Page* p) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 } 330 }
330 #endif 331 #endif
331 332
332 333
333 void MarkCompactCollector::CollectGarbage() { 334 void MarkCompactCollector::CollectGarbage() {
334 // Make sure that Prepare() has been called. The individual steps below will 335 // Make sure that Prepare() has been called. The individual steps below will
335 // update the state as they proceed. 336 // update the state as they proceed.
336 DCHECK(state_ == PREPARE_GC); 337 DCHECK(state_ == PREPARE_GC);
337 338
338 MarkLiveObjects(); 339 MarkLiveObjects();
340
339 DCHECK(heap_->incremental_marking()->IsStopped()); 341 DCHECK(heap_->incremental_marking()->IsStopped());
340 342
341 // ClearNonLiveReferences can deoptimize code in dependent code arrays. 343 // ClearNonLiveReferences can deoptimize code in dependent code arrays.
342 // Process weak cells before so that weak cells in dependent code 344 // Process weak cells before so that weak cells in dependent code
343 // arrays are cleared or contain only live code objects. 345 // arrays are cleared or contain only live code objects.
344 ProcessAndClearWeakCells(); 346 ProcessAndClearWeakCells();
345 347
346 if (FLAG_collect_maps) ClearNonLiveReferences(); 348 if (FLAG_collect_maps) ClearNonLiveReferences();
347 349
348 ClearWeakCollections(); 350 ClearWeakCollections();
(...skipping 1793 matching lines...) Expand 10 before | Expand all | Expand 10 after
2142 } 2144 }
2143 Object* undefined = heap()->undefined_value(); 2145 Object* undefined = heap()->undefined_value();
2144 for (int i = new_length; i < length; i++) { 2146 for (int i = new_length; i < length; i++) {
2145 retained_maps->Clear(i, undefined); 2147 retained_maps->Clear(i, undefined);
2146 } 2148 }
2147 if (new_length != length) retained_maps->SetLength(new_length); 2149 if (new_length != length) retained_maps->SetLength(new_length);
2148 ProcessMarkingDeque(); 2150 ProcessMarkingDeque();
2149 } 2151 }
2150 2152
2151 2153
2152 void MarkCompactCollector::EnsureMarkingDequeIsCommittedAndInitialize( 2154 void MarkCompactCollector::EnsureMarkingDequeIsReserved() {
2153 size_t max_size) { 2155 DCHECK(!marking_deque_.in_use());
2156 if (marking_deque_memory_ == NULL) {
2157 marking_deque_memory_ = new base::VirtualMemory(kMaxMarkingDequeSize);
2158 marking_deque_memory_committed_ = 0;
2159 }
2160 if (marking_deque_memory_ == NULL) {
2161 V8::FatalProcessOutOfMemory("EnsureMarkingDequeIsReserved");
2162 }
2163 }
2164
2165
2166 void MarkCompactCollector::EnsureMarkingDequeIsCommitted(size_t max_size) {
2154 // If the marking deque is too small, we try to allocate a bigger one. 2167 // If the marking deque is too small, we try to allocate a bigger one.
2155 // If that fails, make do with a smaller one. 2168 // If that fails, make do with a smaller one.
2156 for (size_t size = max_size; size >= 256 * KB; size >>= 1) { 2169 CHECK(!marking_deque_.in_use());
2170 for (size_t size = max_size; size >= kMinMarkingDequeSize; size >>= 1) {
2157 base::VirtualMemory* memory = marking_deque_memory_; 2171 base::VirtualMemory* memory = marking_deque_memory_;
2158 bool is_committed = marking_deque_memory_committed_; 2172 size_t currently_committed = marking_deque_memory_committed_;
2159 2173
2160 if (memory == NULL || memory->size() < size) { 2174 if (currently_committed == size) return;
2161 // If we don't have memory or we only have small memory, then 2175
2162 // try to reserve a new one. 2176 if (currently_committed > size) {
2163 memory = new base::VirtualMemory(size); 2177 bool success = marking_deque_memory_->Uncommit(
2164 is_committed = false; 2178 reinterpret_cast<Address>(marking_deque_memory_->address()) + size,
2179 currently_committed - size);
2180 if (success) {
2181 marking_deque_memory_committed_ = size;
2182 return;
2183 }
2184 UNREACHABLE();
2165 } 2185 }
2166 if (is_committed) return; 2186
2167 if (memory->IsReserved() && 2187 bool success = memory->Commit(
2168 memory->Commit(reinterpret_cast<Address>(memory->address()), 2188 reinterpret_cast<Address>(memory->address()) + currently_committed,
2169 memory->size(), 2189 size - currently_committed,
2170 false)) { // Not executable. 2190 false); // Not executable.
2171 if (marking_deque_memory_ != NULL && marking_deque_memory_ != memory) { 2191 if (success) {
2172 delete marking_deque_memory_; 2192 marking_deque_memory_committed_ = size;
2173 }
2174 marking_deque_memory_ = memory;
2175 marking_deque_memory_committed_ = true;
2176 InitializeMarkingDeque();
2177 return; 2193 return;
2178 } else {
2179 // Commit failed, so we are under memory pressure. If this was the
2180 // previously reserved area we tried to commit, then remove references
2181 // to it before deleting it and unreserving it.
2182 if (marking_deque_memory_ == memory) {
2183 marking_deque_memory_ = NULL;
2184 marking_deque_memory_committed_ = false;
2185 }
2186 delete memory; // Will also unreserve the virtual allocation.
2187 } 2194 }
2188 } 2195 }
2189 V8::FatalProcessOutOfMemory("EnsureMarkingDequeIsCommitted"); 2196 V8::FatalProcessOutOfMemory("EnsureMarkingDequeIsCommitted");
2190 } 2197 }
2191 2198
2192 2199
2193 void MarkCompactCollector::InitializeMarkingDeque() { 2200 void MarkCompactCollector::InitializeMarkingDeque() {
2194 if (marking_deque_memory_committed_) { 2201 DCHECK(!marking_deque_.in_use());
2195 Address addr = static_cast<Address>(marking_deque_memory_->address()); 2202 DCHECK(marking_deque_memory_committed_ > 0);
2196 size_t size = marking_deque_memory_->size(); 2203 Address addr = static_cast<Address>(marking_deque_memory_->address());
2197 if (FLAG_force_marking_deque_overflows) size = 64 * kPointerSize; 2204 size_t size = marking_deque_memory_committed_;
2198 marking_deque_.Initialize(addr, addr + size); 2205 if (FLAG_force_marking_deque_overflows) size = 64 * kPointerSize;
2199 } 2206 marking_deque_.Initialize(addr, addr + size);
2200 } 2207 }
2201 2208
2202 2209
2203 void MarkCompactCollector::UncommitMarkingDeque() { 2210 void MarkingDeque::Initialize(Address low, Address high) {
2204 if (marking_deque_memory_committed_) { 2211 DCHECK(!in_use_);
2205 bool success = marking_deque_memory_->Uncommit( 2212 HeapObject** obj_low = reinterpret_cast<HeapObject**>(low);
2206 reinterpret_cast<Address>(marking_deque_memory_->address()), 2213 HeapObject** obj_high = reinterpret_cast<HeapObject**>(high);
2207 marking_deque_memory_->size()); 2214 array_ = obj_low;
2208 CHECK(success); 2215 mask_ = base::bits::RoundDownToPowerOfTwo32(
2209 marking_deque_memory_committed_ = false; 2216 static_cast<uint32_t>(obj_high - obj_low)) -
2210 } 2217 1;
2218 top_ = bottom_ = 0;
2219 overflowed_ = false;
2220 in_use_ = true;
2211 } 2221 }
2212 2222
2213 2223
2224 void MarkingDeque::Uninitialize(bool aborting) {
2225 if (!aborting) {
2226 DCHECK(IsEmpty());
2227 DCHECK(!overflowed_);
2228 }
2229 DCHECK(in_use_);
2230 top_ = bottom_ = 0xdecbad;
2231 in_use_ = false;
2232 }
2233
2234
2214 void MarkCompactCollector::MarkLiveObjects() { 2235 void MarkCompactCollector::MarkLiveObjects() {
2215 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_MARK); 2236 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_MARK);
2216 double start_time = 0.0; 2237 double start_time = 0.0;
2217 if (FLAG_print_cumulative_gc_stat) { 2238 if (FLAG_print_cumulative_gc_stat) {
2218 start_time = base::OS::TimeCurrentMillis(); 2239 start_time = base::OS::TimeCurrentMillis();
2219 } 2240 }
2220 // The recursive GC marker detects when it is nearing stack overflow, 2241 // The recursive GC marker detects when it is nearing stack overflow,
2221 // and switches to a different marking system. JS interrupts interfere 2242 // and switches to a different marking system. JS interrupts interfere
2222 // with the C stack limit check. 2243 // with the C stack limit check.
2223 PostponeInterruptsScope postpone(isolate()); 2244 PostponeInterruptsScope postpone(isolate());
2224 2245
2225 IncrementalMarking* incremental_marking = heap_->incremental_marking(); 2246 IncrementalMarking* incremental_marking = heap_->incremental_marking();
2226 if (was_marked_incrementally_) { 2247 if (was_marked_incrementally_) {
2227 incremental_marking->Finalize(); 2248 incremental_marking->Finalize();
2228 } else { 2249 } else {
2229 // Abort any pending incremental activities e.g. incremental sweeping. 2250 // Abort any pending incremental activities e.g. incremental sweeping.
2230 incremental_marking->Abort(); 2251 incremental_marking->Abort();
2231 InitializeMarkingDeque(); 2252 if (marking_deque_.in_use()) {
2253 marking_deque_.Uninitialize(true);
2254 }
2232 } 2255 }
2233 2256
2234 #ifdef DEBUG 2257 #ifdef DEBUG
2235 DCHECK(state_ == PREPARE_GC); 2258 DCHECK(state_ == PREPARE_GC);
2236 state_ = MARK_LIVE_OBJECTS; 2259 state_ = MARK_LIVE_OBJECTS;
2237 #endif 2260 #endif
2238 2261
2239 EnsureMarkingDequeIsCommittedAndInitialize(); 2262 EnsureMarkingDequeIsCommittedAndInitialize(
2263 MarkCompactCollector::kMaxMarkingDequeSize);
2240 2264
2241 PrepareForCodeFlushing(); 2265 PrepareForCodeFlushing();
2242 2266
2243 RootMarkingVisitor root_visitor(heap()); 2267 RootMarkingVisitor root_visitor(heap());
2244 MarkRoots(&root_visitor); 2268 MarkRoots(&root_visitor);
2245 2269
2246 ProcessTopOptimizedFrame(&root_visitor); 2270 ProcessTopOptimizedFrame(&root_visitor);
2247 2271
2248 // Retaining dying maps should happen before or during ephemeral marking 2272 // Retaining dying maps should happen before or during ephemeral marking
2249 // because a map could keep the key of an ephemeron alive. Note that map 2273 // because a map could keep the key of an ephemeron alive. Note that map
(...skipping 2413 matching lines...) Expand 10 before | Expand all | Expand 10 after
4663 SlotsBuffer* buffer = *buffer_address; 4687 SlotsBuffer* buffer = *buffer_address;
4664 while (buffer != NULL) { 4688 while (buffer != NULL) {
4665 SlotsBuffer* next_buffer = buffer->next(); 4689 SlotsBuffer* next_buffer = buffer->next();
4666 DeallocateBuffer(buffer); 4690 DeallocateBuffer(buffer);
4667 buffer = next_buffer; 4691 buffer = next_buffer;
4668 } 4692 }
4669 *buffer_address = NULL; 4693 *buffer_address = NULL;
4670 } 4694 }
4671 } // namespace internal 4695 } // namespace internal
4672 } // namespace v8 4696 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap/mark-compact.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698