Index: src/heap.cc |
diff --git a/src/heap.cc b/src/heap.cc |
index db13637c9aa9222c631d461ad227f45f727d43fe..064ae39825ce8cfc5d87f9a23be958f319b79bd5 100644 |
--- a/src/heap.cc |
+++ b/src/heap.cc |
@@ -61,7 +61,6 @@ Heap::Heap() |
// Will be 4 * reserved_semispace_size_ to ensure that young |
// generation can be aligned to its size. |
maximum_committed_(0), |
- old_space_growing_factor_(4), |
survived_since_last_expansion_(0), |
sweep_generation_(0), |
always_allocate_scope_depth_(0), |
@@ -90,7 +89,6 @@ Heap::Heap() |
allocation_timeout_(0), |
#endif // DEBUG |
old_generation_allocation_limit_(kMinimumOldGenerationAllocationLimit), |
- size_of_old_gen_at_last_old_space_gc_(0), |
old_gen_exhausted_(false), |
inline_allocation_disabled_(false), |
store_buffer_rebuilder_(store_buffer()), |
@@ -1056,7 +1054,7 @@ bool Heap::PerformGarbageCollection( |
GarbageCollector collector, |
GCTracer* tracer, |
const v8::GCCallbackFlags gc_callback_flags) { |
- bool next_gc_likely_to_collect_more = false; |
+ int freed_global_handles = 0; |
if (collector != SCAVENGER) { |
PROFILE(isolate_, CodeMovingGCEvent()); |
@@ -1096,12 +1094,11 @@ bool Heap::PerformGarbageCollection( |
// Perform mark-sweep with optional compaction. |
MarkCompact(tracer); |
sweep_generation_++; |
- |
- size_of_old_gen_at_last_old_space_gc_ = PromotedSpaceSizeOfObjects(); |
- |
+ // 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(size_of_old_gen_at_last_old_space_gc_); |
- |
+ OldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), 0); |
old_gen_exhausted_ = false; |
} else { |
tracer_ = tracer; |
@@ -1120,7 +1117,7 @@ bool Heap::PerformGarbageCollection( |
gc_post_processing_depth_++; |
{ AllowHeapAllocation allow_allocation; |
GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
- next_gc_likely_to_collect_more = |
+ freed_global_handles = |
isolate_->global_handles()->PostGarbageCollectionProcessing( |
collector, tracer); |
} |
@@ -1135,6 +1132,9 @@ 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); |
} |
{ GCCallbacksScope scope(this); |
@@ -1153,7 +1153,7 @@ bool Heap::PerformGarbageCollection( |
} |
#endif |
- return next_gc_likely_to_collect_more; |
+ return freed_global_handles > 0; |
} |
@@ -4989,12 +4989,6 @@ bool Heap::ConfigureHeap(int max_semi_space_size, |
code_range_size_ = code_range_size * MB; |
- // We set the old generation growing factor to 2 to grow the heap slower on |
- // memory-constrained devices. |
- if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) { |
- old_space_growing_factor_ = 2; |
- } |
- |
configured_ = true; |
return true; |
} |
@@ -5063,6 +5057,47 @@ int64_t Heap::PromotedExternalMemorySize() { |
} |
+intptr_t Heap::OldGenerationAllocationLimit(intptr_t old_gen_size, |
+ int freed_global_handles) { |
+ const int kMaxHandles = 1000; |
+ const int kMinHandles = 100; |
+ double min_factor = 1.1; |
+ double max_factor = 4; |
+ // 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. |
+ double factor; |
+ if (freed_global_handles <= kMinHandles) { |
+ factor = max_factor; |
+ } else if (freed_global_handles >= kMaxHandles) { |
+ factor = min_factor; |
+ } else { |
+ // Compute factor using linear interpolation between points |
+ // (kMinHandles, max_factor) and (kMaxHandles, min_factor). |
+ factor = max_factor - |
+ (freed_global_handles - kMinHandles) * (max_factor - min_factor) / |
+ (kMaxHandles - kMinHandles); |
+ } |
+ |
+ if (FLAG_stress_compaction || |
+ mark_compact_collector()->reduce_memory_footprint_) { |
+ 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); |
+} |
+ |
+ |
void Heap::EnableInlineAllocation() { |
if (!inline_allocation_disabled_) return; |
inline_allocation_disabled_ = false; |