Index: src/heap/heap.cc |
diff --git a/src/heap/heap.cc b/src/heap/heap.cc |
index 1c966b350d2aee49a480e56c4f1c53b8619f25bf..ab05f427df7a94b6f16c21cb2930cc3f58731022 100644 |
--- a/src/heap/heap.cc |
+++ b/src/heap/heap.cc |
@@ -120,12 +120,7 @@ Heap::Heap() |
store_buffer_(this), |
marking_(this), |
incremental_marking_(this), |
- number_idle_notifications_(0), |
- last_idle_notification_gc_count_(0), |
- last_idle_notification_gc_count_init_(false), |
- mark_sweeps_since_idle_round_started_(0), |
gc_count_at_last_idle_gc_(0), |
- scavenges_since_last_idle_round_(kIdleScavengeThreshold), |
full_codegen_bytes_generated_(0), |
crankshaft_codegen_bytes_generated_(0), |
gcs_since_last_deopt_(0), |
@@ -1559,7 +1554,7 @@ void Heap::Scavenge() { |
gc_state_ = NOT_IN_GC; |
- scavenges_since_last_idle_round_++; |
+ gc_idle_time_handler_.NotifyScavenge(); |
} |
@@ -4264,12 +4259,7 @@ void Heap::MakeHeapIterable() { |
} |
-void Heap::AdvanceIdleIncrementalMarking(int idle_time_in_ms) { |
- intptr_t step_size = |
- static_cast<size_t>(GCIdleTimeHandler::EstimateMarkingStepSize( |
- idle_time_in_ms, |
- tracer_.IncrementalMarkingSpeedInBytesPerMillisecond())); |
- |
+void Heap::AdvanceIdleIncrementalMarking(intptr_t step_size) { |
incremental_marking()->Step(step_size, |
IncrementalMarking::NO_GC_VIA_STACK_GUARD, true); |
@@ -4282,7 +4272,7 @@ void Heap::AdvanceIdleIncrementalMarking(int idle_time_in_ms) { |
} |
CollectAllGarbage(kReduceMemoryFootprintMask, |
"idle notification: finalize incremental"); |
- mark_sweeps_since_idle_round_started_++; |
+ gc_idle_time_handler_.NotifyIdleMarkCompact(); |
gc_count_at_last_idle_gc_ = gc_count_; |
if (uncommit) { |
new_space_.Shrink(); |
@@ -4295,83 +4285,49 @@ void Heap::AdvanceIdleIncrementalMarking(int idle_time_in_ms) { |
bool Heap::IdleNotification(int idle_time_in_ms) { |
// If incremental marking is off, we do not perform idle notification. |
if (!FLAG_incremental_marking) return true; |
- |
- // Minimal hint that allows to do full GC. |
- const int kMinHintForFullGC = 100; |
isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample( |
idle_time_in_ms); |
HistogramTimerScope idle_notification_scope( |
isolate_->counters()->gc_idle_notification()); |
- if (contexts_disposed_ > 0) { |
- contexts_disposed_ = 0; |
- int mark_sweep_time = Min(TimeMarkSweepWouldTakeInMs(), 1000); |
- if (idle_time_in_ms >= mark_sweep_time && !FLAG_expose_gc && |
- incremental_marking()->IsStopped()) { |
+ GCIdleTimeAction action = gc_idle_time_handler_.Compute( |
+ idle_time_in_ms, contexts_disposed_, static_cast<size_t>(SizeOfObjects()), |
+ incremental_marking()->IsStopped(), tracer()); |
+ contexts_disposed_ = 0; |
+ bool result = false; |
+ switch (action.type) { |
+ case DO_INCREMENTAL_MARKING: |
+ if (incremental_marking()->IsStopped()) { |
+ incremental_marking()->Start(); |
+ } |
+ AdvanceIdleIncrementalMarking(action.parameter); |
+ break; |
+ case DO_FULL_GC: { |
HistogramTimerScope scope(isolate_->counters()->gc_context()); |
- CollectAllGarbage(kReduceMemoryFootprintMask, |
- "idle notification: contexts disposed"); |
- } else { |
- AdvanceIdleIncrementalMarking(idle_time_in_ms); |
- } |
- |
- // After context disposal there is likely a lot of garbage remaining, reset |
- // the idle notification counters in order to trigger more incremental GCs |
- // on subsequent idle notifications. |
- StartIdleRound(); |
- return false; |
- } |
- |
- // By doing small chunks of GC work in each IdleNotification, |
- // perform a round of incremental GCs and after that wait until |
- // the mutator creates enough garbage to justify a new round. |
- // An incremental GC progresses as follows: |
- // 1. many incremental marking steps, |
- // 2. one old space mark-sweep-compact, |
- // Use mark-sweep-compact events to count incremental GCs in a round. |
- |
- if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { |
- if (EnoughGarbageSinceLastIdleRound()) { |
- StartIdleRound(); |
- } else { |
- return true; |
- } |
- } |
- |
- int remaining_mark_sweeps = |
- kMaxMarkSweepsInIdleRound - mark_sweeps_since_idle_round_started_; |
- |
- if (incremental_marking()->IsStopped()) { |
- // If there are no more than two GCs left in this idle round and we are |
- // allowed to do a full GC, then make those GCs full in order to compact |
- // the code space. |
- // TODO(ulan): Once we enable code compaction for incremental marking, |
- // we can get rid of this special case and always start incremental marking. |
- if (remaining_mark_sweeps <= 2 && idle_time_in_ms >= kMinHintForFullGC) { |
- CollectAllGarbage(kReduceMemoryFootprintMask, |
- "idle notification: finalize idle round"); |
- mark_sweeps_since_idle_round_started_++; |
- } else { |
- incremental_marking()->Start(); |
+ const char* message = contexts_disposed_ |
+ ? "idle notification: contexts disposed" |
+ : "idle notification: finalize idle round"; |
+ CollectAllGarbage(kReduceMemoryFootprintMask, message); |
+ gc_idle_time_handler_.NotifyIdleMarkCompact(); |
+ break; |
} |
+ case DO_SCAVENGE: |
+ CollectGarbage(NEW_SPACE, "idle notification: scavenge"); |
+ break; |
+ case DO_NOTHING: |
+ result = true; |
+ break; |
} |
- if (!incremental_marking()->IsStopped()) { |
- AdvanceIdleIncrementalMarking(idle_time_in_ms); |
- } |
- |
- if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { |
- FinishIdleRound(); |
- return true; |
- } |
- |
// If the IdleNotifcation is called with a large hint we will wait for |
// the sweepter threads here. |
+ // TODO(ulan): move this in GCIdleTimeHandler. |
+ const int kMinHintForFullGC = 100; |
if (idle_time_in_ms >= kMinHintForFullGC && |
mark_compact_collector()->sweeping_in_progress()) { |
mark_compact_collector()->EnsureSweepingCompleted(); |
} |
- return false; |
+ return result; |
} |