| 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; | 
| } | 
|  | 
|  | 
|  |