Index: src/heap/heap.cc |
diff --git a/src/heap/heap.cc b/src/heap/heap.cc |
index c3d44098620cdaf01c19e8fd6905bc60b0bee92c..759d370f6a477ae0e35dfc367bdedee17010b5fe 100644 |
--- a/src/heap/heap.cc |
+++ b/src/heap/heap.cc |
@@ -1131,8 +1131,7 @@ bool Heap::PerformGarbageCollection( |
// Temporarily set the limit for case when PostGarbageCollectionProcessing |
// allocates and triggers GC. The real limit is set at after |
// PostGarbageCollectionProcessing. |
- old_generation_allocation_limit_ = |
- OldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), 0); |
+ SetOldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), 0); |
old_gen_exhausted_ = false; |
old_generation_size_configured_ = true; |
} else { |
@@ -1166,8 +1165,8 @@ bool Heap::PerformGarbageCollection( |
// Register the amount of external allocated memory. |
amount_of_external_allocated_memory_at_last_global_gc_ = |
amount_of_external_allocated_memory_; |
- old_generation_allocation_limit_ = OldGenerationAllocationLimit( |
- PromotedSpaceSizeOfObjects(), freed_global_handles); |
+ SetOldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), |
+ freed_global_handles); |
// We finished a marking cycle. We can uncommit the marking deque until |
// we start marking again. |
mark_compact_collector_.UncommitMarkingDeque(); |
@@ -4548,7 +4547,7 @@ bool Heap::TryFinalizeIdleIncrementalMarking( |
bool Heap::WorthActivatingIncrementalMarking() { |
return incremental_marking()->IsStopped() && |
- incremental_marking()->WorthActivating() && NextGCIsLikelyToBeFull(); |
+ incremental_marking()->ShouldActivate(); |
} |
@@ -4573,6 +4572,7 @@ bool Heap::IdleNotification(double deadline_in_seconds) { |
static_cast<double>(base::Time::kMillisecondsPerSecond); |
HistogramTimerScope idle_notification_scope( |
isolate_->counters()->gc_idle_notification()); |
+ double idle_time_in_ms = deadline_in_ms - MonotonicallyIncreasingTimeInMs(); |
GCIdleTimeHandler::HeapState heap_state; |
heap_state.contexts_disposed = contexts_disposed_; |
@@ -4581,8 +4581,15 @@ bool Heap::IdleNotification(double deadline_in_seconds) { |
heap_state.size_of_objects = static_cast<size_t>(SizeOfObjects()); |
heap_state.incremental_marking_stopped = incremental_marking()->IsStopped(); |
// TODO(ulan): Start incremental marking only for large heaps. |
+ intptr_t limit = old_generation_allocation_limit_; |
+ if (static_cast<size_t>(idle_time_in_ms) > |
+ GCIdleTimeHandler::kMaxFrameRenderingIdleTime) { |
+ limit = idle_old_generation_allocation_limit_; |
+ } |
+ |
heap_state.can_start_incremental_marking = |
- incremental_marking()->ShouldActivate() && FLAG_incremental_marking && |
+ incremental_marking()->WorthActivating() && |
+ NextGCIsLikelyToBeFull(limit) && FLAG_incremental_marking && |
!mark_compact_collector()->sweeping_in_progress(); |
heap_state.sweeping_in_progress = |
mark_compact_collector()->sweeping_in_progress(); |
@@ -4603,7 +4610,6 @@ bool Heap::IdleNotification(double deadline_in_seconds) { |
static_cast<size_t>( |
tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond()); |
- double idle_time_in_ms = deadline_in_ms - MonotonicallyIncreasingTimeInMs(); |
GCIdleTimeAction action = |
gc_idle_time_handler_.Compute(idle_time_in_ms, heap_state); |
isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample( |
@@ -5178,21 +5184,37 @@ int64_t Heap::PromotedExternalMemorySize() { |
} |
-intptr_t Heap::OldGenerationAllocationLimit(intptr_t old_gen_size, |
- int freed_global_handles) { |
+intptr_t Heap::CalculateOldGenerationAllocationLimit(double factor, |
+ intptr_t old_gen_size) { |
+ CHECK(factor > 1.0); |
+ CHECK(old_gen_size > 0); |
+ intptr_t limit = static_cast<intptr_t>(old_gen_size * factor); |
+ limit = Max(limit, kMinimumOldGenerationAllocationLimit); |
+ limit += new_space_.Capacity(); |
+ intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2; |
+ return Min(limit, halfway_to_the_max); |
+} |
+ |
+ |
+void Heap::SetOldGenerationAllocationLimit(intptr_t old_gen_size, |
+ int freed_global_handles) { |
const int kMaxHandles = 1000; |
const int kMinHandles = 100; |
- double min_factor = 1.1; |
+ const double min_factor = 1.1; |
double max_factor = 4; |
+ const double idle_max_factor = 1.5; |
// We set the old generation growing factor to 2 to grow the heap slower on |
// memory-constrained devices. |
if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) { |
max_factor = 2; |
} |
+ |
// If there are many freed global handles, then the next full GC will |
// likely collect a lot of garbage. Choose the heap growing factor |
// depending on freed global handles. |
// TODO(ulan, hpayer): Take into account mutator utilization. |
+ // TODO(hpayer): The idle factor could make the handles heuristic obsolete. |
+ // Look into that. |
double factor; |
if (freed_global_handles <= kMinHandles) { |
factor = max_factor; |
@@ -5211,11 +5233,10 @@ intptr_t Heap::OldGenerationAllocationLimit(intptr_t old_gen_size, |
factor = min_factor; |
} |
- intptr_t limit = static_cast<intptr_t>(old_gen_size * factor); |
- limit = Max(limit, kMinimumOldGenerationAllocationLimit); |
- limit += new_space_.Capacity(); |
- intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2; |
- return Min(limit, halfway_to_the_max); |
+ old_generation_allocation_limit_ = |
+ CalculateOldGenerationAllocationLimit(factor, old_gen_size); |
+ idle_old_generation_allocation_limit_ = CalculateOldGenerationAllocationLimit( |
+ Min(factor, idle_max_factor), old_gen_size); |
} |