Index: src/heap/memory-reducer.h |
diff --git a/src/heap/memory-reducer.h b/src/heap/memory-reducer.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a9ba2980ad8e164a788bfb06e735b3a283dc74af |
--- /dev/null |
+++ b/src/heap/memory-reducer.h |
@@ -0,0 +1,135 @@ |
+// Copyright 2015 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. |
+ |
+#ifndef V8_HEAP_memory_reducer_H |
+#define V8_HEAP_memory_reducer_H |
+ |
+#include "include/v8-platform.h" |
+#include "src/base/macros.h" |
+ |
+namespace v8 { |
+namespace internal { |
+ |
+class Heap; |
+ |
+ |
+// The goal of the MemoryReducer class is to detect transition of the mutator |
+// from high allocation phase to low allocation phase and to collect potential |
+// garbage created in the high allocation phase. |
+// |
+// The class implements an automaton with the following states and transitions. |
+// |
+// States: |
+// - DONE |
+// - WAIT <started_gcs> <next_gc_start_ms> |
+// - RUN <started_gcs> |
+// The <started_gcs> is an integer in range from 0..kMaxNumberOfGCs that stores |
+// the number of GCs initiated by the MemoryReducer since it left the DONE |
+// state. |
+// The <next_gc_start_ms> is a double that stores the earliest time the next GC |
+// can be initiated by the MemoryReducer. |
+// The DONE state means that the MemoryReducer is not active. |
+// The WAIT state means that the MemoryReducer is waiting for mutator allocation |
+// rate to drop. The check for the allocation rate happens in the timer task |
+// callback. |
+// The RUN state means that the MemoryReducer started incremental marking and is |
+// waiting for it to finish. Incremental marking steps are performed as usual |
+// in the idle notification and in the mutator. |
+// |
+// Transitions: |
+// DONE -> WAIT 0 (now_ms + long_delay_ms) happens: |
+// - on context disposal, |
+// - at the end of mark-compact GC initiated by the mutator. |
+// This signals that there is potential garbage to be collected. |
+// |
+// WAIT n x -> WAIT n (now_ms + long_delay_ms) happens: |
+// - on mark-compact GC initiated by the mutator, |
+// - in the timer callback if the mutator allocation rate is high or |
+// incremental GC is in progress. |
+// |
+// WAIT n x -> RUN (n+1) happens: |
+// - in the timer callback if the mutator allocation rate is low |
+// and now_ms >= x and there is no incremental GC in progress. |
+// The MemoryReducer starts incremental marking on this transition. |
+// |
+// RUN n -> DONE happens: |
+// - at end of the incremental GC initiated by the MemoryReducer if |
+// (n > 1 and there is no more garbage to be collected) or |
+// n == kMaxNumberOfGCs. |
+// RUN n -> WAIT n (now_ms + short_delay_ms) happens: |
+// - at end of the incremental GC initiated by the MemoryReducer if |
+// (n == 1 or there is more garbage to be collected) and |
+// n < kMaxNumberOfGCs. |
+// |
+// now_ms is the current time, long_delay_ms and short_delay_ms are constants. |
+class MemoryReducer { |
+ public: |
+ enum Action { kDone, kWait, kRun }; |
+ |
+ struct State { |
+ State(Action action, int started_gcs, double next_gc_start_ms) |
+ : action(action), |
+ started_gcs(started_gcs), |
+ next_gc_start_ms(next_gc_start_ms) {} |
+ Action action; |
+ int started_gcs; |
+ double next_gc_start_ms; |
+ }; |
+ |
+ enum EventType { |
+ kTimer, |
+ kMarkCompact, |
+ kContextDisposed, |
+ }; |
+ |
+ struct Event { |
+ EventType type; |
+ double time_ms; |
+ bool low_allocation_rate; |
+ bool next_gc_likely_to_collect_more; |
+ bool can_start_incremental_gc; |
+ }; |
+ |
+ explicit MemoryReducer(Heap* heap) : heap_(heap), state_(kDone, 0, 0.0) {} |
+ // Callbacks. |
+ void NotifyTimer(const Event& event); |
+ void NotifyMarkCompact(const Event& event); |
+ void NotifyScavenge(const Event& event); |
+ void NotifyContextDisposed(const Event& event); |
+ // The step function that computes the next state from the current state and |
+ // the incoming event. |
+ static State Step(const State& state, const Event& event); |
+ // Posts a timer task that will call NotifyTimer after the given delay. |
+ void ScheduleTimer(double delay_ms); |
+ |
+ static const int kLongDelayMs; |
+ static const int kShortDelayMs; |
+ static const int kMaxNumberOfGCs; |
+ |
+ Heap* heap() { return heap_; } |
+ |
+ private: |
+ class TimerTask : public v8::Task { |
+ public: |
+ explicit TimerTask(MemoryReducer* memory_reducer) |
+ : memory_reducer_(memory_reducer) {} |
+ virtual ~TimerTask() {} |
+ |
+ private: |
+ // v8::Task overrides. |
+ void Run() override; |
+ MemoryReducer* memory_reducer_; |
+ DISALLOW_COPY_AND_ASSIGN(TimerTask); |
+ }; |
+ |
+ Heap* heap_; |
+ State state_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MemoryReducer); |
+}; |
+ |
+} // namespace internal |
+} // namespace v8 |
+ |
+#endif // V8_HEAP_memory_reducer_H |