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