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.

Reply via email to