Index: src/heap/incremental-marking.cc |
diff --git a/src/heap/incremental-marking.cc b/src/heap/incremental-marking.cc |
index a7ac6b2be75fbbda6880ec9251aa0a443d718fe4..e4230d159672de92cb642fc3f21401b0de6cd215 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,12 @@ class IncrementalMarkingMarkingVisitor |
} |
}; |
+void IncrementalMarking::IterateBlackObject(HeapObject* object) { |
+ if (black_allocation() && |
+ Page::FromAddress(object->address())->IsFlagSet(Page::BLACK_PAGE)) { |
+ IncrementalMarkingMarkingVisitor::IterateBody(object->map(), object); |
+ } |
+} |
class IncrementalMarkingRootMarkingVisitor : public ObjectVisitor { |
public: |
@@ -597,12 +602,43 @@ 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() { |
+ if (heap_->isolate()->serializer_enabled()) { |
+ if (FLAG_trace_incremental_marking) { |
+ PrintF("[IncrementalMarking] Black allocation delayed - serializer\n"); |
+ } |
+ return; |
+ } |
+ 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(); |
+ } |
+ if (FLAG_trace_incremental_marking) { |
+ PrintF("[IncrementalMarking] Black allocation started\n"); |
+ } |
+} |
+ |
+void IncrementalMarking::FinishBlackAllocation() { |
+ black_allocation_ = false; |
+ if (FLAG_trace_incremental_marking) { |
+ PrintF("[IncrementalMarking] Black allocation finished\n"); |
+ } |
+} |
void IncrementalMarking::MarkRoots() { |
DCHECK(!finalize_marking_completed_); |
@@ -805,6 +841,8 @@ void IncrementalMarking::UpdateMarkingDequeAfterScavenge() { |
// them. |
if (map_word.IsForwardingAddress()) { |
HeapObject* dest = map_word.ToForwardingAddress(); |
+ if (Page::FromAddress(dest->address())->IsFlagSet(Page::BLACK_PAGE)) |
+ continue; |
array[new_top] = dest; |
new_top = ((new_top + 1) & mask); |
DCHECK(new_top != marking_deque->bottom()); |
@@ -899,7 +937,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(); |
@@ -964,6 +1007,7 @@ void IncrementalMarking::Stop() { |
heap_->isolate()->stack_guard()->ClearGC(); |
state_ = STOPPED; |
is_compacting_ = false; |
+ FinishBlackAllocation(); |
} |
@@ -1182,6 +1226,11 @@ intptr_t IncrementalMarking::Step(intptr_t allocated_bytes, |
StartMarking(); |
} |
} else if (state_ == MARKING) { |
+ if (FLAG_black_allocation && !black_allocation()) { |
+ // If black allocation was not started when incremental marking started |
+ // start it now. |
+ StartBlackAllocation(); |
+ } |
bytes_processed = ProcessMarkingDeque(bytes_to_process); |
if (heap_->mark_compact_collector()->marking_deque()->IsEmpty()) { |
if (completion == FORCE_COMPLETION || |