Index: src/heap/gc-idle-time-handler.cc |
diff --git a/src/heap/gc-idle-time-handler.cc b/src/heap/gc-idle-time-handler.cc |
index 5ff4017c233f071b742974b9fcf242609de03de3..a2e08b28c514e1c08c0c394a9100c8da6150897d 100644 |
--- a/src/heap/gc-idle-time-handler.cc |
+++ b/src/heap/gc-idle-time-handler.cc |
@@ -3,12 +3,14 @@ |
// found in the LICENSE file. |
#include "src/heap/gc-idle-time-handler.h" |
+#include "src/heap/gc-tracer.h" |
+#include "src/utils.h" |
namespace v8 { |
namespace internal { |
- |
const double GCIdleTimeHandler::kConservativeTimeRatio = 0.9; |
+const size_t GCIdleTimeHandler::kMaxMarkCompactTimeInMs = 1000000; |
size_t GCIdleTimeHandler::EstimateMarkingStepSize( |
@@ -16,14 +18,13 @@ size_t GCIdleTimeHandler::EstimateMarkingStepSize( |
DCHECK(idle_time_in_ms > 0); |
if (marking_speed_in_bytes_per_ms == 0) { |
- marking_speed_in_bytes_per_ms = |
- GCIdleTimeHandler::kInitialConservativeMarkingSpeed; |
+ marking_speed_in_bytes_per_ms = kInitialConservativeMarkingSpeed; |
} |
size_t marking_step_size = marking_speed_in_bytes_per_ms * idle_time_in_ms; |
if (marking_step_size / marking_speed_in_bytes_per_ms != idle_time_in_ms) { |
// In the case of an overflow we return maximum marking step size. |
- return GCIdleTimeHandler::kMaximumMarkingStepSize; |
+ return kMaximumMarkingStepSize; |
} |
if (marking_step_size > kMaximumMarkingStepSize) |
@@ -32,5 +33,51 @@ size_t GCIdleTimeHandler::EstimateMarkingStepSize( |
return static_cast<size_t>(marking_step_size * |
GCIdleTimeHandler::kConservativeTimeRatio); |
} |
+ |
+ |
+size_t GCIdleTimeHandler::EstimateMarkCompactTime( |
+ size_t size_of_objects, size_t mark_compact_speed_in_bytes_per_ms) { |
+ if (mark_compact_speed_in_bytes_per_ms == 0) { |
+ mark_compact_speed_in_bytes_per_ms = kInitialConservativeMarkCompactSpeed; |
+ } |
+ size_t result = size_of_objects / mark_compact_speed_in_bytes_per_ms; |
+ return Min(result, kMaxMarkCompactTimeInMs); |
+} |
+ |
+ |
+GCIdleTimeAction GCIdleTimeHandler::Compute(int idle_time_in_ms, |
+ int contexts_disposed, |
+ size_t size_of_objects, |
+ bool incremental_marking_stopped, |
+ GCTracer* gc_tracer) { |
+ if (IsIdleRoundFinished()) { |
+ if (EnoughGarbageSinceLastIdleRound() || contexts_disposed > 0) { |
+ StartIdleRound(); |
+ } else { |
+ return GCIdleTimeAction::Nothing(); |
+ } |
+ } |
+ if (incremental_marking_stopped) { |
+ size_t speed = |
+ static_cast<size_t>(gc_tracer->MarkCompactSpeedInBytesPerMillisecond()); |
+ if (idle_time_in_ms >= |
+ static_cast<int>(EstimateMarkCompactTime(size_of_objects, speed))) { |
+ // If there are no more than two GCs left in this idle round and we are |
+ // allowed to do a full GC, then make those GCs full in order to compact |
+ // the code space. |
+ // TODO(ulan): Once we enable code compaction for incremental marking, we |
+ // can get rid of this special case and always start incremental marking. |
+ int remaining_mark_sweeps = |
+ kMaxMarkCompactsInIdleRound - mark_compacts_since_idle_round_started_; |
+ if (contexts_disposed > 0 || remaining_mark_sweeps <= 2) { |
+ return GCIdleTimeAction::FullGC(); |
+ } |
+ } |
+ } |
+ intptr_t speed = gc_tracer->IncrementalMarkingSpeedInBytesPerMillisecond(); |
+ size_t step_size = |
+ static_cast<size_t>(EstimateMarkingStepSize(idle_time_in_ms, speed)); |
+ return GCIdleTimeAction::IncrementalMarking(step_size); |
+} |
} |
} |