Reviewers: ulan,

Description:
Do 2 GCs on LowMemoryNotification instead of 7.

Please review this at https://chromiumcodereview.appspot.com/10933124/

SVN Base: http://v8.googlecode.com/svn/branches/bleeding_edge/

Affected files:
  M     src/heap-inl.h
  M     src/heap.h
  M     src/heap.cc
  M     src/mark-compact.cc
  M     test/cctest/test-heap.cc


Index: src/heap-inl.h
===================================================================
--- src/heap-inl.h      (revision 12520)
+++ src/heap-inl.h      (working copy)
@@ -774,6 +774,17 @@
 }


+FlushEagerly::FlushEagerly() {
+  old_state_ = HEAP->flush_eagerly();
+  HEAP->set_flush_eagerly(true);
+}
+
+
+FlushEagerly::~FlushEagerly() {
+  HEAP->set_flush_eagerly(old_state_);
+}
+
+
 #ifdef DEBUG
 AssertNoAllocation::AssertNoAllocation() {
   Isolate* isolate = ISOLATE;
Index: src/heap.cc
===================================================================
--- src/heap.cc (revision 12528)
+++ src/heap.cc (working copy)
@@ -119,6 +119,7 @@
       debug_utils_(NULL),
 #endif  // DEBUG
       new_space_high_promotion_mode_active_(false),
+      flush_eagerly_(false),
       old_gen_promotion_limit_(kMinimumPromotionLimit),
       old_gen_allocation_limit_(kMinimumAllocationLimit),
       old_gen_limit_factor_(1),
@@ -546,7 +547,8 @@
   mark_compact_collector()->SetFlags(kMakeHeapIterableMask |
                                      kReduceMemoryFootprintMask);
   isolate_->compilation_cache()->Clear();
-  const int kMaxNumberOfAttempts = 7;
+  const int kMaxNumberOfAttempts = 2;
+  FlushEagerly flush_eagerly_scope;
   for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) {
if (!CollectGarbage(OLD_POINTER_SPACE, MARK_COMPACTOR, gc_reason, NULL)) {
       break;
Index: src/heap.h
===================================================================
--- src/heap.h  (revision 12520)
+++ src/heap.h  (working copy)
@@ -1315,6 +1315,9 @@
     return disallow_allocation_failure_;
   }

+  bool flush_eagerly() { return flush_eagerly_; }
+  void set_flush_eagerly(bool to) { flush_eagerly_ = to; }
+
   void TracePathToObjectFrom(Object* target, Object* root);
   void TracePathToObject(Object* target);
   void TracePathToGlobal();
@@ -1772,6 +1775,9 @@
   // rates caused by the mutator allocating a lot of long-lived objects.
   bool new_space_high_promotion_mode_active_;

+  // For emergency memory-freeing GCs.
+  bool flush_eagerly_;
+
// Limit that triggers a global GC on the next (normally caused) GC. This
   // is checked when we have already decided to do a GC to help determine
   // which collector to invoke.
@@ -2196,6 +2202,16 @@
 };


+class FlushEagerly {
+ public:
+  inline FlushEagerly();
+  inline ~FlushEagerly();
+
+ private:
+  bool old_state_;
+};
+
+
 class AlwaysAllocateScope {
  public:
   inline AlwaysAllocateScope();
Index: src/mark-compact.cc
===================================================================
--- src/mark-compact.cc (revision 12520)
+++ src/mark-compact.cc (working copy)
@@ -1248,7 +1248,8 @@
     }

     // Age this shared function info.
-    if (shared_info->code_age() < kCodeAgeThreshold) {
+    if (!heap->flush_eagerly() &&
+        shared_info->code_age() < kCodeAgeThreshold) {
       shared_info->set_code_age(shared_info->code_age() + 1);
       return false;
     }
@@ -1325,7 +1326,8 @@
       }

       // Check if we should flush now.
- if (value == ((heap->sweep_generation() - kRegExpCodeThreshold) & 0xff)) {
+      if (heap->flush_eagerly() ||
+ value == ((heap->sweep_generation() - kRegExpCodeThreshold) & 0xff)) {
         re->SetDataAtUnchecked(JSRegExp::code_index(is_ascii),
                                Smi::FromInt(JSRegExp::kUninitializedValue),
                                heap);
Index: test/cctest/test-heap.cc
===================================================================
--- test/cctest/test-heap.cc    (revision 12520)
+++ test/cctest/test-heap.cc    (working copy)
@@ -1941,6 +1941,57 @@
 }


+// Tests the FlushEagerly class from heap.h
+TEST(ReleaseUnoptimizedCode) {
+  i::FLAG_trace_gc = true;
+  // The optimizer can allocate stuff, messing up the test.
+  i::FLAG_crankshaft = false;
+  if (i::FLAG_always_opt) return;
+  InitializeVM();
+  v8::HandleScope scope;
+
+  PagedSpace* code_space = HEAP->code_space();
+  CompileRun("var a = [];"
+             "var sum = 0;"
+             "for (var j = 0; j < 1e4; j++) {"
+             "  var fn = new Function("
+ " 'var k; var o = {}; for (k in o) { } return ' + j + ';');"
+             "  sum += fn();"
+             "}");
+  HEAP->CollectAllGarbage(Heap::kNoGCFlags, "triggered for preparation");
+  printf("%d\n", code_space->CountTotalPages());
+  CHECK_GE(5, code_space->CountTotalPages());
+  HEAP->CollectAllAvailableGarbage("triggered really hard");
+  printf("%d\n", code_space->CountTotalPages());
+  CHECK_LE(2, code_space->CountTotalPages());
+}
+
+
+// Tests the FlushEagerly class from heap.h
+TEST(ReleaseRegexpCode) {
+  i::FLAG_trace_gc = true;
+  // The optimizer can allocate stuff, messing up the test.
+  i::FLAG_crankshaft = false;
+  if (i::FLAG_always_opt) return;
+  InitializeVM();
+  v8::HandleScope scope;
+
+  PagedSpace* code_space = HEAP->code_space();
+  CompileRun("var a = [];"
+             "for (var j = 0; j < 2e4; j++) {"
+             "  var re = RegExp(j + '?');"
+             "  a.push(re);"
+             "  re.test('foo');"
+             "}");
+  HEAP->CollectAllGarbage(Heap::kNoGCFlags, "triggered for preparation");
+  printf("%d\n", code_space->CountTotalPages());
+  CHECK_GT(15, code_space->CountTotalPages());
+  HEAP->CollectAllAvailableGarbage("triggered really hard");
+  printf("%d\n", code_space->CountTotalPages());
+  CHECK_LE(2, code_space->CountTotalPages());
+}
+
+
 TEST(Regress2237) {
   InitializeVM();
   v8::HandleScope scope;


--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev

Reply via email to