Index: test/unittests/heap/cleanup-gc-unittest.cc |
diff --git a/test/unittests/heap/cleanup-gc-unittest.cc b/test/unittests/heap/cleanup-gc-unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9c046d774da99d077b89dcaa2f3166f2c3fd1fba |
--- /dev/null |
+++ b/test/unittests/heap/cleanup-gc-unittest.cc |
@@ -0,0 +1,287 @@ |
+// Copyright 2014 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <limits> |
+ |
+#include "src/flags.h" |
+#include "src/heap/cleanup-gc.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace v8 { |
+namespace internal { |
+ |
+CleanupGC::State DoneState() { |
+ return CleanupGC::State(CleanupGC::kDone, 0, 0.0); |
+} |
+ |
+ |
+CleanupGC::State WaitState(int started_gcs, double next_gc_start_ms) { |
+ return CleanupGC::State(CleanupGC::kWait, started_gcs, next_gc_start_ms); |
+} |
+ |
+ |
+CleanupGC::State RunState(int started_gcs, double next_gc_start_ms) { |
+ return CleanupGC::State(CleanupGC::kRun, started_gcs, next_gc_start_ms); |
+} |
+ |
+ |
+CleanupGC::Event MarkCompactEvent(double time_ms, |
+ bool next_gc_likely_to_collect_more) { |
+ CleanupGC::Event event; |
+ event.type = CleanupGC::kMarkCompact; |
+ event.time_ms = time_ms; |
+ event.next_gc_likely_to_collect_more = next_gc_likely_to_collect_more; |
+ return event; |
+} |
+ |
+ |
+CleanupGC::Event MarkCompactEventGarbageLeft(double time_ms) { |
+ return MarkCompactEvent(time_ms, true); |
+} |
+ |
+ |
+CleanupGC::Event MarkCompactEventNoGarbageLeft(double time_ms) { |
+ return MarkCompactEvent(time_ms, false); |
+} |
+ |
+ |
+CleanupGC::Event TimerEvent(double time_ms, bool low_allocation_rate, |
+ bool high_fragmentation, |
+ bool incremental_gc_in_progress) { |
+ CleanupGC::Event event; |
+ event.type = CleanupGC::kTimer; |
+ event.time_ms = time_ms; |
+ event.low_allocation_rate = low_allocation_rate; |
+ event.high_fragmentation = high_fragmentation; |
+ event.incremental_gc_in_progress = incremental_gc_in_progress; |
+ return event; |
+} |
+ |
+ |
+CleanupGC::Event TimerEventLowAllocationRate(double time_ms) { |
+ return TimerEvent(time_ms, true, false, false); |
+} |
+ |
+ |
+CleanupGC::Event TimerEventHighFragmentation(double time_ms) { |
+ return TimerEvent(time_ms, false, true, false); |
+} |
+ |
+ |
+CleanupGC::Event TimerEventHighAllocationRateAndLowFragmentation( |
+ double time_ms) { |
+ return TimerEvent(time_ms, false, false, false); |
+} |
+ |
+ |
+CleanupGC::Event TimerEventPendingGC(double time_ms) { |
+ return TimerEvent(time_ms, true, true, true); |
+} |
+ |
+ |
+CleanupGC::Event ScavengeEvent(double time_ms) { |
+ CleanupGC::Event event; |
+ event.type = CleanupGC::kScavenge; |
+ event.time_ms = time_ms; |
+ return event; |
+} |
+ |
+ |
+CleanupGC::Event ContextDisposedEvent(double time_ms) { |
+ CleanupGC::Event event; |
+ event.type = CleanupGC::kContextDisposed; |
+ event.time_ms = time_ms; |
+ return event; |
+} |
+ |
+ |
+TEST(CleanupGC, FromDoneToDone) { |
+ CleanupGC::State state0(DoneState()), state1(DoneState()); |
+ |
+ state1 = CleanupGC::Step(state0, TimerEventLowAllocationRate(0)); |
+ EXPECT_EQ(CleanupGC::kDone, state1.action); |
+ |
+ state1 = CleanupGC::Step(state0, TimerEventHighFragmentation(0)); |
+ EXPECT_EQ(CleanupGC::kDone, state1.action); |
+ |
+ state1 = CleanupGC::Step(state0, |
+ TimerEventHighAllocationRateAndLowFragmentation(0)); |
+ EXPECT_EQ(CleanupGC::kDone, state1.action); |
+ |
+ state1 = CleanupGC::Step(state0, TimerEventPendingGC(0)); |
+ EXPECT_EQ(CleanupGC::kDone, state1.action); |
+ |
+ state1 = CleanupGC::Step(state0, ScavengeEvent(0)); |
+ EXPECT_EQ(CleanupGC::kDone, state1.action); |
+} |
+ |
+ |
+TEST(CleanupGC, FromDoneToWait) { |
+ if (!FLAG_incremental_marking) return; |
+ |
+ CleanupGC::State state0(DoneState()), state1(DoneState()); |
+ |
+ state1 = CleanupGC::Step(state0, MarkCompactEventGarbageLeft(0)); |
+ EXPECT_EQ(CleanupGC::kWait, state1.action); |
+ EXPECT_EQ(CleanupGC::kLongDelayMs, state1.next_gc_start_ms); |
+ EXPECT_EQ(0, state1.started_gcs); |
+ |
+ state1 = CleanupGC::Step(state0, MarkCompactEventNoGarbageLeft(0)); |
+ EXPECT_EQ(CleanupGC::kWait, state1.action); |
+ EXPECT_EQ(CleanupGC::kLongDelayMs, state1.next_gc_start_ms); |
+ EXPECT_EQ(0, state1.started_gcs); |
+ |
+ state1 = CleanupGC::Step(state0, ContextDisposedEvent(0)); |
+ EXPECT_EQ(CleanupGC::kWait, state1.action); |
+ EXPECT_EQ(CleanupGC::kLongDelayMs, state1.next_gc_start_ms); |
+ EXPECT_EQ(0, state1.started_gcs); |
+} |
+ |
+ |
+TEST(CleanupGC, FromWaitToWait) { |
+ if (!FLAG_incremental_marking) return; |
+ |
+ CleanupGC::State state0(WaitState(2, 1000.0)), state1(DoneState()); |
+ |
+ state1 = CleanupGC::Step(state0, ContextDisposedEvent(2000)); |
+ EXPECT_EQ(CleanupGC::kWait, state1.action); |
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+ |
+ state1 = CleanupGC::Step( |
+ state0, TimerEventLowAllocationRate(state0.next_gc_start_ms - 1)); |
+ EXPECT_EQ(CleanupGC::kWait, state1.action); |
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+ |
+ state1 = CleanupGC::Step( |
+ state0, TimerEventHighFragmentation(state0.next_gc_start_ms - 1)); |
+ EXPECT_EQ(CleanupGC::kWait, state1.action); |
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+ |
+ state1 = CleanupGC::Step( |
+ state0, TimerEventHighAllocationRateAndLowFragmentation(2000)); |
+ EXPECT_EQ(CleanupGC::kWait, state1.action); |
+ EXPECT_EQ(2000 + CleanupGC::kLongDelayMs, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+ |
+ state1 = CleanupGC::Step(state0, TimerEventPendingGC(2000)); |
+ EXPECT_EQ(CleanupGC::kWait, state1.action); |
+ EXPECT_EQ(2000 + CleanupGC::kLongDelayMs, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+ |
+ state1 = CleanupGC::Step(state0, ScavengeEvent(2000)); |
+ EXPECT_EQ(CleanupGC::kWait, state1.action); |
+ EXPECT_EQ(2000 + CleanupGC::kLongDelayMs, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+ |
+ state1 = CleanupGC::Step(state0, MarkCompactEventGarbageLeft(2000)); |
+ EXPECT_EQ(CleanupGC::kWait, state1.action); |
+ EXPECT_EQ(2000 + CleanupGC::kLongDelayMs, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+ |
+ state1 = CleanupGC::Step(state0, MarkCompactEventNoGarbageLeft(2000)); |
+ EXPECT_EQ(CleanupGC::kWait, state1.action); |
+ EXPECT_EQ(2000 + CleanupGC::kLongDelayMs, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+} |
+ |
+ |
+TEST(CleanupGC, FromWaitToRun) { |
+ if (!FLAG_incremental_marking) return; |
+ |
+ CleanupGC::State state0(WaitState(0, 1000.0)), state1(DoneState()); |
+ |
+ state1 = CleanupGC::Step( |
+ state0, TimerEventLowAllocationRate(state0.next_gc_start_ms + 1)); |
+ EXPECT_EQ(CleanupGC::kRun, state1.action); |
+ EXPECT_EQ(0, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs + 1, state1.started_gcs); |
+ |
+ state1 = CleanupGC::Step( |
+ state0, TimerEventHighFragmentation(state0.next_gc_start_ms + 1)); |
+ EXPECT_EQ(CleanupGC::kRun, state1.action); |
+ EXPECT_EQ(0, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs + 1, state1.started_gcs); |
+} |
+ |
+ |
+TEST(CleanupGC, FromRunToRun) { |
+ if (!FLAG_incremental_marking) return; |
+ |
+ CleanupGC::State state0(RunState(1, 0.0)), state1(DoneState()); |
+ |
+ state1 = CleanupGC::Step(state0, TimerEventLowAllocationRate(2000)); |
+ EXPECT_EQ(CleanupGC::kRun, state1.action); |
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+ |
+ state1 = CleanupGC::Step(state0, TimerEventHighFragmentation(2000)); |
+ EXPECT_EQ(CleanupGC::kRun, state1.action); |
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+ |
+ state1 = CleanupGC::Step( |
+ state0, TimerEventHighAllocationRateAndLowFragmentation(2000)); |
+ EXPECT_EQ(CleanupGC::kRun, state1.action); |
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+ |
+ state1 = CleanupGC::Step(state0, TimerEventPendingGC(2000)); |
+ EXPECT_EQ(CleanupGC::kRun, state1.action); |
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+ |
+ state1 = CleanupGC::Step(state0, ScavengeEvent(2000)); |
+ EXPECT_EQ(CleanupGC::kRun, state1.action); |
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+ |
+ state1 = CleanupGC::Step(state0, ContextDisposedEvent(2000)); |
+ EXPECT_EQ(CleanupGC::kRun, state1.action); |
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+} |
+ |
+ |
+TEST(CleanupGC, FromRunToDone) { |
+ if (!FLAG_incremental_marking) return; |
+ |
+ CleanupGC::State state0(RunState(2, 0.0)), state1(DoneState()); |
+ |
+ state1 = CleanupGC::Step(state0, MarkCompactEventNoGarbageLeft(2000)); |
+ EXPECT_EQ(CleanupGC::kDone, state1.action); |
+ EXPECT_EQ(0, state1.next_gc_start_ms); |
+ EXPECT_EQ(0, state1.started_gcs); |
+ |
+ state0.started_gcs = CleanupGC::kMaxNumberOfGCs; |
+ |
+ state1 = CleanupGC::Step(state0, MarkCompactEventGarbageLeft(2000)); |
+ EXPECT_EQ(CleanupGC::kDone, state1.action); |
+ EXPECT_EQ(0, state1.next_gc_start_ms); |
+ EXPECT_EQ(0, state1.started_gcs); |
+} |
+ |
+ |
+TEST(CleanupGC, FromRunToWait) { |
+ if (!FLAG_incremental_marking) return; |
+ |
+ CleanupGC::State state0(RunState(2, 0.0)), state1(DoneState()); |
+ |
+ state1 = CleanupGC::Step(state0, MarkCompactEventGarbageLeft(2000)); |
+ EXPECT_EQ(CleanupGC::kWait, state1.action); |
+ EXPECT_EQ(2000 + CleanupGC::kShortDelayMs, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+ |
+ state0.started_gcs = 1; |
+ |
+ state1 = CleanupGC::Step(state0, MarkCompactEventNoGarbageLeft(2000)); |
+ EXPECT_EQ(CleanupGC::kWait, state1.action); |
+ EXPECT_EQ(2000 + CleanupGC::kShortDelayMs, state1.next_gc_start_ms); |
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
+} |
+ |
+} // namespace internal |
+} // namespace v8 |