Chromium Code Reviews| Index: src/heap.cc |
| diff --git a/src/heap.cc b/src/heap.cc |
| index 4da83e859e3ddff3f2988c00f066ab63ddf58c04..8d36b87307006ff496f2ee622cb6faf93dde1731 100644 |
| --- a/src/heap.cc |
| +++ b/src/heap.cc |
| @@ -143,6 +143,11 @@ Heap::Heap() |
| number_idle_notifications_(0), |
| last_idle_notification_gc_count_(0), |
| last_idle_notification_gc_count_init_(false), |
| + idle_notification_will_schedule_next_gc_(false), |
| + mark_sweeps_since_idle_round_started_(0), |
| + ms_count_at_last_idle_notification_(0), |
| + gc_count_at_last_idle_gc_(0), |
| + scavenges_since_last_idle_round_(kIdleScavengeThreshold), |
|
ulan
2011/11/23 16:18:06
The initial value allows to start the idle round o
|
| configured_(false), |
| chunks_queued_for_free_(NULL) { |
| // Allow build-time customization of the max semispace size. Building |
| @@ -1010,8 +1015,7 @@ void Heap::Scavenge() { |
| incremental_marking()->PrepareForScavenge(); |
| - old_pointer_space()->AdvanceSweeper(new_space_.Size()); |
| - old_data_space()->AdvanceSweeper(new_space_.Size()); |
| + AdvanceSweepers(new_space_.Size()); |
| // Flip the semispaces. After flipping, to space is empty, from space has |
| // live objects. |
| @@ -1099,6 +1103,8 @@ void Heap::Scavenge() { |
| LOG(isolate_, ResourceEvent("scavenge", "end")); |
| gc_state_ = NOT_IN_GC; |
| + |
| + scavenges_since_last_idle_round_++; |
| } |
| @@ -4460,7 +4466,79 @@ void Heap::EnsureHeapIsIterable() { |
| } |
| -bool Heap::IdleNotification() { |
| +bool Heap::IdleNotification(int hint) { |
| + if (!FLAG_incremental_marking || FLAG_expose_gc) { |
| + return hint < 1000 ? true : IdleGlobalGC(); |
| + } |
| + |
| + // 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, |
| + // 3. many lazy sweep steps. |
| + // Use mark-sweep-compact events to count incremental GCs in a round. |
| + |
| + intptr_t size_factor = Min(Max(hint, 30), 1000) / 10; |
| + // The size factor is in range [3..100]. |
| + intptr_t step_size = size_factor * IncrementalMarking::kAllocatedThreshold; |
| + |
| + if (incremental_marking()->IsStopped()) { |
| + if (!IsSweepingComplete() && !AdvanceSweepers(step_size)) { |
| + return false; |
| + } |
| + } |
| + |
| + if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { |
| + if (EnoughGarbageSinceLastIdleRound()) { |
| + StartIdleRound(); |
| + } else { |
| + return true; |
| + } |
| + } |
| + |
| + int new_mark_sweeps = ms_count_ - ms_count_at_last_idle_notification_; |
| + mark_sweeps_since_idle_round_started_ += new_mark_sweeps; |
| + ms_count_at_last_idle_notification_ = ms_count_; |
| + |
| + if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { |
| + FinishIdleRound(); |
| + return true; |
| + } |
| + |
| + if (incremental_marking()->IsStopped()) { |
| + if (hint < 1000 && !WorthStartingGCWhenIdle()) { |
|
ulan
2011/11/23 16:18:06
If hint >= 1000 then the embedder is asking us to
|
| + FinishIdleRound(); |
| + return true; |
| + } |
| + incremental_marking()->Start(); |
| + } |
| + |
| + // This flag prevents incremental marking from requesting GC via stack guard |
| + idle_notification_will_schedule_next_gc_ = true; |
| + incremental_marking()->Step(step_size); |
| + idle_notification_will_schedule_next_gc_ = false; |
| + |
| + if (incremental_marking()->IsComplete()) { |
| + bool uncommit = false; |
| + if (gc_count_at_last_idle_gc_ == gc_count_) { |
| + // No GC since the last full GC, the mutator is probably not active. |
| + isolate_->compilation_cache()->Clear(); |
| + uncommit = true; |
| + } |
| + CollectAllGarbage(kNoGCFlags); |
| + gc_count_at_last_idle_gc_ = gc_count_; |
| + if (uncommit) { |
| + new_space_.Shrink(); |
| + UncommitFromSpace(); |
| + } |
| + } |
| + return false; |
| +} |
| + |
| + |
| +bool Heap::IdleGlobalGC() { |
| static const int kIdlesBeforeScavenge = 4; |
| static const int kIdlesBeforeMarkSweep = 7; |
| static const int kIdlesBeforeMarkCompact = 8; |