Revision: 21623
Author: hpa...@chromium.org
Date: Tue Jun 3 07:55:38 2014 UTC
Log: Tenure allocation sites only when semi-space is maximum size.
BUG=
R=mvstan...@chromium.org
Review URL: https://codereview.chromium.org/309623007
http://code.google.com/p/v8/source/detail?r=21623
Modified:
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/heap.h
/branches/bleeding_edge/src/mark-compact.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/spaces.h
/branches/bleeding_edge/test/cctest/test-heap.cc
=======================================
--- /branches/bleeding_edge/src/heap.cc Wed May 28 08:35:16 2014 UTC
+++ /branches/bleeding_edge/src/heap.cc Tue Jun 3 07:55:38 2014 UTC
@@ -101,6 +101,7 @@
promotion_rate_(0),
semi_space_copied_object_size_(0),
semi_space_copied_rate_(0),
+ maximum_size_scavenges_(0),
max_gc_pause_(0.0),
total_gc_time_ms_(0.0),
max_alive_after_gc_(0),
@@ -438,6 +439,13 @@
if (isolate()->concurrent_osr_enabled()) {
isolate()->optimizing_compiler_thread()->AgeBufferedOsrJobs();
}
+
+ if (new_space_.IsAtMaximumCapacity()) {
+ maximum_size_scavenges_++;
+ } else {
+ maximum_size_scavenges_ = 0;
+ }
+ CheckNewSpaceExpansionCriteria();
}
@@ -485,12 +493,19 @@
// If the scratchpad overflowed, we have to iterate over the allocation
// sites list.
+ // TODO(hpayer): We iterate over the whole list of allocation sites
when
+ // we grew to the maximum semi-space size to deopt maybe tenured
+ // allocation sites. We could hold the maybe tenured allocation sites
+ // in a seperate data structure if this is a performance problem.
bool use_scratchpad =
- allocation_sites_scratchpad_length_ <
kAllocationSiteScratchpadSize;
+ allocation_sites_scratchpad_length_ <
kAllocationSiteScratchpadSize &&
+ new_space_.IsAtMaximumCapacity() &&
+ maximum_size_scavenges_ == 0;
int i = 0;
Object* list_element = allocation_sites_list();
bool trigger_deoptimization = false;
+ bool maximum_size_scavenge = MaximumSizeScavenge();
while (use_scratchpad ?
i < allocation_sites_scratchpad_length_ :
list_element->IsAllocationSite()) {
@@ -500,14 +515,17 @@
allocation_mementos_found += site->memento_found_count();
if (site->memento_found_count() > 0) {
active_allocation_sites++;
- }
- if (site->DigestPretenuringFeedback()) trigger_deoptimization = true;
- if (site->GetPretenureMode() == TENURED) {
- tenure_decisions++;
- } else {
- dont_tenure_decisions++;
+ if (site->DigestPretenuringFeedback(maximum_size_scavenge)) {
+ trigger_deoptimization = true;
+ }
+ if (site->GetPretenureMode() == TENURED) {
+ tenure_decisions++;
+ } else {
+ dont_tenure_decisions++;
+ }
+ allocation_sites++;
}
- allocation_sites++;
+
if (use_scratchpad) {
i++;
} else {
@@ -1433,8 +1451,6 @@
// Used for updating survived_since_last_expansion_ at function end.
intptr_t survived_watermark = PromotedSpaceSizeOfObjects();
- CheckNewSpaceExpansionCriteria();
-
SelectScavengingVisitorsTable();
incremental_marking()->PrepareForScavenge();
=======================================
--- /branches/bleeding_edge/src/heap.h Tue May 27 13:43:29 2014 UTC
+++ /branches/bleeding_edge/src/heap.h Tue Jun 3 07:55:38 2014 UTC
@@ -1359,6 +1359,10 @@
void DeoptMarkedAllocationSites();
+ bool MaximumSizeScavenge() {
+ return maximum_size_scavenges_ > 0;
+ }
+
// ObjectStats are kept in two arrays, counts and sizes. Related stats
are
// stored in a contiguous linear buffer. Stats groups are stored one
after
// another.
@@ -2019,6 +2023,12 @@
intptr_t semi_space_copied_object_size_;
double semi_space_copied_rate_;
+ // This is the pretenuring trigger for allocation sites that are in maybe
+ // tenure state. When we switched to the maximum new space size we
deoptimize
+ // the code that belongs to the allocation site and derive the lifetime
+ // of the allocation site.
+ unsigned int maximum_size_scavenges_;
+
// TODO(hpayer): Allocation site pretenuring may make this method
obsolete.
// Re-visit incremental marking heuristics.
bool IsHighSurvivalRate() {
=======================================
--- /branches/bleeding_edge/src/mark-compact.cc Mon Jun 2 11:41:50 2014 UTC
+++ /branches/bleeding_edge/src/mark-compact.cc Tue Jun 3 07:55:38 2014 UTC
@@ -3030,7 +3030,6 @@
// sweep collection by failing allocations. But since we are already in
// a mark-sweep allocation, there is no sense in trying to trigger one.
AlwaysAllocateScope scope(isolate());
- heap()->CheckNewSpaceExpansionCriteria();
NewSpace* new_space = heap()->new_space();
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Tue Jun 3 00:34:01 2014 UTC
+++ /branches/bleeding_edge/src/objects-inl.h Tue Jun 3 07:55:38 2014 UTC
@@ -1577,42 +1577,60 @@
}
-inline bool AllocationSite::DigestPretenuringFeedback() {
- bool decision_changed = false;
+inline bool AllocationSite::MakePretenureDecision(
+ PretenureDecision current_decision,
+ double ratio,
+ bool maximum_size_scavenge) {
+ // Here we just allow state transitions from undecided or maybe tenure
+ // to don't tenure, maybe tenure, or tenure.
+ if ((current_decision == kUndecided || current_decision ==
kMaybeTenure)) {
+ if (ratio >= kPretenureRatio) {
+ // We just transition into tenure state when the semi-space was at
+ // maximum capacity.
+ if (maximum_size_scavenge) {
+ set_deopt_dependent_code(true);
+ set_pretenure_decision(kTenure);
+ // Currently we just need to deopt when we make a state transition
to
+ // tenure.
+ return true;
+ }
+ set_pretenure_decision(kMaybeTenure);
+ } else {
+ set_pretenure_decision(kDontTenure);
+ }
+ }
+ return false;
+}
+
+
+inline bool AllocationSite::DigestPretenuringFeedback(
+ bool maximum_size_scavenge) {
+ bool deopt = false;
int create_count = memento_create_count();
int found_count = memento_found_count();
bool minimum_mementos_created = create_count >= kPretenureMinimumCreated;
double ratio =
minimum_mementos_created || FLAG_trace_pretenuring_statistics ?
static_cast<double>(found_count) / create_count : 0.0;
- PretenureFlag current_mode = GetPretenureMode();
+ PretenureDecision current_decision = pretenure_decision();
- // TODO(hpayer): Add an intermediate state MAYBE_TENURE which collects
- // more lifetime feedback for tenuring candidates. In the meantime, we
- // just allow transitions from undecided to tenured or not tenured.
- if (minimum_mementos_created && pretenure_decision() == kUndecided) {
- PretenureDecision result = ratio >= kPretenureRatio
- ? kTenure
- : kDontTenure;
- set_pretenure_decision(result);
- if (current_mode != GetPretenureMode()) {
- decision_changed = true;
- set_deopt_dependent_code(true);
- }
+ if (minimum_mementos_created) {
+ deopt = MakePretenureDecision(
+ current_decision, ratio, maximum_size_scavenge);
}
if (FLAG_trace_pretenuring_statistics) {
PrintF(
"AllocationSite(%p): (created, found, ratio) (%d, %d, %f) %s
=> %s\n",
static_cast<void*>(this), create_count, found_count, ratio,
- current_mode == TENURED ? "tenured" : "not tenured",
- GetPretenureMode() == TENURED ? "tenured" : "not tenured");
+ PretenureDecisionName(current_decision),
+ PretenureDecisionName(pretenure_decision()));
}
// Clear feedback calculation fields until the next gc.
set_memento_found_count(0);
set_memento_create_count(0);
- return decision_changed;
+ return deopt;
}
=======================================
--- /branches/bleeding_edge/src/objects.cc Tue Jun 3 00:53:16 2014 UTC
+++ /branches/bleeding_edge/src/objects.cc Tue Jun 3 07:55:38 2014 UTC
@@ -13301,6 +13301,19 @@
if (*codes != site->dependent_code()) site->set_dependent_code(*codes);
info->dependencies(group)->Add(Handle<HeapObject>(*site), info->zone());
}
+
+
+const char* AllocationSite::PretenureDecisionName(PretenureDecision
decision) {
+ switch (decision) {
+ case kUndecided: return "undecided";
+ case kDontTenure: return "don't tenure";
+ case kMaybeTenure: return "maybe tenure";
+ case kTenure: return "tenure";
+ case kZombie: return "zombie";
+ default: UNREACHABLE();
+ }
+ return NULL;
+}
void JSObject::UpdateAllocationSite(Handle<JSObject> object,
=======================================
--- /branches/bleeding_edge/src/objects.h Tue Jun 3 04:01:34 2014 UTC
+++ /branches/bleeding_edge/src/objects.h Tue Jun 3 07:55:38 2014 UTC
@@ -8412,11 +8412,14 @@
enum PretenureDecision {
kUndecided = 0,
kDontTenure = 1,
- kTenure = 2,
- kZombie = 3,
+ kMaybeTenure = 2,
+ kTenure = 3,
+ kZombie = 4,
kLastPretenureDecisionValue = kZombie
};
+ const char* PretenureDecisionName(PretenureDecision decision);
+
DECL_ACCESSORS(transition_info, Object)
// nested_site threads a list of sites that represent nested literals
// walked in a particular order. So [[1, 2], 1, 2] will have one
@@ -8438,8 +8441,8 @@
class DoNotInlineBit: public BitField<bool, 29, 1> {};
// Bitfields for pretenure_data
- class MementoFoundCountBits: public BitField<int, 0, 27>
{};
- class PretenureDecisionBits: public BitField<PretenureDecision, 27, 2>
{};
+ class MementoFoundCountBits: public BitField<int, 0, 26>
{};
+ class PretenureDecisionBits: public BitField<PretenureDecision, 26, 3>
{};
class DeoptDependentCodeBit: public BitField<bool, 29, 1>
{};
STATIC_ASSERT(PretenureDecisionBits::kMax >=
kLastPretenureDecisionValue);
@@ -8502,7 +8505,11 @@
inline void MarkZombie();
- inline bool DigestPretenuringFeedback();
+ inline bool MakePretenureDecision(PretenureDecision current_decision,
+ double ratio,
+ bool maximum_size_scavenge);
+
+ inline bool DigestPretenuringFeedback(bool maximum_size_scavenge);
ElementsKind GetElementsKind() {
ASSERT(!SitePointsToLiteral());
=======================================
--- /branches/bleeding_edge/src/spaces.h Tue May 27 13:43:29 2014 UTC
+++ /branches/bleeding_edge/src/spaces.h Tue Jun 3 07:55:38 2014 UTC
@@ -2498,6 +2498,10 @@
ASSERT(to_space_.MaximumCapacity() == from_space_.MaximumCapacity());
return to_space_.MaximumCapacity();
}
+
+ bool IsAtMaximumCapacity() {
+ return Capacity() == MaximumCapacity();
+ }
// Returns the initial capacity of a semispace.
int InitialCapacity() {
=======================================
--- /branches/bleeding_edge/test/cctest/test-heap.cc Wed May 28 08:39:33
2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-heap.cc Tue Jun 3 07:55:38
2014 UTC
@@ -2199,6 +2199,11 @@
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
+
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
i::ScopedVector<char> source(1024);
i::OS::SNPrintF(
@@ -2243,6 +2248,11 @@
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
+
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
i::ScopedVector<char> source(1024);
i::OS::SNPrintF(
@@ -2279,6 +2289,12 @@
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
+
+
i::ScopedVector<char> source(1024);
i::OS::SNPrintF(
source,
@@ -2319,6 +2335,11 @@
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
+
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
i::ScopedVector<char> source(1024);
i::OS::SNPrintF(
@@ -2354,6 +2375,11 @@
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
+
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
i::ScopedVector<char> source(1024);
i::OS::SNPrintF(
@@ -2389,6 +2415,11 @@
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
+
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
i::ScopedVector<char> source(1024);
i::OS::SNPrintF(
@@ -2433,6 +2464,11 @@
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
+
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
i::ScopedVector<char> source(1024);
i::OS::SNPrintF(
@@ -2477,6 +2513,11 @@
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
+
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
i::ScopedVector<char> source(1024);
i::OS::SNPrintF(
@@ -2529,6 +2570,11 @@
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
+
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
i::ScopedVector<char> source(1024);
// Call new is doing slack tracking for the first
@@ -2575,6 +2621,11 @@
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
v8::HandleScope scope(CcTest::isolate());
+
+ // Grow new space unitl maximum capacity reached.
+ while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
+ CcTest::heap()->new_space()->Grow();
+ }
i::ScopedVector<char> source(1024);
// Call new is doing slack tracking for the first
--
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.