| Index: test/cctest/test-heap.cc
|
| diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
|
| index 6927c43b9ac9507ea1dfcb01e00ea43df6123782..2ccc9d41e69c4b795742eba362033998b1ad2f8b 100644
|
| --- a/test/cctest/test-heap.cc
|
| +++ b/test/cctest/test-heap.cc
|
| @@ -23,6 +23,19 @@ static void InitializeVM() {
|
| }
|
|
|
|
|
| +// Go through all incremental marking steps in one swoop.
|
| +static void SimulateIncrementalMarking() {
|
| + IncrementalMarking* marking = HEAP->incremental_marking();
|
| + CHECK(marking->IsStopped());
|
| + marking->Start();
|
| + CHECK(marking->IsMarking());
|
| + while (!marking->IsComplete()) {
|
| + marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
|
| + }
|
| + CHECK(marking->IsComplete());
|
| +}
|
| +
|
| +
|
| static void CheckMap(Map* map, int type, int instance_size) {
|
| CHECK(map->IsHeapObject());
|
| #ifdef DEBUG
|
| @@ -942,9 +955,9 @@ TEST(Regression39128) {
|
|
|
|
|
| TEST(TestCodeFlushing) {
|
| - i::FLAG_allow_natives_syntax = true;
|
| // If we do not flush code this test is invalid.
|
| if (!FLAG_flush_code) return;
|
| + i::FLAG_allow_natives_syntax = true;
|
| InitializeVM();
|
| v8::HandleScope scope;
|
| const char* source = "function foo() {"
|
| @@ -967,18 +980,16 @@ TEST(TestCodeFlushing) {
|
| Handle<JSFunction> function(JSFunction::cast(func_value));
|
| CHECK(function->shared()->is_compiled());
|
|
|
| - // TODO(1609) Currently incremental marker does not support code flushing.
|
| - HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
|
| - HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
|
| -
|
| + // The code will survive at least two GCs.
|
| + HEAP->CollectAllGarbage(Heap::kNoGCFlags);
|
| + HEAP->CollectAllGarbage(Heap::kNoGCFlags);
|
| CHECK(function->shared()->is_compiled());
|
|
|
| - HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
|
| - HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
|
| - HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
|
| - HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
|
| - HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
|
| - HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
|
| + // Simulate several GCs that use full marking.
|
| + const int kAgingThreshold = 6;
|
| + for (int i = 0; i < kAgingThreshold; i++) {
|
| + HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
|
| + }
|
|
|
| // foo should no longer be in the compilation cache
|
| CHECK(!function->shared()->is_compiled() || function->IsOptimized());
|
| @@ -990,6 +1001,74 @@ TEST(TestCodeFlushing) {
|
| }
|
|
|
|
|
| +TEST(TestCodeFlushingIncremental) {
|
| + // If we do not flush code this test is invalid.
|
| + if (!FLAG_flush_code) return;
|
| + i::FLAG_allow_natives_syntax = true;
|
| + InitializeVM();
|
| + v8::HandleScope scope;
|
| + const char* source = "function foo() {"
|
| + " var x = 42;"
|
| + " var y = 42;"
|
| + " var z = x + y;"
|
| + "};"
|
| + "foo()";
|
| + Handle<String> foo_name = FACTORY->LookupAsciiSymbol("foo");
|
| +
|
| + // This compile will add the code to the compilation cache.
|
| + { v8::HandleScope scope;
|
| + CompileRun(source);
|
| + }
|
| +
|
| + // Check function is compiled.
|
| + Object* func_value = Isolate::Current()->context()->global_object()->
|
| + GetProperty(*foo_name)->ToObjectChecked();
|
| + CHECK(func_value->IsJSFunction());
|
| + Handle<JSFunction> function(JSFunction::cast(func_value));
|
| + CHECK(function->shared()->is_compiled());
|
| +
|
| + // The code will survive at least two GCs.
|
| + HEAP->CollectAllGarbage(Heap::kNoGCFlags);
|
| + HEAP->CollectAllGarbage(Heap::kNoGCFlags);
|
| + CHECK(function->shared()->is_compiled());
|
| +
|
| + // Simulate several GCs that use incremental marking.
|
| + const int kAgingThreshold = 6;
|
| + for (int i = 0; i < kAgingThreshold; i++) {
|
| + HEAP->incremental_marking()->Abort();
|
| + SimulateIncrementalMarking();
|
| + HEAP->CollectAllGarbage(Heap::kNoGCFlags);
|
| + }
|
| + CHECK(!function->shared()->is_compiled() || function->IsOptimized());
|
| + CHECK(!function->is_compiled() || function->IsOptimized());
|
| +
|
| + // This compile will compile the function again.
|
| + { v8::HandleScope scope;
|
| + CompileRun("foo();");
|
| + }
|
| +
|
| + // Simulate several GCs that use incremental marking but make sure
|
| + // the loop breaks once the function is enqueued as a candidate.
|
| + for (int i = 0; i < kAgingThreshold; i++) {
|
| + HEAP->incremental_marking()->Abort();
|
| + SimulateIncrementalMarking();
|
| + if (!function->next_function_link()->IsUndefined()) break;
|
| + HEAP->CollectAllGarbage(Heap::kNoGCFlags);
|
| + }
|
| +
|
| + // Force optimization while incremental marking is active and while
|
| + // the function is enqueued as a candidate.
|
| + { v8::HandleScope scope;
|
| + CompileRun("%OptimizeFunctionOnNextCall(foo); foo();");
|
| + }
|
| +
|
| + // Simulate one final GC to make sure the candidate queue is sane.
|
| + HEAP->CollectAllGarbage(Heap::kNoGCFlags);
|
| + CHECK(function->shared()->is_compiled() || !function->IsOptimized());
|
| + CHECK(function->is_compiled() || !function->IsOptimized());
|
| +}
|
| +
|
| +
|
| // Count the number of native contexts in the weak list of native contexts.
|
| int CountNativeContexts() {
|
| int count = 0;
|
| @@ -1767,19 +1846,6 @@ static int CountMapTransitions(Map* map) {
|
| }
|
|
|
|
|
| -// Go through all incremental marking steps in one swoop.
|
| -static void SimulateIncrementalMarking() {
|
| - IncrementalMarking* marking = HEAP->incremental_marking();
|
| - CHECK(marking->IsStopped());
|
| - marking->Start();
|
| - CHECK(marking->IsMarking());
|
| - while (!marking->IsComplete()) {
|
| - marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
|
| - }
|
| - CHECK(marking->IsComplete());
|
| -}
|
| -
|
| -
|
| // Test that map transitions are cleared and maps are collected with
|
| // incremental marking as well.
|
| TEST(Regress1465) {
|
|
|