Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Unified Diff: src/heap.cc

Issue 8519002: Start incremental marking on idle notification. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/heap.cc
diff --git a/src/heap.cc b/src/heap.cc
index 4da83e859e3ddff3f2988c00f066ab63ddf58c04..8e4c833a26cf3610bdee79e272ef54ad8ac2443f 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -143,6 +143,7 @@ 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),
configured_(false),
chunks_queued_for_free_(NULL) {
// Allow build-time customization of the max semispace size. Building
@@ -513,7 +514,8 @@ bool Heap::CollectGarbage(AllocationSpace space, GarbageCollector collector) {
}
ASSERT(collector == SCAVENGER || incremental_marking()->IsStopped());
- if (incremental_marking()->IsStopped()) {
+ if (incremental_marking()->IsStopped() &&
+ !idle_notification_will_schedule_next_gc()) {
Erik Corry 2011/11/10 15:06:55 I think if the heuristics say we need to start a G
ulan 2011/11/11 13:27:26 Removed the flag.
if (incremental_marking()->WorthActivating() && NextGCIsLikelyToBeFull()) {
incremental_marking()->Start();
}
@@ -4461,17 +4463,88 @@ void Heap::EnsureHeapIsIterable() {
bool Heap::IdleNotification() {
Erik Corry 2011/11/10 15:06:55 A comment here to say what the return value means
ulan 2011/11/11 13:27:26 This function is documented in V8 API. Added a com
- static const int kIdlesBeforeScavenge = 4;
- static const int kIdlesBeforeMarkSweep = 7;
- static const int kIdlesBeforeMarkCompact = 8;
- static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1;
- static const unsigned int kGCsBetweenCleanup = 4;
-
if (!last_idle_notification_gc_count_init_) {
last_idle_notification_gc_count_ = gc_count_;
last_idle_notification_gc_count_init_ = true;
+ last_idle_notification_timestamp_ = OS::TimeCurrentMillis();
+ }
+
+ if (!FLAG_incremental_marking) return IdleGlobalGC();
+
+ // The goal is to perform kMaxIdleCount incremental GC cycles and then
+ // wait until the mutator creates more garbage.
Erik Corry 2011/11/10 15:06:55 "Creates more garbage" is rather vague. If this m
ulan 2011/11/11 13:27:26 Rephrased it to "enough garbage to justify a new r
+ // A GC cycle consists of:
+ // 1. many incremental marking steps,
+ // 2. one old space mark-sweep-compact,
+ // 3. many lazy sweep steps.
+ // The counters from IdleGlobalGC are reused, but have different meaning:
Erik Corry 2011/11/10 15:06:55 This seems unnecessarily complicated. Counters ar
ulan 2011/11/11 13:27:26 Done.
+ // - number_idle_notifications_ counts the GC cycles.
Erik Corry 2011/11/10 15:06:55 I do not like the phrase "GC cycles". If we use t
ulan 2011/11/11 13:27:26 Done.
+ // - last_idle_notification_gc_count_ stores the gc_count_ after the last
+ // old space mark-sweep-compact.
+
+ if (number_idle_notifications_ >= kMaxIdleCount &&
+ gc_count_ - last_idle_notification_gc_count_ >= kGCsBetweenCleanup) {
+ // The mutator created more garbage, start new round of GC cycles.
+ number_idle_notifications_ = 0;
}
+ intptr_t step_size = IncrementalMarking::kStepFakeAllocatedBytes;
+
+ double delay = OS::TimeCurrentMillis() - last_idle_notification_timestamp_;
+ last_idle_notification_timestamp_ += delay;
+
+ if (delay > 400) {
+ // Speed up if idle notifications are rare.
Erik Corry 2011/11/10 15:06:55 Time-based things make debugging difficult, and in
ulan 2011/11/11 13:27:26 As discussed offline, added a "hint" argument to I
+ step_size *= 10;
+ }
+
+ if (incremental_marking()->IsStopped()) {
+ if (!old_data_space()->IsSweepingComplete() ||
+ !old_pointer_space()->IsSweepingComplete()) {
Erik Corry 2011/11/10 15:06:55 It is a little dangerous to name individual spaces
ulan 2011/11/11 13:27:26 Done.
+ bool sweeping_complete = old_data_space()->AdvanceSweeper(step_size);
+ sweeping_complete &= old_pointer_space()->AdvanceSweeper(step_size);
+ if (!sweeping_complete) {
+ return false;
+ }
+ }
+ if (!WorthStartingGCWhenIdle()) {
+ return true;
+ }
+ incremental_marking()->Start();
+ }
+
+ // This flag prevents incremental marking from requesting GC via stack guard
+ // and also prevents GC from starting a new incremental marking.
+ idle_notification_will_schedule_next_gc_ = true;
+
+ incremental_marking()->Step(step_size);
Erik Corry 2011/11/10 15:06:55 It seems that we do a step without checking that w
ulan 2011/11/11 13:27:26 Line 4513 starts marking if it is not started alre
+
+ if (incremental_marking()->IsComplete()) {
+ bool uncommit = false;
+ if (last_idle_notification_gc_count_ - gc_count_ < kGCsBetweenCleanup / 2) {
+ // Mutator was idle since the the last GC caused by IdleNotification.
+ isolate_->compilation_cache()->Clear();
Erik Corry 2011/11/10 15:06:55 We seem to be duplicating a lot of the logic of in
ulan 2011/11/11 13:27:26 We do it in LowMemoryNotification and in old versi
+ uncommit = true;
+ }
+ CollectAllGarbage(kNoGCFlags);
+ if (uncommit) {
+ new_space_.Shrink();
+ UncommitFromSpace();
+ }
+ last_idle_notification_gc_count_ = gc_count_;
+ number_idle_notifications_++;
+ }
+
+ idle_notification_will_schedule_next_gc_ = false;
+
+ return !WorthStartingGCWhenIdle() &&
Erik Corry 2011/11/10 15:06:55 If it is worth starting, should we not just start
ulan 2011/11/11 13:27:26 Now I am simply returning false, so the next notif
+ incremental_marking()->IsStopped() &&
+ old_data_space()->IsSweepingComplete() &&
Erik Corry 2011/11/10 15:06:55 Listing the lazily swept pages is fragile.
ulan 2011/11/11 13:27:26 Done.
+ old_pointer_space()->IsSweepingComplete();
+}
+
+
+bool Heap::IdleGlobalGC() {
bool uncommit = true;
bool finished = false;

Powered by Google App Engine
This is Rietveld 408576698