Index: src/heap/incremental-marking.cc |
diff --git a/src/heap/incremental-marking.cc b/src/heap/incremental-marking.cc |
index 47e1e12c77b6fbcd47f362a337edd583ecccaca4..79df882e89241be0ea041cd838dd52d8a7a13e35 100644 |
--- a/src/heap/incremental-marking.cc |
+++ b/src/heap/incremental-marking.cc |
@@ -23,7 +23,6 @@ IncrementalMarking::StepActions IncrementalMarking::IdleStepActions() { |
IncrementalMarking::DO_NOT_FORCE_COMPLETION); |
} |
- |
IncrementalMarking::IncrementalMarking(Heap* heap) |
: heap_(heap), |
observer_(*this, kAllocatedThreshold), |
@@ -42,11 +41,11 @@ IncrementalMarking::IncrementalMarking(Heap* heap) |
no_marking_scope_depth_(0), |
unscanned_bytes_of_large_object_(0), |
was_activated_(false), |
+ black_allocation_(false), |
finalize_marking_completed_(false), |
incremental_marking_finalization_rounds_(0), |
request_type_(COMPLETE_MARKING) {} |
- |
bool IncrementalMarking::BaseRecordWrite(HeapObject* obj, Object* value) { |
HeapObject* value_heap_obj = HeapObject::cast(value); |
MarkBit value_bit = Marking::MarkBitFrom(value_heap_obj); |
@@ -324,6 +323,9 @@ class IncrementalMarkingMarkingVisitor |
} |
}; |
+void IncrementalMarking::IterateBlackCode(Code* code) { |
+ Code::BodyDescriptor::IterateBody<IncrementalMarkingMarkingVisitor>(code); |
+} |
class IncrementalMarkingRootMarkingVisitor : public ObjectVisitor { |
public: |
@@ -598,12 +600,29 @@ void IncrementalMarking::StartMarking() { |
IncrementalMarkingRootMarkingVisitor visitor(this); |
heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); |
+ if (FLAG_black_allocation) { |
+ StartBlackAllocation(); |
+ } |
+ |
// Ready to start incremental marking. |
if (FLAG_trace_incremental_marking) { |
PrintF("[IncrementalMarking] Running\n"); |
} |
} |
+void IncrementalMarking::StartBlackAllocation() { |
+ DCHECK(FLAG_black_allocation); |
+ DCHECK(IsMarking()); |
+ black_allocation_ = true; |
+ PagedSpaces spaces(heap()); |
+ for (PagedSpace* space = spaces.next(); space != NULL; |
+ space = spaces.next()) { |
+ space->EmptyAllocationInfo(); |
+ space->free_list()->Reset(); |
+ } |
+} |
+ |
+void IncrementalMarking::FinishBlackAllocation() { black_allocation_ = false; } |
void IncrementalMarking::MarkRoots() { |
DCHECK(!finalize_marking_completed_); |
@@ -800,6 +819,14 @@ void IncrementalMarking::UpdateMarkingDequeAfterScavenge() { |
MapWord map_word = obj->map_word(); |
if (map_word.IsForwardingAddress()) { |
HeapObject* dest = map_word.ToForwardingAddress(); |
+ if (Page::FromAddress(dest->address())->IsFlagSet(Page::BLACK_PAGE)) |
+ continue; |
+ // If the color of the source object was not transitioned, fix that |
+ // now. |
+ MarkBit mark_bit_dest = Marking::MarkBitFrom(dest); |
+ if (Marking::IsWhite(mark_bit_dest)) { |
+ Marking::WhiteToGrey(mark_bit_dest); |
+ } |
array[new_top] = dest; |
new_top = ((new_top + 1) & mask); |
DCHECK(new_top != marking_deque->bottom()); |
@@ -894,7 +921,12 @@ void IncrementalMarking::ProcessMarkingDeque() { |
void IncrementalMarking::Hurry() { |
- if (state() == MARKING) { |
+ // A scavenge may have pushed new objects on the marking deque (due to black |
+ // allocation) even in COMPLETE state. This may happen if scavenges are |
+ // forced e.g. in tests. It should not happen when COMPLETE was set when |
+ // incremental marking finished and a regular GC was triggered after that |
+ // because should_hurry_ will force a full GC. |
+ if (!heap_->mark_compact_collector()->marking_deque()->IsEmpty()) { |
double start = 0.0; |
if (FLAG_trace_incremental_marking || FLAG_print_cumulative_gc_stat) { |
start = heap_->MonotonicallyIncreasingTimeInMs(); |
@@ -959,6 +991,7 @@ void IncrementalMarking::Stop() { |
heap_->isolate()->stack_guard()->ClearGC(); |
state_ = STOPPED; |
is_compacting_ = false; |
+ black_allocation_ = false; |
} |