Reviewers: Vyacheslav Egorov,
Message:
Please take a look, it is to be committed after the push to trunk.
Description:
Start incremental marking on idle notification.
Once marking is finished, perform global GC in the same way
IdleNotification
did before.
BUG=v8:1458
TEST=cctest/test-heap/IdleNotificationAdvancesIncrementalMarking
Please review this at http://codereview.chromium.org/8084002/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/heap.h
M src/heap.cc
M src/incremental-marking.h
M test/cctest/test-heap.cc
Index: src/heap.cc
diff --git a/src/heap.cc b/src/heap.cc
index
522861deda05e2a163861ac527be202631387441..945587f92fb4e63b301d846c4f2e648796c08ca7
100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -140,6 +140,7 @@ Heap::Heap()
store_buffer_(this),
marking_(this),
incremental_marking_(this),
+ idle_work_(IDLE_INCREMENTAL_MARKING),
number_idle_notifications_(0),
last_idle_notification_gc_count_(0),
last_idle_notification_gc_count_init_(false),
@@ -4515,6 +4516,36 @@ void Heap::EnsureHeapIsIterable() {
bool Heap::IdleNotification() {
+ switch (idle_work_) {
+ case IDLE_INCREMENTAL_MARKING:
+ if (IdleIncrementalMarking()) {
+ idle_work_ = IDLE_GLOBAL_GC;
+ }
+ break;
+ case IDLE_GLOBAL_GC:
+ if (IdleGlobalGC()) {
+ idle_work_ = IDLE_INCREMENTAL_MARKING;
+ return true;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ return false;
+}
+
+bool Heap::IdleIncrementalMarking() {
+ if (incremental_marking()->IsStopped()) {
+ if (!incremental_marking()->WorthActivating()) {
+ return true;
+ }
+ incremental_marking()->Start();
+ }
+ incremental_marking()->Step(IncrementalMarking::kStepFakeAllocatedBytes);
+ return incremental_marking()->IsComplete();
+}
+
+bool Heap::IdleGlobalGC() {
static const int kIdlesBeforeScavenge = 4;
static const int kIdlesBeforeMarkSweep = 7;
static const int kIdlesBeforeMarkCompact = 8;
Index: src/heap.h
diff --git a/src/heap.h b/src/heap.h
index
4a1e01dcaa3135aa4ebd452259c847f60a9e70ab..e042957f31f76c2029db3c80cca73abebbdaa653
100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -1757,6 +1757,12 @@ class Heap {
void SelectScavengingVisitorsTable();
+ // Returns true if incremental marking is finished.
+ bool IdleIncrementalMarking();
+
+ // Returns true if no more GC work is left.
+ bool IdleGlobalGC();
+
static const int kInitialSymbolTableSize = 2048;
static const int kInitialEvalCacheSize = 64;
@@ -1782,6 +1788,13 @@ class Heap {
IncrementalMarking incremental_marking_;
+ enum IdleWork {
+ IDLE_INCREMENTAL_MARKING,
+ IDLE_GLOBAL_GC
+ };
+
+ IdleWork idle_work_;
+
int number_idle_notifications_;
unsigned int last_idle_notification_gc_count_;
bool last_idle_notification_gc_count_init_;
Index: src/incremental-marking.h
diff --git a/src/incremental-marking.h b/src/incremental-marking.h
index
30dbbc1605c7c5415767101469cc1f55c2d504ef..94500978b0b00882127a2734befc5ce79fadd19c
100644
--- a/src/incremental-marking.h
+++ b/src/incremental-marking.h
@@ -63,6 +63,8 @@ class IncrementalMarking {
inline bool IsMarkingIncomplete() { return state() == MARKING; }
+ inline bool IsComplete() { return state() == COMPLETE; }
+
bool WorthActivating();
void Start();
@@ -97,6 +99,9 @@ class IncrementalMarking {
// This is how much we increase the marking/allocating factor by.
static const intptr_t kAllocationMarkingFactorSpeedup = 2;
static const intptr_t kMaxAllocationMarkingFactor = 1000000000;
+ // This is given to Step() function when it is called without any
allocation.
+ static const intptr_t kStepFakeAllocatedBytes = kAllocatedThreshold * 3;
+
void OldSpaceStep(intptr_t allocated) {
Step(allocated * kFastMarking / kInitialAllocationMarkingFactor);
Index: test/cctest/test-heap.cc
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index
40482be7edbd755cc06430d60b8816f448ad2cb2..058559c8ad4d727e6a77f7b69b51b5e224a121af
100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -1272,3 +1272,34 @@ TEST(GrowAndShrinkNewSpace) {
new_capacity = new_space->Capacity();
CHECK(old_capacity == new_capacity);
}
+
+TEST(IdleNotificationAdvancesIncrementalMarking) {
+ if (!FLAG_incremental_marking || !FLAG_incremental_marking_steps) return;
+ InitializeVM();
+ v8::HandleScope scope;
+ const char* source = "function binom(n, m) {"
+ " var C = [[1]];"
+ " for (var i = 1; i <= n; ++i) {"
+ " C[i] = [1];"
+ " for (var j = 1; j < i; ++j) {"
+ " C[i][j] = C[i-1][j-1] + C[i-1][j];"
+ " }"
+ " C[i][i] = 1;"
+ " }"
+ " return C[n][m];"
+ "};"
+ "binom(1000, 500)";
+ {
+ AlwaysAllocateScope aa_scope;
+ CompileRun(source);
+ }
+ intptr_t old_size = HEAP->SizeOfObjects();
+ int old_steps = HEAP->incremental_marking()->steps_count();
+ HEAP->IdleNotification();
+ int new_steps = HEAP->incremental_marking()->steps_count();
+ CHECK(new_steps > old_steps);
+ while (!HEAP->IdleNotification());
+ intptr_t new_size = HEAP->SizeOfObjects();
+ CHECK(new_size < old_size);
+}
+
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev