| 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();
 | 
|  }
 | 
|  
 | 
|  
 | 
| 
 |