Index: src/heap.cc |
diff --git a/src/heap.cc b/src/heap.cc |
index 52711584363977303d682436a0cec6f746e7cfff..60b425c2bb566c82526fdfc4006737223a874428 100644 |
--- a/src/heap.cc |
+++ b/src/heap.cc |
@@ -506,7 +506,8 @@ void Heap::RepairFreeListsAfterBoot() { |
void Heap::ProcessPretenuringFeedback() { |
- if (FLAG_allocation_site_pretenuring) { |
+ if (FLAG_allocation_site_pretenuring && |
+ new_space_high_promotion_mode_active_) { |
int tenure_decisions = 0; |
int dont_tenure_decisions = 0; |
int allocation_mementos_found = 0; |
@@ -514,7 +515,7 @@ void Heap::ProcessPretenuringFeedback() { |
int active_allocation_sites = 0; |
// If the scratchpad overflowed, we have to iterate over the allocation |
- // stites list. |
+ // sites list. |
bool use_scratchpad = |
allocation_sites_scratchpad_length < kAllocationSiteScratchpadSize; |
@@ -1100,12 +1101,15 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector, |
PrintPID("Limited new space size due to high promotion rate: %d MB\n", |
new_space_.InitialCapacity() / MB); |
} |
- // Support for global pre-tenuring uses the high promotion mode as a |
- // heuristic indicator of whether to pretenure or not, we trigger |
- // deoptimization here to take advantage of pre-tenuring as soon as |
- // possible. |
+ // The high promotion mode is our indicator to turn on pretenuring. We have |
+ // to deoptimize all optimized code in global pretenuring mode and all |
+ // code which should be tenured in local pretenuring mode. |
if (FLAG_pretenuring) { |
- isolate_->stack_guard()->FullDeopt(); |
+ if (FLAG_allocation_site_pretenuring) { |
+ ResetAllAllocationSitesDependentCode(NOT_TENURED); |
+ } else { |
+ isolate_->stack_guard()->FullDeopt(); |
+ } |
} |
} else if (new_space_high_promotion_mode_active_ && |
IsStableOrDecreasingSurvivalTrend() && |
@@ -1118,9 +1122,9 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector, |
PrintPID("Unlimited new space size due to low promotion rate: %d MB\n", |
new_space_.MaximumCapacity() / MB); |
} |
- // Trigger deoptimization here to turn off pre-tenuring as soon as |
+ // Trigger deoptimization here to turn off global pretenuring as soon as |
// possible. |
- if (FLAG_pretenuring) { |
+ if (FLAG_pretenuring && !FLAG_allocation_site_pretenuring) { |
isolate_->stack_guard()->FullDeopt(); |
} |
} |
@@ -1212,6 +1216,8 @@ void Heap::MarkCompact(GCTracer* tracer) { |
gc_state_ = MARK_COMPACT; |
LOG(isolate_, ResourceEvent("markcompact", "begin")); |
+ uint64_t size_of_objects_before_gc = SizeOfObjects(); |
+ |
mark_compact_collector_.Prepare(tracer); |
ms_count_++; |
@@ -1228,6 +1234,10 @@ void Heap::MarkCompact(GCTracer* tracer) { |
isolate_->counters()->objs_since_last_full()->Set(0); |
flush_monomorphic_ics_ = false; |
+ |
+ if (FLAG_allocation_site_pretenuring) { |
+ EvaluateOldSpaceLocalPretenuring(size_of_objects_before_gc); |
+ } |
} |
@@ -1966,6 +1976,39 @@ void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer, |
} |
+void Heap::ResetAllAllocationSitesDependentCode(PretenureFlag flag) { |
+ Object* cur = allocation_sites_list(); |
+ while (cur->IsAllocationSite()) { |
+ AllocationSite* casted = AllocationSite::cast(cur); |
+ if (casted->GetPretenureMode() == flag) { |
+ casted->ResetPretenureDecision(); |
+ } |
+ cur = casted->weak_next(); |
+ } |
+} |
+ |
+ |
+void Heap::EvaluateOldSpaceLocalPretenuring( |
+ uint64_t size_of_objects_before_gc) { |
+ uint64_t size_of_objects_after_gc = SizeOfObjects(); |
+ double old_generation_survival_rate = |
+ (static_cast<double>(size_of_objects_after_gc) * 100) / |
+ static_cast<double>(size_of_objects_before_gc); |
+ |
+ if (old_generation_survival_rate < kOldSurvivalRateLowThreshold) { |
+ // Too many objects died in the old generation, pretenuring of wrong |
+ // allocation sites may be the cause for that. We have to deopt all |
+ // dependent code registered in the allocation sites to re-evaluate |
+ // our pretenuring decisions. |
+ ResetAllAllocationSitesDependentCode(TENURED); |
+ if (FLAG_trace_pretenuring) { |
+ PrintF("Deopt all allocation sites dependent code due to low survival " |
+ "rate in the old generation %f\n", old_generation_survival_rate); |
+ } |
+ } |
+} |
+ |
+ |
void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) { |
DisallowHeapAllocation no_allocation; |
// All external strings are listed in the external string table. |