Index: test/cctest/test-heap.cc |
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc |
index aca4b9d2fba03e94ed0be9a3a3cf35df2dfa23cf..fcee9f4498548184a794770d86c3c31acc86c473 100644 |
--- a/test/cctest/test-heap.cc |
+++ b/test/cctest/test-heap.cc |
@@ -1052,53 +1052,61 @@ TEST(Regression39128) { |
} |
-TEST(TestCodeFlushing) { |
+UNINITIALIZED_TEST(TestCodeFlushing) { |
// If we do not flush code this test is invalid. |
if (!FLAG_flush_code) return; |
i::FLAG_allow_natives_syntax = true; |
i::FLAG_optimize_for_size = false; |
- CcTest::InitializeVM(); |
- Isolate* isolate = CcTest::i_isolate(); |
- Factory* factory = isolate->factory(); |
- v8::HandleScope scope(CcTest::isolate()); |
- const char* source = "function foo() {" |
- " var x = 42;" |
- " var y = 42;" |
- " var z = x + y;" |
- "};" |
- "foo()"; |
- Handle<String> foo_name = factory->InternalizeUtf8String("foo"); |
+ v8::Isolate* isolate = v8::Isolate::New(); |
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
+ isolate->Enter(); |
+ Factory* factory = i_isolate->factory(); |
+ { |
+ v8::HandleScope scope(isolate); |
+ v8::Context::New(isolate)->Enter(); |
+ const char* source = |
+ "function foo() {" |
+ " var x = 42;" |
+ " var y = 42;" |
+ " var z = x + y;" |
+ "};" |
+ "foo()"; |
+ Handle<String> foo_name = factory->InternalizeUtf8String("foo"); |
+ |
+ // This compile will add the code to the compilation cache. |
+ { |
+ v8::HandleScope scope(isolate); |
+ CompileRun(source); |
+ } |
- // This compile will add the code to the compilation cache. |
- { v8::HandleScope scope(CcTest::isolate()); |
- CompileRun(source); |
- } |
+ // Check function is compiled. |
+ Handle<Object> func_value = Object::GetProperty(i_isolate->global_object(), |
+ foo_name).ToHandleChecked(); |
+ CHECK(func_value->IsJSFunction()); |
+ Handle<JSFunction> function = Handle<JSFunction>::cast(func_value); |
+ CHECK(function->shared()->is_compiled()); |
- // Check function is compiled. |
- Handle<Object> func_value = Object::GetProperty( |
- CcTest::i_isolate()->global_object(), foo_name).ToHandleChecked(); |
- CHECK(func_value->IsJSFunction()); |
- Handle<JSFunction> function = Handle<JSFunction>::cast(func_value); |
- CHECK(function->shared()->is_compiled()); |
+ // The code will survive at least two GCs. |
+ i_isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
+ i_isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
+ CHECK(function->shared()->is_compiled()); |
- // The code will survive at least two GCs. |
- CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
- CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
- CHECK(function->shared()->is_compiled()); |
+ // Simulate several GCs that use full marking. |
+ const int kAgingThreshold = 6; |
+ for (int i = 0; i < kAgingThreshold; i++) { |
+ i_isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
+ } |
- // Simulate several GCs that use full marking. |
- const int kAgingThreshold = 6; |
- for (int i = 0; i < kAgingThreshold; i++) { |
- CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
+ // foo should no longer be in the compilation cache |
+ CHECK(!function->shared()->is_compiled() || function->IsOptimized()); |
+ CHECK(!function->is_compiled() || function->IsOptimized()); |
+ // Call foo to get it recompiled. |
+ CompileRun("foo()"); |
+ CHECK(function->shared()->is_compiled()); |
+ CHECK(function->is_compiled()); |
} |
- |
- // foo should no longer be in the compilation cache |
- CHECK(!function->shared()->is_compiled() || function->IsOptimized()); |
- CHECK(!function->is_compiled() || function->IsOptimized()); |
- // Call foo to get it recompiled. |
- CompileRun("foo()"); |
- CHECK(function->shared()->is_compiled()); |
- CHECK(function->is_compiled()); |
+ isolate->Exit(); |
+ isolate->Dispose(); |
} |
@@ -3297,26 +3305,28 @@ class SourceResource : public v8::String::ExternalOneByteStringResource { |
}; |
-void ReleaseStackTraceDataTest(const char* source, const char* accessor) { |
+void ReleaseStackTraceDataTest(v8::Isolate* isolate, const char* source, |
+ const char* accessor) { |
// Test that the data retained by the Error.stack accessor is released |
// after the first time the accessor is fired. We use external string |
// to check whether the data is being released since the external string |
// resource's callback is fired when the external string is GC'ed. |
- v8::HandleScope scope(CcTest::isolate()); |
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
+ v8::HandleScope scope(isolate); |
SourceResource* resource = new SourceResource(i::StrDup(source)); |
{ |
- v8::HandleScope scope(CcTest::isolate()); |
+ v8::HandleScope scope(isolate); |
v8::Handle<v8::String> source_string = |
- v8::String::NewExternal(CcTest::isolate(), resource); |
- CcTest::heap()->CollectAllAvailableGarbage(); |
+ v8::String::NewExternal(isolate, resource); |
+ i_isolate->heap()->CollectAllAvailableGarbage(); |
v8::Script::Compile(source_string)->Run(); |
CHECK(!resource->IsDisposed()); |
} |
- // CcTest::heap()->CollectAllAvailableGarbage(); |
+ // i_isolate->heap()->CollectAllAvailableGarbage(); |
CHECK(!resource->IsDisposed()); |
CompileRun(accessor); |
- CcTest::heap()->CollectAllAvailableGarbage(); |
+ i_isolate->heap()->CollectAllAvailableGarbage(); |
// External source has been released. |
CHECK(resource->IsDisposed()); |
@@ -3324,7 +3334,7 @@ void ReleaseStackTraceDataTest(const char* source, const char* accessor) { |
} |
-TEST(ReleaseStackTraceData) { |
+UNINITIALIZED_TEST(ReleaseStackTraceData) { |
if (i::FLAG_always_opt) { |
// TODO(ulan): Remove this once the memory leak via code_next_link is fixed. |
// See: https://codereview.chromium.org/181833004/ |
@@ -3332,46 +3342,51 @@ TEST(ReleaseStackTraceData) { |
} |
FLAG_use_ic = false; // ICs retain objects. |
FLAG_concurrent_recompilation = false; |
- CcTest::InitializeVM(); |
- static const char* source1 = "var error = null; " |
- /* Normal Error */ "try { " |
- " throw new Error(); " |
- "} catch (e) { " |
- " error = e; " |
- "} "; |
- static const char* source2 = "var error = null; " |
- /* Stack overflow */ "try { " |
- " (function f() { f(); })(); " |
- "} catch (e) { " |
- " error = e; " |
- "} "; |
- static const char* source3 = "var error = null; " |
- /* Normal Error */ "try { " |
- /* as prototype */ " throw new Error(); " |
- "} catch (e) { " |
- " error = {}; " |
- " error.__proto__ = e; " |
- "} "; |
- static const char* source4 = "var error = null; " |
- /* Stack overflow */ "try { " |
- /* as prototype */ " (function f() { f(); })(); " |
- "} catch (e) { " |
- " error = {}; " |
- " error.__proto__ = e; " |
- "} "; |
- static const char* getter = "error.stack"; |
- static const char* setter = "error.stack = 0"; |
- |
- ReleaseStackTraceDataTest(source1, setter); |
- ReleaseStackTraceDataTest(source2, setter); |
- // We do not test source3 and source4 with setter, since the setter is |
- // supposed to (untypically) write to the receiver, not the holder. This is |
- // to emulate the behavior of a data property. |
- |
- ReleaseStackTraceDataTest(source1, getter); |
- ReleaseStackTraceDataTest(source2, getter); |
- ReleaseStackTraceDataTest(source3, getter); |
- ReleaseStackTraceDataTest(source4, getter); |
+ v8::Isolate* isolate = v8::Isolate::New(); |
+ { |
+ v8::Isolate::Scope isolate_scope(isolate); |
+ v8::HandleScope handle_scope(isolate); |
+ v8::Context::New(isolate)->Enter(); |
+ static const char* source1 = "var error = null; " |
+ /* Normal Error */ "try { " |
+ " throw new Error(); " |
+ "} catch (e) { " |
+ " error = e; " |
+ "} "; |
+ static const char* source2 = "var error = null; " |
+ /* Stack overflow */ "try { " |
+ " (function f() { f(); })(); " |
+ "} catch (e) { " |
+ " error = e; " |
+ "} "; |
+ static const char* source3 = "var error = null; " |
+ /* Normal Error */ "try { " |
+ /* as prototype */ " throw new Error(); " |
+ "} catch (e) { " |
+ " error = {}; " |
+ " error.__proto__ = e; " |
+ "} "; |
+ static const char* source4 = "var error = null; " |
+ /* Stack overflow */ "try { " |
+ /* as prototype */ " (function f() { f(); })(); " |
+ "} catch (e) { " |
+ " error = {}; " |
+ " error.__proto__ = e; " |
+ "} "; |
+ static const char* getter = "error.stack"; |
+ static const char* setter = "error.stack = 0"; |
+ |
+ ReleaseStackTraceDataTest(isolate, source1, setter); |
+ ReleaseStackTraceDataTest(isolate, source2, setter); |
+ // We do not test source3 and source4 with setter, since the setter is |
+ // supposed to (untypically) write to the receiver, not the holder. This is |
+ // to emulate the behavior of a data property. |
+ |
+ ReleaseStackTraceDataTest(isolate, source1, getter); |
+ ReleaseStackTraceDataTest(isolate, source2, getter); |
+ ReleaseStackTraceDataTest(isolate, source3, getter); |
+ ReleaseStackTraceDataTest(isolate, source4, getter); |
+ } |
} |
@@ -4349,78 +4364,84 @@ TEST(ArrayShiftSweeping) { |
} |
-TEST(PromotionQueue) { |
+UNINITIALIZED_TEST(PromotionQueue) { |
i::FLAG_expose_gc = true; |
i::FLAG_max_semi_space_size = 2; |
- CcTest::InitializeVM(); |
- v8::HandleScope scope(CcTest::isolate()); |
- Isolate* isolate = CcTest::i_isolate(); |
- Heap* heap = isolate->heap(); |
- NewSpace* new_space = heap->new_space(); |
- |
- // In this test we will try to overwrite the promotion queue which is at the |
- // end of to-space. To actually make that possible, we need at least two |
- // semi-space pages and take advantage of fragementation. |
- // (1) Grow semi-space to two pages. |
- // (2) Create a few small long living objects and call the scavenger to |
- // move them to the other semi-space. |
- // (3) Create a huge object, i.e., remainder of first semi-space page and |
- // create another huge object which should be of maximum allocatable memory |
- // size of the second semi-space page. |
- // (4) Call the scavenger again. |
- // What will happen is: the scavenger will promote the objects created in (2) |
- // and will create promotion queue entries at the end of the second |
- // semi-space page during the next scavenge when it promotes the objects to |
- // the old generation. The first allocation of (3) will fill up the first |
- // semi-space page. The second allocation in (3) will not fit into the first |
- // semi-space page, but it will overwrite the promotion queue which are in |
- // the second semi-space page. If the right guards are in place, the promotion |
- // queue will be evacuated in that case. |
- |
- // Grow the semi-space to two pages to make semi-space copy overwrite the |
- // promotion queue, which will be at the end of the second page. |
- intptr_t old_capacity = new_space->TotalCapacity(); |
- new_space->Grow(); |
- CHECK(new_space->IsAtMaximumCapacity()); |
- CHECK(2 * old_capacity == new_space->TotalCapacity()); |
- |
- // Call the scavenger two times to get an empty new space |
- heap->CollectGarbage(NEW_SPACE); |
- heap->CollectGarbage(NEW_SPACE); |
- |
- // First create a few objects which will survive a scavenge, and will get |
- // promoted to the old generation later on. These objects will create |
- // promotion queue entries at the end of the second semi-space page. |
- const int number_handles = 12; |
- Handle<FixedArray> handles[number_handles]; |
- for (int i = 0; i < number_handles; i++) { |
- handles[i] = isolate->factory()->NewFixedArray(1, NOT_TENURED); |
+ v8::Isolate* isolate = v8::Isolate::New(); |
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
+ { |
+ v8::Isolate::Scope isolate_scope(isolate); |
+ v8::HandleScope handle_scope(isolate); |
+ v8::Context::New(isolate)->Enter(); |
+ Heap* heap = i_isolate->heap(); |
+ NewSpace* new_space = heap->new_space(); |
+ |
+ // In this test we will try to overwrite the promotion queue which is at the |
+ // end of to-space. To actually make that possible, we need at least two |
+ // semi-space pages and take advantage of fragementation. |
+ // (1) Grow semi-space to two pages. |
+ // (2) Create a few small long living objects and call the scavenger to |
+ // move them to the other semi-space. |
+ // (3) Create a huge object, i.e., remainder of first semi-space page and |
+ // create another huge object which should be of maximum allocatable memory |
+ // size of the second semi-space page. |
+ // (4) Call the scavenger again. |
+ // What will happen is: the scavenger will promote the objects created in |
+ // (2) and will create promotion queue entries at the end of the second |
+ // semi-space page during the next scavenge when it promotes the objects to |
+ // the old generation. The first allocation of (3) will fill up the first |
+ // semi-space page. The second allocation in (3) will not fit into the |
+ // first semi-space page, but it will overwrite the promotion queue which |
+ // are in the second semi-space page. If the right guards are in place, the |
+ // promotion queue will be evacuated in that case. |
+ |
+ // Grow the semi-space to two pages to make semi-space copy overwrite the |
+ // promotion queue, which will be at the end of the second page. |
+ intptr_t old_capacity = new_space->TotalCapacity(); |
+ new_space->Grow(); |
+ CHECK(new_space->IsAtMaximumCapacity()); |
+ CHECK(2 * old_capacity == new_space->TotalCapacity()); |
+ |
+ // Call the scavenger two times to get an empty new space |
+ heap->CollectGarbage(NEW_SPACE); |
+ heap->CollectGarbage(NEW_SPACE); |
+ |
+ // First create a few objects which will survive a scavenge, and will get |
+ // promoted to the old generation later on. These objects will create |
+ // promotion queue entries at the end of the second semi-space page. |
+ const int number_handles = 12; |
+ Handle<FixedArray> handles[number_handles]; |
+ for (int i = 0; i < number_handles; i++) { |
+ handles[i] = i_isolate->factory()->NewFixedArray(1, NOT_TENURED); |
+ } |
+ heap->CollectGarbage(NEW_SPACE); |
+ |
+ // Create the first huge object which will exactly fit the first semi-space |
+ // page. |
+ int new_linear_size = |
+ static_cast<int>(*heap->new_space()->allocation_limit_address() - |
+ *heap->new_space()->allocation_top_address()); |
+ int length = new_linear_size / kPointerSize - FixedArray::kHeaderSize; |
+ Handle<FixedArray> first = |
+ i_isolate->factory()->NewFixedArray(length, NOT_TENURED); |
+ CHECK(heap->InNewSpace(*first)); |
+ |
+ // Create the second huge object of maximum allocatable second semi-space |
+ // page size. |
+ new_linear_size = |
+ static_cast<int>(*heap->new_space()->allocation_limit_address() - |
+ *heap->new_space()->allocation_top_address()); |
+ length = Page::kMaxRegularHeapObjectSize / kPointerSize - |
+ FixedArray::kHeaderSize; |
+ Handle<FixedArray> second = |
+ i_isolate->factory()->NewFixedArray(length, NOT_TENURED); |
+ CHECK(heap->InNewSpace(*second)); |
+ |
+ // This scavenge will corrupt memory if the promotion queue is not |
+ // evacuated. |
+ heap->CollectGarbage(NEW_SPACE); |
} |
- heap->CollectGarbage(NEW_SPACE); |
- |
- // Create the first huge object which will exactly fit the first semi-space |
- // page. |
- int new_linear_size = static_cast<int>( |
- *heap->new_space()->allocation_limit_address() - |
- *heap->new_space()->allocation_top_address()); |
- int length = new_linear_size / kPointerSize - FixedArray::kHeaderSize; |
- Handle<FixedArray> first = |
- isolate->factory()->NewFixedArray(length, NOT_TENURED); |
- CHECK(heap->InNewSpace(*first)); |
- |
- // Create the second huge object of maximum allocatable second semi-space |
- // page size. |
- new_linear_size = static_cast<int>( |
- *heap->new_space()->allocation_limit_address() - |
- *heap->new_space()->allocation_top_address()); |
- length = Page::kMaxRegularHeapObjectSize / kPointerSize - |
- FixedArray::kHeaderSize; |
- Handle<FixedArray> second = |
- isolate->factory()->NewFixedArray(length, NOT_TENURED); |
- CHECK(heap->InNewSpace(*second)); |
- |
- // This scavenge will corrupt memory if the promotion queue is not evacuated. |
- heap->CollectGarbage(NEW_SPACE); |
+ isolate->Dispose(); |
} |