Home | History | Annotate | Download | only in heap
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include <stdlib.h>
     29 #include <utility>
     30 
     31 #include "src/compilation-cache.h"
     32 #include "src/context-measure.h"
     33 #include "src/deoptimizer.h"
     34 #include "src/execution.h"
     35 #include "src/factory.h"
     36 #include "src/global-handles.h"
     37 #include "src/heap/gc-tracer.h"
     38 #include "src/heap/memory-reducer.h"
     39 #include "src/ic/ic.h"
     40 #include "src/macro-assembler.h"
     41 #include "src/regexp/jsregexp.h"
     42 #include "src/snapshot/snapshot.h"
     43 #include "test/cctest/cctest.h"
     44 #include "test/cctest/heap/heap-tester.h"
     45 #include "test/cctest/heap/utils-inl.h"
     46 #include "test/cctest/test-feedback-vector.h"
     47 
     48 
     49 namespace v8 {
     50 namespace internal {
     51 
     52 static void CheckMap(Map* map, int type, int instance_size) {
     53   CHECK(map->IsHeapObject());
     54 #ifdef DEBUG
     55   CHECK(CcTest::heap()->Contains(map));
     56 #endif
     57   CHECK_EQ(CcTest::heap()->meta_map(), map->map());
     58   CHECK_EQ(type, map->instance_type());
     59   CHECK_EQ(instance_size, map->instance_size());
     60 }
     61 
     62 
     63 TEST(HeapMaps) {
     64   CcTest::InitializeVM();
     65   Heap* heap = CcTest::heap();
     66   CheckMap(heap->meta_map(), MAP_TYPE, Map::kSize);
     67   CheckMap(heap->heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize);
     68 #define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
     69   CheckMap(heap->type##_map(), SIMD128_VALUE_TYPE, Type::kSize);
     70   SIMD128_TYPES(SIMD128_TYPE)
     71 #undef SIMD128_TYPE
     72   CheckMap(heap->fixed_array_map(), FIXED_ARRAY_TYPE, kVariableSizeSentinel);
     73   CheckMap(heap->string_map(), STRING_TYPE, kVariableSizeSentinel);
     74 }
     75 
     76 
     77 static void CheckOddball(Isolate* isolate, Object* obj, const char* string) {
     78   CHECK(obj->IsOddball());
     79   Handle<Object> handle(obj, isolate);
     80   Object* print_string = *Object::ToString(isolate, handle).ToHandleChecked();
     81   CHECK(String::cast(print_string)->IsUtf8EqualTo(CStrVector(string)));
     82 }
     83 
     84 
     85 static void CheckSmi(Isolate* isolate, int value, const char* string) {
     86   Handle<Object> handle(Smi::FromInt(value), isolate);
     87   Object* print_string = *Object::ToString(isolate, handle).ToHandleChecked();
     88   CHECK(String::cast(print_string)->IsUtf8EqualTo(CStrVector(string)));
     89 }
     90 
     91 
     92 static void CheckNumber(Isolate* isolate, double value, const char* string) {
     93   Handle<Object> number = isolate->factory()->NewNumber(value);
     94   CHECK(number->IsNumber());
     95   Handle<Object> print_string =
     96       Object::ToString(isolate, number).ToHandleChecked();
     97   CHECK(String::cast(*print_string)->IsUtf8EqualTo(CStrVector(string)));
     98 }
     99 
    100 
    101 static void CheckFindCodeObject(Isolate* isolate) {
    102   // Test FindCodeObject
    103 #define __ assm.
    104 
    105   Assembler assm(isolate, NULL, 0);
    106 
    107   __ nop();  // supported on all architectures
    108 
    109   CodeDesc desc;
    110   assm.GetCode(&desc);
    111   Handle<Code> code = isolate->factory()->NewCode(
    112       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    113   CHECK(code->IsCode());
    114 
    115   HeapObject* obj = HeapObject::cast(*code);
    116   Address obj_addr = obj->address();
    117 
    118   for (int i = 0; i < obj->Size(); i += kPointerSize) {
    119     Object* found = isolate->FindCodeObject(obj_addr + i);
    120     CHECK_EQ(*code, found);
    121   }
    122 
    123   Handle<Code> copy = isolate->factory()->NewCode(
    124       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    125   HeapObject* obj_copy = HeapObject::cast(*copy);
    126   Object* not_right = isolate->FindCodeObject(obj_copy->address() +
    127                                               obj_copy->Size() / 2);
    128   CHECK(not_right != *code);
    129 }
    130 
    131 
    132 TEST(HandleNull) {
    133   CcTest::InitializeVM();
    134   Isolate* isolate = CcTest::i_isolate();
    135   HandleScope outer_scope(isolate);
    136   LocalContext context;
    137   Handle<Object> n(static_cast<Object*>(nullptr), isolate);
    138   CHECK(!n.is_null());
    139 }
    140 
    141 
    142 TEST(HeapObjects) {
    143   CcTest::InitializeVM();
    144   Isolate* isolate = CcTest::i_isolate();
    145   Factory* factory = isolate->factory();
    146   Heap* heap = isolate->heap();
    147 
    148   HandleScope sc(isolate);
    149   Handle<Object> value = factory->NewNumber(1.000123);
    150   CHECK(value->IsHeapNumber());
    151   CHECK(value->IsNumber());
    152   CHECK_EQ(1.000123, value->Number());
    153 
    154   value = factory->NewNumber(1.0);
    155   CHECK(value->IsSmi());
    156   CHECK(value->IsNumber());
    157   CHECK_EQ(1.0, value->Number());
    158 
    159   value = factory->NewNumberFromInt(1024);
    160   CHECK(value->IsSmi());
    161   CHECK(value->IsNumber());
    162   CHECK_EQ(1024.0, value->Number());
    163 
    164   value = factory->NewNumberFromInt(Smi::kMinValue);
    165   CHECK(value->IsSmi());
    166   CHECK(value->IsNumber());
    167   CHECK_EQ(Smi::kMinValue, Handle<Smi>::cast(value)->value());
    168 
    169   value = factory->NewNumberFromInt(Smi::kMaxValue);
    170   CHECK(value->IsSmi());
    171   CHECK(value->IsNumber());
    172   CHECK_EQ(Smi::kMaxValue, Handle<Smi>::cast(value)->value());
    173 
    174 #if !defined(V8_TARGET_ARCH_64_BIT)
    175   // TODO(lrn): We need a NumberFromIntptr function in order to test this.
    176   value = factory->NewNumberFromInt(Smi::kMinValue - 1);
    177   CHECK(value->IsHeapNumber());
    178   CHECK(value->IsNumber());
    179   CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number());
    180 #endif
    181 
    182   value = factory->NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1);
    183   CHECK(value->IsHeapNumber());
    184   CHECK(value->IsNumber());
    185   CHECK_EQ(static_cast<double>(static_cast<uint32_t>(Smi::kMaxValue) + 1),
    186            value->Number());
    187 
    188   value = factory->NewNumberFromUint(static_cast<uint32_t>(1) << 31);
    189   CHECK(value->IsHeapNumber());
    190   CHECK(value->IsNumber());
    191   CHECK_EQ(static_cast<double>(static_cast<uint32_t>(1) << 31),
    192            value->Number());
    193 
    194   // nan oddball checks
    195   CHECK(factory->nan_value()->IsNumber());
    196   CHECK(std::isnan(factory->nan_value()->Number()));
    197 
    198   Handle<String> s = factory->NewStringFromStaticChars("fisk hest ");
    199   CHECK(s->IsString());
    200   CHECK_EQ(10, s->length());
    201 
    202   Handle<String> object_string = Handle<String>::cast(factory->Object_string());
    203   Handle<JSGlobalObject> global(
    204       CcTest::i_isolate()->context()->global_object());
    205   CHECK(Just(true) == JSReceiver::HasOwnProperty(global, object_string));
    206 
    207   // Check ToString for oddballs
    208   CheckOddball(isolate, heap->true_value(), "true");
    209   CheckOddball(isolate, heap->false_value(), "false");
    210   CheckOddball(isolate, heap->null_value(), "null");
    211   CheckOddball(isolate, heap->undefined_value(), "undefined");
    212 
    213   // Check ToString for Smis
    214   CheckSmi(isolate, 0, "0");
    215   CheckSmi(isolate, 42, "42");
    216   CheckSmi(isolate, -42, "-42");
    217 
    218   // Check ToString for Numbers
    219   CheckNumber(isolate, 1.1, "1.1");
    220 
    221   CheckFindCodeObject(isolate);
    222 }
    223 
    224 
    225 template <typename T, typename LANE_TYPE, int LANES>
    226 static void CheckSimdValue(T* value, LANE_TYPE lane_values[LANES],
    227                            LANE_TYPE other_value) {
    228   // Check against lane_values, and check that all lanes can be set to
    229   // other_value without disturbing the other lanes.
    230   for (int i = 0; i < LANES; i++) {
    231     CHECK_EQ(lane_values[i], value->get_lane(i));
    232   }
    233   for (int i = 0; i < LANES; i++) {
    234     value->set_lane(i, other_value);  // change the value
    235     for (int j = 0; j < LANES; j++) {
    236       if (i != j)
    237         CHECK_EQ(lane_values[j], value->get_lane(j));
    238       else
    239         CHECK_EQ(other_value, value->get_lane(j));
    240     }
    241     value->set_lane(i, lane_values[i]);  // restore the lane
    242   }
    243   CHECK(value->BooleanValue());  // SIMD values are 'true'.
    244 }
    245 
    246 
    247 TEST(SimdObjects) {
    248   CcTest::InitializeVM();
    249   Isolate* isolate = CcTest::i_isolate();
    250   Factory* factory = isolate->factory();
    251 
    252   HandleScope sc(isolate);
    253 
    254   // Float32x4
    255   {
    256     float lanes[4] = {1, 2, 3, 4};
    257     float quiet_NaN = std::numeric_limits<float>::quiet_NaN();
    258     float signaling_NaN = std::numeric_limits<float>::signaling_NaN();
    259 
    260     Handle<Float32x4> value = factory->NewFloat32x4(lanes);
    261     CHECK(value->IsFloat32x4());
    262     CheckSimdValue<Float32x4, float, 4>(*value, lanes, 3.14f);
    263 
    264     // Check special lane values.
    265     value->set_lane(1, -0.0);
    266     CHECK_EQ(-0.0f, value->get_lane(1));
    267     CHECK(std::signbit(value->get_lane(1)));  // Sign bit should be preserved.
    268     value->set_lane(2, quiet_NaN);
    269     CHECK(std::isnan(value->get_lane(2)));
    270     value->set_lane(3, signaling_NaN);
    271     CHECK(std::isnan(value->get_lane(3)));
    272 
    273 #ifdef OBJECT_PRINT
    274     // Check value printing.
    275     {
    276       value = factory->NewFloat32x4(lanes);
    277       std::ostringstream os;
    278       value->Float32x4Print(os);
    279       CHECK_EQ("1, 2, 3, 4", os.str());
    280     }
    281     {
    282       float special_lanes[4] = {0, -0.0, quiet_NaN, signaling_NaN};
    283       value = factory->NewFloat32x4(special_lanes);
    284       std::ostringstream os;
    285       value->Float32x4Print(os);
    286       // Value printing doesn't preserve signed zeroes.
    287       CHECK_EQ("0, 0, NaN, NaN", os.str());
    288     }
    289 #endif  // OBJECT_PRINT
    290   }
    291   // Int32x4
    292   {
    293     int32_t lanes[4] = {1, 2, 3, 4};
    294 
    295     Handle<Int32x4> value = factory->NewInt32x4(lanes);
    296     CHECK(value->IsInt32x4());
    297     CheckSimdValue<Int32x4, int32_t, 4>(*value, lanes, 3);
    298 
    299 #ifdef OBJECT_PRINT
    300     std::ostringstream os;
    301     value->Int32x4Print(os);
    302     CHECK_EQ("1, 2, 3, 4", os.str());
    303 #endif  // OBJECT_PRINT
    304   }
    305   // Uint32x4
    306   {
    307     uint32_t lanes[4] = {1, 2, 3, 4};
    308 
    309     Handle<Uint32x4> value = factory->NewUint32x4(lanes);
    310     CHECK(value->IsUint32x4());
    311     CheckSimdValue<Uint32x4, uint32_t, 4>(*value, lanes, 3);
    312 
    313 #ifdef OBJECT_PRINT
    314     std::ostringstream os;
    315     value->Uint32x4Print(os);
    316     CHECK_EQ("1, 2, 3, 4", os.str());
    317 #endif  // OBJECT_PRINT
    318   }
    319   // Bool32x4
    320   {
    321     bool lanes[4] = {true, false, true, false};
    322 
    323     Handle<Bool32x4> value = factory->NewBool32x4(lanes);
    324     CHECK(value->IsBool32x4());
    325     CheckSimdValue<Bool32x4, bool, 4>(*value, lanes, false);
    326 
    327 #ifdef OBJECT_PRINT
    328     std::ostringstream os;
    329     value->Bool32x4Print(os);
    330     CHECK_EQ("true, false, true, false", os.str());
    331 #endif  // OBJECT_PRINT
    332   }
    333   // Int16x8
    334   {
    335     int16_t lanes[8] = {1, 2, 3, 4, 5, 6, 7, 8};
    336 
    337     Handle<Int16x8> value = factory->NewInt16x8(lanes);
    338     CHECK(value->IsInt16x8());
    339     CheckSimdValue<Int16x8, int16_t, 8>(*value, lanes, 32767);
    340 
    341 #ifdef OBJECT_PRINT
    342     std::ostringstream os;
    343     value->Int16x8Print(os);
    344     CHECK_EQ("1, 2, 3, 4, 5, 6, 7, 8", os.str());
    345 #endif  // OBJECT_PRINT
    346   }
    347   // Uint16x8
    348   {
    349     uint16_t lanes[8] = {1, 2, 3, 4, 5, 6, 7, 8};
    350 
    351     Handle<Uint16x8> value = factory->NewUint16x8(lanes);
    352     CHECK(value->IsUint16x8());
    353     CheckSimdValue<Uint16x8, uint16_t, 8>(*value, lanes, 32767);
    354 
    355 #ifdef OBJECT_PRINT
    356     std::ostringstream os;
    357     value->Uint16x8Print(os);
    358     CHECK_EQ("1, 2, 3, 4, 5, 6, 7, 8", os.str());
    359 #endif  // OBJECT_PRINT
    360   }
    361   // Bool16x8
    362   {
    363     bool lanes[8] = {true, false, true, false, true, false, true, false};
    364 
    365     Handle<Bool16x8> value = factory->NewBool16x8(lanes);
    366     CHECK(value->IsBool16x8());
    367     CheckSimdValue<Bool16x8, bool, 8>(*value, lanes, false);
    368 
    369 #ifdef OBJECT_PRINT
    370     std::ostringstream os;
    371     value->Bool16x8Print(os);
    372     CHECK_EQ("true, false, true, false, true, false, true, false", os.str());
    373 #endif  // OBJECT_PRINT
    374   }
    375   // Int8x16
    376   {
    377     int8_t lanes[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
    378 
    379     Handle<Int8x16> value = factory->NewInt8x16(lanes);
    380     CHECK(value->IsInt8x16());
    381     CheckSimdValue<Int8x16, int8_t, 16>(*value, lanes, 127);
    382 
    383 #ifdef OBJECT_PRINT
    384     std::ostringstream os;
    385     value->Int8x16Print(os);
    386     CHECK_EQ("1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16", os.str());
    387 #endif  // OBJECT_PRINT
    388   }
    389   // Uint8x16
    390   {
    391     uint8_t lanes[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
    392 
    393     Handle<Uint8x16> value = factory->NewUint8x16(lanes);
    394     CHECK(value->IsUint8x16());
    395     CheckSimdValue<Uint8x16, uint8_t, 16>(*value, lanes, 127);
    396 
    397 #ifdef OBJECT_PRINT
    398     std::ostringstream os;
    399     value->Uint8x16Print(os);
    400     CHECK_EQ("1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16", os.str());
    401 #endif  // OBJECT_PRINT
    402   }
    403   // Bool8x16
    404   {
    405     bool lanes[16] = {true, false, true, false, true, false, true, false,
    406                       true, false, true, false, true, false, true, false};
    407 
    408     Handle<Bool8x16> value = factory->NewBool8x16(lanes);
    409     CHECK(value->IsBool8x16());
    410     CheckSimdValue<Bool8x16, bool, 16>(*value, lanes, false);
    411 
    412 #ifdef OBJECT_PRINT
    413     std::ostringstream os;
    414     value->Bool8x16Print(os);
    415     CHECK_EQ(
    416         "true, false, true, false, true, false, true, false, true, false, "
    417         "true, false, true, false, true, false",
    418         os.str());
    419 #endif  // OBJECT_PRINT
    420   }
    421 }
    422 
    423 
    424 TEST(Tagging) {
    425   CcTest::InitializeVM();
    426   int request = 24;
    427   CHECK_EQ(request, static_cast<int>(OBJECT_POINTER_ALIGN(request)));
    428   CHECK(Smi::FromInt(42)->IsSmi());
    429   CHECK(Smi::FromInt(Smi::kMinValue)->IsSmi());
    430   CHECK(Smi::FromInt(Smi::kMaxValue)->IsSmi());
    431 }
    432 
    433 
    434 TEST(GarbageCollection) {
    435   CcTest::InitializeVM();
    436   Isolate* isolate = CcTest::i_isolate();
    437   Heap* heap = isolate->heap();
    438   Factory* factory = isolate->factory();
    439 
    440   HandleScope sc(isolate);
    441   // Check GC.
    442   heap->CollectGarbage(NEW_SPACE);
    443 
    444   Handle<JSGlobalObject> global(
    445       CcTest::i_isolate()->context()->global_object());
    446   Handle<String> name = factory->InternalizeUtf8String("theFunction");
    447   Handle<String> prop_name = factory->InternalizeUtf8String("theSlot");
    448   Handle<String> prop_namex = factory->InternalizeUtf8String("theSlotx");
    449   Handle<String> obj_name = factory->InternalizeUtf8String("theObject");
    450   Handle<Smi> twenty_three(Smi::FromInt(23), isolate);
    451   Handle<Smi> twenty_four(Smi::FromInt(24), isolate);
    452 
    453   {
    454     HandleScope inner_scope(isolate);
    455     // Allocate a function and keep it in global object's property.
    456     Handle<JSFunction> function = factory->NewFunction(name);
    457     JSReceiver::SetProperty(global, name, function, SLOPPY).Check();
    458     // Allocate an object.  Unrooted after leaving the scope.
    459     Handle<JSObject> obj = factory->NewJSObject(function);
    460     JSReceiver::SetProperty(obj, prop_name, twenty_three, SLOPPY).Check();
    461     JSReceiver::SetProperty(obj, prop_namex, twenty_four, SLOPPY).Check();
    462 
    463     CHECK_EQ(Smi::FromInt(23),
    464              *Object::GetProperty(obj, prop_name).ToHandleChecked());
    465     CHECK_EQ(Smi::FromInt(24),
    466              *Object::GetProperty(obj, prop_namex).ToHandleChecked());
    467   }
    468 
    469   heap->CollectGarbage(NEW_SPACE);
    470 
    471   // Function should be alive.
    472   CHECK(Just(true) == JSReceiver::HasOwnProperty(global, name));
    473   // Check function is retained.
    474   Handle<Object> func_value =
    475       Object::GetProperty(global, name).ToHandleChecked();
    476   CHECK(func_value->IsJSFunction());
    477   Handle<JSFunction> function = Handle<JSFunction>::cast(func_value);
    478 
    479   {
    480     HandleScope inner_scope(isolate);
    481     // Allocate another object, make it reachable from global.
    482     Handle<JSObject> obj = factory->NewJSObject(function);
    483     JSReceiver::SetProperty(global, obj_name, obj, SLOPPY).Check();
    484     JSReceiver::SetProperty(obj, prop_name, twenty_three, SLOPPY).Check();
    485   }
    486 
    487   // After gc, it should survive.
    488   heap->CollectGarbage(NEW_SPACE);
    489 
    490   CHECK(Just(true) == JSReceiver::HasOwnProperty(global, obj_name));
    491   Handle<Object> obj =
    492       Object::GetProperty(global, obj_name).ToHandleChecked();
    493   CHECK(obj->IsJSObject());
    494   CHECK_EQ(Smi::FromInt(23),
    495            *Object::GetProperty(obj, prop_name).ToHandleChecked());
    496 }
    497 
    498 
    499 static void VerifyStringAllocation(Isolate* isolate, const char* string) {
    500   HandleScope scope(isolate);
    501   Handle<String> s = isolate->factory()->NewStringFromUtf8(
    502       CStrVector(string)).ToHandleChecked();
    503   CHECK_EQ(StrLength(string), s->length());
    504   for (int index = 0; index < s->length(); index++) {
    505     CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index));
    506   }
    507 }
    508 
    509 
    510 TEST(String) {
    511   CcTest::InitializeVM();
    512   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
    513 
    514   VerifyStringAllocation(isolate, "a");
    515   VerifyStringAllocation(isolate, "ab");
    516   VerifyStringAllocation(isolate, "abc");
    517   VerifyStringAllocation(isolate, "abcd");
    518   VerifyStringAllocation(isolate, "fiskerdrengen er paa havet");
    519 }
    520 
    521 
    522 TEST(LocalHandles) {
    523   CcTest::InitializeVM();
    524   Isolate* isolate = CcTest::i_isolate();
    525   Factory* factory = isolate->factory();
    526 
    527   v8::HandleScope scope(CcTest::isolate());
    528   const char* name = "Kasper the spunky";
    529   Handle<String> string = factory->NewStringFromAsciiChecked(name);
    530   CHECK_EQ(StrLength(name), string->length());
    531 }
    532 
    533 
    534 TEST(GlobalHandles) {
    535   CcTest::InitializeVM();
    536   Isolate* isolate = CcTest::i_isolate();
    537   Heap* heap = isolate->heap();
    538   Factory* factory = isolate->factory();
    539   GlobalHandles* global_handles = isolate->global_handles();
    540 
    541   Handle<Object> h1;
    542   Handle<Object> h2;
    543   Handle<Object> h3;
    544   Handle<Object> h4;
    545 
    546   {
    547     HandleScope scope(isolate);
    548 
    549     Handle<Object> i = factory->NewStringFromStaticChars("fisk");
    550     Handle<Object> u = factory->NewNumber(1.12344);
    551 
    552     h1 = global_handles->Create(*i);
    553     h2 = global_handles->Create(*u);
    554     h3 = global_handles->Create(*i);
    555     h4 = global_handles->Create(*u);
    556   }
    557 
    558   // after gc, it should survive
    559   heap->CollectGarbage(NEW_SPACE);
    560 
    561   CHECK((*h1)->IsString());
    562   CHECK((*h2)->IsHeapNumber());
    563   CHECK((*h3)->IsString());
    564   CHECK((*h4)->IsHeapNumber());
    565 
    566   CHECK_EQ(*h3, *h1);
    567   GlobalHandles::Destroy(h1.location());
    568   GlobalHandles::Destroy(h3.location());
    569 
    570   CHECK_EQ(*h4, *h2);
    571   GlobalHandles::Destroy(h2.location());
    572   GlobalHandles::Destroy(h4.location());
    573 }
    574 
    575 
    576 static bool WeakPointerCleared = false;
    577 
    578 static void TestWeakGlobalHandleCallback(
    579     const v8::WeakCallbackData<v8::Value, void>& data) {
    580   std::pair<v8::Persistent<v8::Value>*, int>* p =
    581       reinterpret_cast<std::pair<v8::Persistent<v8::Value>*, int>*>(
    582           data.GetParameter());
    583   if (p->second == 1234) WeakPointerCleared = true;
    584   p->first->Reset();
    585 }
    586 
    587 
    588 TEST(WeakGlobalHandlesScavenge) {
    589   i::FLAG_stress_compaction = false;
    590   CcTest::InitializeVM();
    591   Isolate* isolate = CcTest::i_isolate();
    592   Heap* heap = isolate->heap();
    593   Factory* factory = isolate->factory();
    594   GlobalHandles* global_handles = isolate->global_handles();
    595 
    596   WeakPointerCleared = false;
    597 
    598   Handle<Object> h1;
    599   Handle<Object> h2;
    600 
    601   {
    602     HandleScope scope(isolate);
    603 
    604     Handle<Object> i = factory->NewStringFromStaticChars("fisk");
    605     Handle<Object> u = factory->NewNumber(1.12344);
    606 
    607     h1 = global_handles->Create(*i);
    608     h2 = global_handles->Create(*u);
    609   }
    610 
    611   std::pair<Handle<Object>*, int> handle_and_id(&h2, 1234);
    612   GlobalHandles::MakeWeak(h2.location(),
    613                           reinterpret_cast<void*>(&handle_and_id),
    614                           &TestWeakGlobalHandleCallback);
    615 
    616   // Scavenge treats weak pointers as normal roots.
    617   heap->CollectGarbage(NEW_SPACE);
    618 
    619   CHECK((*h1)->IsString());
    620   CHECK((*h2)->IsHeapNumber());
    621 
    622   CHECK(!WeakPointerCleared);
    623   CHECK(!global_handles->IsNearDeath(h2.location()));
    624   CHECK(!global_handles->IsNearDeath(h1.location()));
    625 
    626   GlobalHandles::Destroy(h1.location());
    627   GlobalHandles::Destroy(h2.location());
    628 }
    629 
    630 
    631 TEST(WeakGlobalHandlesMark) {
    632   CcTest::InitializeVM();
    633   Isolate* isolate = CcTest::i_isolate();
    634   Heap* heap = isolate->heap();
    635   Factory* factory = isolate->factory();
    636   GlobalHandles* global_handles = isolate->global_handles();
    637 
    638   WeakPointerCleared = false;
    639 
    640   Handle<Object> h1;
    641   Handle<Object> h2;
    642 
    643   {
    644     HandleScope scope(isolate);
    645 
    646     Handle<Object> i = factory->NewStringFromStaticChars("fisk");
    647     Handle<Object> u = factory->NewNumber(1.12344);
    648 
    649     h1 = global_handles->Create(*i);
    650     h2 = global_handles->Create(*u);
    651   }
    652 
    653   // Make sure the objects are promoted.
    654   heap->CollectGarbage(OLD_SPACE);
    655   heap->CollectGarbage(NEW_SPACE);
    656   CHECK(!heap->InNewSpace(*h1) && !heap->InNewSpace(*h2));
    657 
    658   std::pair<Handle<Object>*, int> handle_and_id(&h2, 1234);
    659   GlobalHandles::MakeWeak(h2.location(),
    660                           reinterpret_cast<void*>(&handle_and_id),
    661                           &TestWeakGlobalHandleCallback);
    662   CHECK(!GlobalHandles::IsNearDeath(h1.location()));
    663   CHECK(!GlobalHandles::IsNearDeath(h2.location()));
    664 
    665   // Incremental marking potentially marked handles before they turned weak.
    666   heap->CollectAllGarbage();
    667 
    668   CHECK((*h1)->IsString());
    669 
    670   CHECK(WeakPointerCleared);
    671   CHECK(!GlobalHandles::IsNearDeath(h1.location()));
    672 
    673   GlobalHandles::Destroy(h1.location());
    674 }
    675 
    676 
    677 TEST(DeleteWeakGlobalHandle) {
    678   i::FLAG_stress_compaction = false;
    679   CcTest::InitializeVM();
    680   Isolate* isolate = CcTest::i_isolate();
    681   Heap* heap = isolate->heap();
    682   Factory* factory = isolate->factory();
    683   GlobalHandles* global_handles = isolate->global_handles();
    684 
    685   WeakPointerCleared = false;
    686 
    687   Handle<Object> h;
    688 
    689   {
    690     HandleScope scope(isolate);
    691 
    692     Handle<Object> i = factory->NewStringFromStaticChars("fisk");
    693     h = global_handles->Create(*i);
    694   }
    695 
    696   std::pair<Handle<Object>*, int> handle_and_id(&h, 1234);
    697   GlobalHandles::MakeWeak(h.location(),
    698                           reinterpret_cast<void*>(&handle_and_id),
    699                           &TestWeakGlobalHandleCallback);
    700 
    701   // Scanvenge does not recognize weak reference.
    702   heap->CollectGarbage(NEW_SPACE);
    703 
    704   CHECK(!WeakPointerCleared);
    705 
    706   // Mark-compact treats weak reference properly.
    707   heap->CollectGarbage(OLD_SPACE);
    708 
    709   CHECK(WeakPointerCleared);
    710 }
    711 
    712 
    713 TEST(BytecodeArray) {
    714   static const uint8_t kRawBytes[] = {0xc3, 0x7e, 0xa5, 0x5a};
    715   static const int kRawBytesSize = sizeof(kRawBytes);
    716   static const int kFrameSize = 32;
    717   static const int kParameterCount = 2;
    718 
    719   i::FLAG_manual_evacuation_candidates_selection = true;
    720   CcTest::InitializeVM();
    721   Isolate* isolate = CcTest::i_isolate();
    722   Heap* heap = isolate->heap();
    723   Factory* factory = isolate->factory();
    724   HandleScope scope(isolate);
    725 
    726   SimulateFullSpace(heap->old_space());
    727   Handle<FixedArray> constant_pool = factory->NewFixedArray(5, TENURED);
    728   for (int i = 0; i < 5; i++) {
    729     Handle<Object> number = factory->NewHeapNumber(i);
    730     constant_pool->set(i, *number);
    731   }
    732 
    733   // Allocate and initialize BytecodeArray
    734   Handle<BytecodeArray> array = factory->NewBytecodeArray(
    735       kRawBytesSize, kRawBytes, kFrameSize, kParameterCount, constant_pool);
    736 
    737   CHECK(array->IsBytecodeArray());
    738   CHECK_EQ(array->length(), (int)sizeof(kRawBytes));
    739   CHECK_EQ(array->frame_size(), kFrameSize);
    740   CHECK_EQ(array->parameter_count(), kParameterCount);
    741   CHECK_EQ(array->constant_pool(), *constant_pool);
    742   CHECK_LE(array->address(), array->GetFirstBytecodeAddress());
    743   CHECK_GE(array->address() + array->BytecodeArraySize(),
    744            array->GetFirstBytecodeAddress() + array->length());
    745   for (int i = 0; i < kRawBytesSize; i++) {
    746     CHECK_EQ(array->GetFirstBytecodeAddress()[i], kRawBytes[i]);
    747     CHECK_EQ(array->get(i), kRawBytes[i]);
    748   }
    749 
    750   FixedArray* old_constant_pool_address = *constant_pool;
    751 
    752   // Perform a full garbage collection and force the constant pool to be on an
    753   // evacuation candidate.
    754   Page* evac_page = Page::FromAddress(constant_pool->address());
    755   evac_page->SetFlag(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
    756   heap->CollectAllGarbage();
    757 
    758   // BytecodeArray should survive.
    759   CHECK_EQ(array->length(), kRawBytesSize);
    760   CHECK_EQ(array->frame_size(), kFrameSize);
    761   for (int i = 0; i < kRawBytesSize; i++) {
    762     CHECK_EQ(array->get(i), kRawBytes[i]);
    763     CHECK_EQ(array->GetFirstBytecodeAddress()[i], kRawBytes[i]);
    764   }
    765 
    766   // Constant pool should have been migrated.
    767   CHECK_EQ(array->constant_pool(), *constant_pool);
    768   CHECK_NE(array->constant_pool(), old_constant_pool_address);
    769 }
    770 
    771 
    772 static const char* not_so_random_string_table[] = {
    773   "abstract",
    774   "boolean",
    775   "break",
    776   "byte",
    777   "case",
    778   "catch",
    779   "char",
    780   "class",
    781   "const",
    782   "continue",
    783   "debugger",
    784   "default",
    785   "delete",
    786   "do",
    787   "double",
    788   "else",
    789   "enum",
    790   "export",
    791   "extends",
    792   "false",
    793   "final",
    794   "finally",
    795   "float",
    796   "for",
    797   "function",
    798   "goto",
    799   "if",
    800   "implements",
    801   "import",
    802   "in",
    803   "instanceof",
    804   "int",
    805   "interface",
    806   "long",
    807   "native",
    808   "new",
    809   "null",
    810   "package",
    811   "private",
    812   "protected",
    813   "public",
    814   "return",
    815   "short",
    816   "static",
    817   "super",
    818   "switch",
    819   "synchronized",
    820   "this",
    821   "throw",
    822   "throws",
    823   "transient",
    824   "true",
    825   "try",
    826   "typeof",
    827   "var",
    828   "void",
    829   "volatile",
    830   "while",
    831   "with",
    832   0
    833 };
    834 
    835 
    836 static void CheckInternalizedStrings(const char** strings) {
    837   Isolate* isolate = CcTest::i_isolate();
    838   Factory* factory = isolate->factory();
    839   for (const char* string = *strings; *strings != 0; string = *strings++) {
    840     HandleScope scope(isolate);
    841     Handle<String> a =
    842         isolate->factory()->InternalizeUtf8String(CStrVector(string));
    843     // InternalizeUtf8String may return a failure if a GC is needed.
    844     CHECK(a->IsInternalizedString());
    845     Handle<String> b = factory->InternalizeUtf8String(string);
    846     CHECK_EQ(*b, *a);
    847     CHECK(b->IsUtf8EqualTo(CStrVector(string)));
    848     b = isolate->factory()->InternalizeUtf8String(CStrVector(string));
    849     CHECK_EQ(*b, *a);
    850     CHECK(b->IsUtf8EqualTo(CStrVector(string)));
    851   }
    852 }
    853 
    854 
    855 TEST(StringTable) {
    856   CcTest::InitializeVM();
    857 
    858   v8::HandleScope sc(CcTest::isolate());
    859   CheckInternalizedStrings(not_so_random_string_table);
    860   CheckInternalizedStrings(not_so_random_string_table);
    861 }
    862 
    863 
    864 TEST(FunctionAllocation) {
    865   CcTest::InitializeVM();
    866   Isolate* isolate = CcTest::i_isolate();
    867   Factory* factory = isolate->factory();
    868 
    869   v8::HandleScope sc(CcTest::isolate());
    870   Handle<String> name = factory->InternalizeUtf8String("theFunction");
    871   Handle<JSFunction> function = factory->NewFunction(name);
    872 
    873   Handle<Smi> twenty_three(Smi::FromInt(23), isolate);
    874   Handle<Smi> twenty_four(Smi::FromInt(24), isolate);
    875 
    876   Handle<String> prop_name = factory->InternalizeUtf8String("theSlot");
    877   Handle<JSObject> obj = factory->NewJSObject(function);
    878   JSReceiver::SetProperty(obj, prop_name, twenty_three, SLOPPY).Check();
    879   CHECK_EQ(Smi::FromInt(23),
    880            *Object::GetProperty(obj, prop_name).ToHandleChecked());
    881   // Check that we can add properties to function objects.
    882   JSReceiver::SetProperty(function, prop_name, twenty_four, SLOPPY).Check();
    883   CHECK_EQ(Smi::FromInt(24),
    884            *Object::GetProperty(function, prop_name).ToHandleChecked());
    885 }
    886 
    887 
    888 TEST(ObjectProperties) {
    889   CcTest::InitializeVM();
    890   Isolate* isolate = CcTest::i_isolate();
    891   Factory* factory = isolate->factory();
    892 
    893   v8::HandleScope sc(CcTest::isolate());
    894   Handle<String> object_string(String::cast(CcTest::heap()->Object_string()));
    895   Handle<Object> object = Object::GetProperty(
    896       CcTest::i_isolate()->global_object(), object_string).ToHandleChecked();
    897   Handle<JSFunction> constructor = Handle<JSFunction>::cast(object);
    898   Handle<JSObject> obj = factory->NewJSObject(constructor);
    899   Handle<String> first = factory->InternalizeUtf8String("first");
    900   Handle<String> second = factory->InternalizeUtf8String("second");
    901 
    902   Handle<Smi> one(Smi::FromInt(1), isolate);
    903   Handle<Smi> two(Smi::FromInt(2), isolate);
    904 
    905   // check for empty
    906   CHECK(Just(false) == JSReceiver::HasOwnProperty(obj, first));
    907 
    908   // add first
    909   JSReceiver::SetProperty(obj, first, one, SLOPPY).Check();
    910   CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, first));
    911 
    912   // delete first
    913   CHECK(Just(true) == JSReceiver::DeleteProperty(obj, first, SLOPPY));
    914   CHECK(Just(false) == JSReceiver::HasOwnProperty(obj, first));
    915 
    916   // add first and then second
    917   JSReceiver::SetProperty(obj, first, one, SLOPPY).Check();
    918   JSReceiver::SetProperty(obj, second, two, SLOPPY).Check();
    919   CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, first));
    920   CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, second));
    921 
    922   // delete first and then second
    923   CHECK(Just(true) == JSReceiver::DeleteProperty(obj, first, SLOPPY));
    924   CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, second));
    925   CHECK(Just(true) == JSReceiver::DeleteProperty(obj, second, SLOPPY));
    926   CHECK(Just(false) == JSReceiver::HasOwnProperty(obj, first));
    927   CHECK(Just(false) == JSReceiver::HasOwnProperty(obj, second));
    928 
    929   // add first and then second
    930   JSReceiver::SetProperty(obj, first, one, SLOPPY).Check();
    931   JSReceiver::SetProperty(obj, second, two, SLOPPY).Check();
    932   CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, first));
    933   CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, second));
    934 
    935   // delete second and then first
    936   CHECK(Just(true) == JSReceiver::DeleteProperty(obj, second, SLOPPY));
    937   CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, first));
    938   CHECK(Just(true) == JSReceiver::DeleteProperty(obj, first, SLOPPY));
    939   CHECK(Just(false) == JSReceiver::HasOwnProperty(obj, first));
    940   CHECK(Just(false) == JSReceiver::HasOwnProperty(obj, second));
    941 
    942   // check string and internalized string match
    943   const char* string1 = "fisk";
    944   Handle<String> s1 = factory->NewStringFromAsciiChecked(string1);
    945   JSReceiver::SetProperty(obj, s1, one, SLOPPY).Check();
    946   Handle<String> s1_string = factory->InternalizeUtf8String(string1);
    947   CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, s1_string));
    948 
    949   // check internalized string and string match
    950   const char* string2 = "fugl";
    951   Handle<String> s2_string = factory->InternalizeUtf8String(string2);
    952   JSReceiver::SetProperty(obj, s2_string, one, SLOPPY).Check();
    953   Handle<String> s2 = factory->NewStringFromAsciiChecked(string2);
    954   CHECK(Just(true) == JSReceiver::HasOwnProperty(obj, s2));
    955 }
    956 
    957 
    958 TEST(JSObjectMaps) {
    959   CcTest::InitializeVM();
    960   Isolate* isolate = CcTest::i_isolate();
    961   Factory* factory = isolate->factory();
    962 
    963   v8::HandleScope sc(CcTest::isolate());
    964   Handle<String> name = factory->InternalizeUtf8String("theFunction");
    965   Handle<JSFunction> function = factory->NewFunction(name);
    966 
    967   Handle<String> prop_name = factory->InternalizeUtf8String("theSlot");
    968   Handle<JSObject> obj = factory->NewJSObject(function);
    969   Handle<Map> initial_map(function->initial_map());
    970 
    971   // Set a propery
    972   Handle<Smi> twenty_three(Smi::FromInt(23), isolate);
    973   JSReceiver::SetProperty(obj, prop_name, twenty_three, SLOPPY).Check();
    974   CHECK_EQ(Smi::FromInt(23),
    975            *Object::GetProperty(obj, prop_name).ToHandleChecked());
    976 
    977   // Check the map has changed
    978   CHECK(*initial_map != obj->map());
    979 }
    980 
    981 
    982 TEST(JSArray) {
    983   CcTest::InitializeVM();
    984   Isolate* isolate = CcTest::i_isolate();
    985   Factory* factory = isolate->factory();
    986 
    987   v8::HandleScope sc(CcTest::isolate());
    988   Handle<String> name = factory->InternalizeUtf8String("Array");
    989   Handle<Object> fun_obj = Object::GetProperty(
    990       CcTest::i_isolate()->global_object(), name).ToHandleChecked();
    991   Handle<JSFunction> function = Handle<JSFunction>::cast(fun_obj);
    992 
    993   // Allocate the object.
    994   Handle<Object> element;
    995   Handle<JSObject> object = factory->NewJSObject(function);
    996   Handle<JSArray> array = Handle<JSArray>::cast(object);
    997   // We just initialized the VM, no heap allocation failure yet.
    998   JSArray::Initialize(array, 0);
    999 
   1000   // Set array length to 0.
   1001   JSArray::SetLength(array, 0);
   1002   CHECK_EQ(Smi::FromInt(0), array->length());
   1003   // Must be in fast mode.
   1004   CHECK(array->HasFastSmiOrObjectElements());
   1005 
   1006   // array[length] = name.
   1007   JSReceiver::SetElement(isolate, array, 0, name, SLOPPY).Check();
   1008   CHECK_EQ(Smi::FromInt(1), array->length());
   1009   element = i::Object::GetElement(isolate, array, 0).ToHandleChecked();
   1010   CHECK_EQ(*element, *name);
   1011 
   1012   // Set array length with larger than smi value.
   1013   JSArray::SetLength(array, static_cast<uint32_t>(Smi::kMaxValue) + 1);
   1014 
   1015   uint32_t int_length = 0;
   1016   CHECK(array->length()->ToArrayIndex(&int_length));
   1017   CHECK_EQ(static_cast<uint32_t>(Smi::kMaxValue) + 1, int_length);
   1018   CHECK(array->HasDictionaryElements());  // Must be in slow mode.
   1019 
   1020   // array[length] = name.
   1021   JSReceiver::SetElement(isolate, array, int_length, name, SLOPPY).Check();
   1022   uint32_t new_int_length = 0;
   1023   CHECK(array->length()->ToArrayIndex(&new_int_length));
   1024   CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
   1025   element = Object::GetElement(isolate, array, int_length).ToHandleChecked();
   1026   CHECK_EQ(*element, *name);
   1027   element = Object::GetElement(isolate, array, 0).ToHandleChecked();
   1028   CHECK_EQ(*element, *name);
   1029 }
   1030 
   1031 
   1032 TEST(JSObjectCopy) {
   1033   CcTest::InitializeVM();
   1034   Isolate* isolate = CcTest::i_isolate();
   1035   Factory* factory = isolate->factory();
   1036 
   1037   v8::HandleScope sc(CcTest::isolate());
   1038   Handle<String> object_string(String::cast(CcTest::heap()->Object_string()));
   1039   Handle<Object> object = Object::GetProperty(
   1040       CcTest::i_isolate()->global_object(), object_string).ToHandleChecked();
   1041   Handle<JSFunction> constructor = Handle<JSFunction>::cast(object);
   1042   Handle<JSObject> obj = factory->NewJSObject(constructor);
   1043   Handle<String> first = factory->InternalizeUtf8String("first");
   1044   Handle<String> second = factory->InternalizeUtf8String("second");
   1045 
   1046   Handle<Smi> one(Smi::FromInt(1), isolate);
   1047   Handle<Smi> two(Smi::FromInt(2), isolate);
   1048 
   1049   JSReceiver::SetProperty(obj, first, one, SLOPPY).Check();
   1050   JSReceiver::SetProperty(obj, second, two, SLOPPY).Check();
   1051 
   1052   JSReceiver::SetElement(isolate, obj, 0, first, SLOPPY).Check();
   1053   JSReceiver::SetElement(isolate, obj, 1, second, SLOPPY).Check();
   1054 
   1055   // Make the clone.
   1056   Handle<Object> value1, value2;
   1057   Handle<JSObject> clone = factory->CopyJSObject(obj);
   1058   CHECK(!clone.is_identical_to(obj));
   1059 
   1060   value1 = Object::GetElement(isolate, obj, 0).ToHandleChecked();
   1061   value2 = Object::GetElement(isolate, clone, 0).ToHandleChecked();
   1062   CHECK_EQ(*value1, *value2);
   1063   value1 = Object::GetElement(isolate, obj, 1).ToHandleChecked();
   1064   value2 = Object::GetElement(isolate, clone, 1).ToHandleChecked();
   1065   CHECK_EQ(*value1, *value2);
   1066 
   1067   value1 = Object::GetProperty(obj, first).ToHandleChecked();
   1068   value2 = Object::GetProperty(clone, first).ToHandleChecked();
   1069   CHECK_EQ(*value1, *value2);
   1070   value1 = Object::GetProperty(obj, second).ToHandleChecked();
   1071   value2 = Object::GetProperty(clone, second).ToHandleChecked();
   1072   CHECK_EQ(*value1, *value2);
   1073 
   1074   // Flip the values.
   1075   JSReceiver::SetProperty(clone, first, two, SLOPPY).Check();
   1076   JSReceiver::SetProperty(clone, second, one, SLOPPY).Check();
   1077 
   1078   JSReceiver::SetElement(isolate, clone, 0, second, SLOPPY).Check();
   1079   JSReceiver::SetElement(isolate, clone, 1, first, SLOPPY).Check();
   1080 
   1081   value1 = Object::GetElement(isolate, obj, 1).ToHandleChecked();
   1082   value2 = Object::GetElement(isolate, clone, 0).ToHandleChecked();
   1083   CHECK_EQ(*value1, *value2);
   1084   value1 = Object::GetElement(isolate, obj, 0).ToHandleChecked();
   1085   value2 = Object::GetElement(isolate, clone, 1).ToHandleChecked();
   1086   CHECK_EQ(*value1, *value2);
   1087 
   1088   value1 = Object::GetProperty(obj, second).ToHandleChecked();
   1089   value2 = Object::GetProperty(clone, first).ToHandleChecked();
   1090   CHECK_EQ(*value1, *value2);
   1091   value1 = Object::GetProperty(obj, first).ToHandleChecked();
   1092   value2 = Object::GetProperty(clone, second).ToHandleChecked();
   1093   CHECK_EQ(*value1, *value2);
   1094 }
   1095 
   1096 
   1097 TEST(StringAllocation) {
   1098   CcTest::InitializeVM();
   1099   Isolate* isolate = CcTest::i_isolate();
   1100   Factory* factory = isolate->factory();
   1101 
   1102   const unsigned char chars[] = { 0xe5, 0xa4, 0xa7 };
   1103   for (int length = 0; length < 100; length++) {
   1104     v8::HandleScope scope(CcTest::isolate());
   1105     char* non_one_byte = NewArray<char>(3 * length + 1);
   1106     char* one_byte = NewArray<char>(length + 1);
   1107     non_one_byte[3 * length] = 0;
   1108     one_byte[length] = 0;
   1109     for (int i = 0; i < length; i++) {
   1110       one_byte[i] = 'a';
   1111       non_one_byte[3 * i] = chars[0];
   1112       non_one_byte[3 * i + 1] = chars[1];
   1113       non_one_byte[3 * i + 2] = chars[2];
   1114     }
   1115     Handle<String> non_one_byte_sym = factory->InternalizeUtf8String(
   1116         Vector<const char>(non_one_byte, 3 * length));
   1117     CHECK_EQ(length, non_one_byte_sym->length());
   1118     Handle<String> one_byte_sym =
   1119         factory->InternalizeOneByteString(OneByteVector(one_byte, length));
   1120     CHECK_EQ(length, one_byte_sym->length());
   1121     Handle<String> non_one_byte_str =
   1122         factory->NewStringFromUtf8(Vector<const char>(non_one_byte, 3 * length))
   1123             .ToHandleChecked();
   1124     non_one_byte_str->Hash();
   1125     CHECK_EQ(length, non_one_byte_str->length());
   1126     Handle<String> one_byte_str =
   1127         factory->NewStringFromUtf8(Vector<const char>(one_byte, length))
   1128             .ToHandleChecked();
   1129     one_byte_str->Hash();
   1130     CHECK_EQ(length, one_byte_str->length());
   1131     DeleteArray(non_one_byte);
   1132     DeleteArray(one_byte);
   1133   }
   1134 }
   1135 
   1136 
   1137 static int ObjectsFoundInHeap(Heap* heap, Handle<Object> objs[], int size) {
   1138   // Count the number of objects found in the heap.
   1139   int found_count = 0;
   1140   HeapIterator iterator(heap);
   1141   for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
   1142     for (int i = 0; i < size; i++) {
   1143       if (*objs[i] == obj) {
   1144         found_count++;
   1145       }
   1146     }
   1147   }
   1148   return found_count;
   1149 }
   1150 
   1151 
   1152 TEST(Iteration) {
   1153   CcTest::InitializeVM();
   1154   Isolate* isolate = CcTest::i_isolate();
   1155   Factory* factory = isolate->factory();
   1156   v8::HandleScope scope(CcTest::isolate());
   1157 
   1158   // Array of objects to scan haep for.
   1159   const int objs_count = 6;
   1160   Handle<Object> objs[objs_count];
   1161   int next_objs_index = 0;
   1162 
   1163   // Allocate a JS array to OLD_SPACE and NEW_SPACE
   1164   objs[next_objs_index++] = factory->NewJSArray(10);
   1165   objs[next_objs_index++] =
   1166       factory->NewJSArray(10, FAST_HOLEY_ELEMENTS, Strength::WEAK, TENURED);
   1167 
   1168   // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE
   1169   objs[next_objs_index++] = factory->NewStringFromStaticChars("abcdefghij");
   1170   objs[next_objs_index++] =
   1171       factory->NewStringFromStaticChars("abcdefghij", TENURED);
   1172 
   1173   // Allocate a large string (for large object space).
   1174   int large_size = Page::kMaxRegularHeapObjectSize + 1;
   1175   char* str = new char[large_size];
   1176   for (int i = 0; i < large_size - 1; ++i) str[i] = 'a';
   1177   str[large_size - 1] = '\0';
   1178   objs[next_objs_index++] = factory->NewStringFromAsciiChecked(str, TENURED);
   1179   delete[] str;
   1180 
   1181   // Add a Map object to look for.
   1182   objs[next_objs_index++] = Handle<Map>(HeapObject::cast(*objs[0])->map());
   1183 
   1184   CHECK_EQ(objs_count, next_objs_index);
   1185   CHECK_EQ(objs_count, ObjectsFoundInHeap(CcTest::heap(), objs, objs_count));
   1186 }
   1187 
   1188 
   1189 UNINITIALIZED_TEST(TestCodeFlushing) {
   1190   // If we do not flush code this test is invalid.
   1191   if (!FLAG_flush_code) return;
   1192   i::FLAG_allow_natives_syntax = true;
   1193   i::FLAG_optimize_for_size = false;
   1194   v8::Isolate::CreateParams create_params;
   1195   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   1196   v8::Isolate* isolate = v8::Isolate::New(create_params);
   1197   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   1198   isolate->Enter();
   1199   Factory* factory = i_isolate->factory();
   1200   {
   1201     v8::HandleScope scope(isolate);
   1202     v8::Context::New(isolate)->Enter();
   1203     const char* source =
   1204         "function foo() {"
   1205         "  var x = 42;"
   1206         "  var y = 42;"
   1207         "  var z = x + y;"
   1208         "};"
   1209         "foo()";
   1210     Handle<String> foo_name = factory->InternalizeUtf8String("foo");
   1211 
   1212     // This compile will add the code to the compilation cache.
   1213     {
   1214       v8::HandleScope scope(isolate);
   1215       CompileRun(source);
   1216     }
   1217 
   1218     // Check function is compiled.
   1219     Handle<Object> func_value = Object::GetProperty(i_isolate->global_object(),
   1220                                                     foo_name).ToHandleChecked();
   1221     CHECK(func_value->IsJSFunction());
   1222     Handle<JSFunction> function = Handle<JSFunction>::cast(func_value);
   1223     CHECK(function->shared()->is_compiled());
   1224 
   1225     // The code will survive at least two GCs.
   1226     i_isolate->heap()->CollectAllGarbage();
   1227     i_isolate->heap()->CollectAllGarbage();
   1228     CHECK(function->shared()->is_compiled());
   1229 
   1230     // Simulate several GCs that use full marking.
   1231     const int kAgingThreshold = 6;
   1232     for (int i = 0; i < kAgingThreshold; i++) {
   1233       i_isolate->heap()->CollectAllGarbage();
   1234     }
   1235 
   1236     // foo should no longer be in the compilation cache
   1237     CHECK(!function->shared()->is_compiled() || function->IsOptimized());
   1238     CHECK(!function->is_compiled() || function->IsOptimized());
   1239     // Call foo to get it recompiled.
   1240     CompileRun("foo()");
   1241     CHECK(function->shared()->is_compiled());
   1242     CHECK(function->is_compiled());
   1243   }
   1244   isolate->Exit();
   1245   isolate->Dispose();
   1246 }
   1247 
   1248 
   1249 TEST(TestCodeFlushingPreAged) {
   1250   // If we do not flush code this test is invalid.
   1251   if (!FLAG_flush_code) return;
   1252   i::FLAG_allow_natives_syntax = true;
   1253   i::FLAG_optimize_for_size = true;
   1254   CcTest::InitializeVM();
   1255   Isolate* isolate = CcTest::i_isolate();
   1256   Factory* factory = isolate->factory();
   1257   v8::HandleScope scope(CcTest::isolate());
   1258   const char* source = "function foo() {"
   1259                        "  var x = 42;"
   1260                        "  var y = 42;"
   1261                        "  var z = x + y;"
   1262                        "};"
   1263                        "foo()";
   1264   Handle<String> foo_name = factory->InternalizeUtf8String("foo");
   1265 
   1266   // Compile foo, but don't run it.
   1267   { v8::HandleScope scope(CcTest::isolate());
   1268     CompileRun(source);
   1269   }
   1270 
   1271   // Check function is compiled.
   1272   Handle<Object> func_value =
   1273       Object::GetProperty(isolate->global_object(), foo_name).ToHandleChecked();
   1274   CHECK(func_value->IsJSFunction());
   1275   Handle<JSFunction> function = Handle<JSFunction>::cast(func_value);
   1276   CHECK(function->shared()->is_compiled());
   1277 
   1278   // The code has been run so will survive at least one GC.
   1279   CcTest::heap()->CollectAllGarbage();
   1280   CHECK(function->shared()->is_compiled());
   1281 
   1282   // The code was only run once, so it should be pre-aged and collected on the
   1283   // next GC.
   1284   CcTest::heap()->CollectAllGarbage();
   1285   CHECK(!function->shared()->is_compiled() || function->IsOptimized());
   1286 
   1287   // Execute the function again twice, and ensure it is reset to the young age.
   1288   { v8::HandleScope scope(CcTest::isolate());
   1289     CompileRun("foo();"
   1290                "foo();");
   1291   }
   1292 
   1293   // The code will survive at least two GC now that it is young again.
   1294   CcTest::heap()->CollectAllGarbage();
   1295   CcTest::heap()->CollectAllGarbage();
   1296   CHECK(function->shared()->is_compiled());
   1297 
   1298   // Simulate several GCs that use full marking.
   1299   const int kAgingThreshold = 6;
   1300   for (int i = 0; i < kAgingThreshold; i++) {
   1301     CcTest::heap()->CollectAllGarbage();
   1302   }
   1303 
   1304   // foo should no longer be in the compilation cache
   1305   CHECK(!function->shared()->is_compiled() || function->IsOptimized());
   1306   CHECK(!function->is_compiled() || function->IsOptimized());
   1307   // Call foo to get it recompiled.
   1308   CompileRun("foo()");
   1309   CHECK(function->shared()->is_compiled());
   1310   CHECK(function->is_compiled());
   1311 }
   1312 
   1313 
   1314 TEST(TestCodeFlushingIncremental) {
   1315   // If we do not flush code this test is invalid.
   1316   if (!FLAG_flush_code) return;
   1317   i::FLAG_allow_natives_syntax = true;
   1318   i::FLAG_optimize_for_size = false;
   1319   CcTest::InitializeVM();
   1320   Isolate* isolate = CcTest::i_isolate();
   1321   Factory* factory = isolate->factory();
   1322   v8::HandleScope scope(CcTest::isolate());
   1323   const char* source = "function foo() {"
   1324                        "  var x = 42;"
   1325                        "  var y = 42;"
   1326                        "  var z = x + y;"
   1327                        "};"
   1328                        "foo()";
   1329   Handle<String> foo_name = factory->InternalizeUtf8String("foo");
   1330 
   1331   // This compile will add the code to the compilation cache.
   1332   { v8::HandleScope scope(CcTest::isolate());
   1333     CompileRun(source);
   1334   }
   1335 
   1336   // Check function is compiled.
   1337   Handle<Object> func_value =
   1338       Object::GetProperty(isolate->global_object(), foo_name).ToHandleChecked();
   1339   CHECK(func_value->IsJSFunction());
   1340   Handle<JSFunction> function = Handle<JSFunction>::cast(func_value);
   1341   CHECK(function->shared()->is_compiled());
   1342 
   1343   // The code will survive at least two GCs.
   1344   CcTest::heap()->CollectAllGarbage();
   1345   CcTest::heap()->CollectAllGarbage();
   1346   CHECK(function->shared()->is_compiled());
   1347 
   1348   // Simulate several GCs that use incremental marking.
   1349   const int kAgingThreshold = 6;
   1350   for (int i = 0; i < kAgingThreshold; i++) {
   1351     SimulateIncrementalMarking(CcTest::heap());
   1352     CcTest::heap()->CollectAllGarbage();
   1353   }
   1354   CHECK(!function->shared()->is_compiled() || function->IsOptimized());
   1355   CHECK(!function->is_compiled() || function->IsOptimized());
   1356 
   1357   // This compile will compile the function again.
   1358   { v8::HandleScope scope(CcTest::isolate());
   1359     CompileRun("foo();");
   1360   }
   1361 
   1362   // Simulate several GCs that use incremental marking but make sure
   1363   // the loop breaks once the function is enqueued as a candidate.
   1364   for (int i = 0; i < kAgingThreshold; i++) {
   1365     SimulateIncrementalMarking(CcTest::heap());
   1366     if (!function->next_function_link()->IsUndefined()) break;
   1367     CcTest::heap()->CollectAllGarbage();
   1368   }
   1369 
   1370   // Force optimization while incremental marking is active and while
   1371   // the function is enqueued as a candidate.
   1372   { v8::HandleScope scope(CcTest::isolate());
   1373     CompileRun("%OptimizeFunctionOnNextCall(foo); foo();");
   1374   }
   1375 
   1376   // Simulate one final GC to make sure the candidate queue is sane.
   1377   CcTest::heap()->CollectAllGarbage();
   1378   CHECK(function->shared()->is_compiled() || !function->IsOptimized());
   1379   CHECK(function->is_compiled() || !function->IsOptimized());
   1380 }
   1381 
   1382 
   1383 TEST(TestCodeFlushingIncrementalScavenge) {
   1384   // If we do not flush code this test is invalid.
   1385   if (!FLAG_flush_code) return;
   1386   i::FLAG_allow_natives_syntax = true;
   1387   i::FLAG_optimize_for_size = false;
   1388   CcTest::InitializeVM();
   1389   Isolate* isolate = CcTest::i_isolate();
   1390   Factory* factory = isolate->factory();
   1391   v8::HandleScope scope(CcTest::isolate());
   1392   const char* source = "var foo = function() {"
   1393                        "  var x = 42;"
   1394                        "  var y = 42;"
   1395                        "  var z = x + y;"
   1396                        "};"
   1397                        "foo();"
   1398                        "var bar = function() {"
   1399                        "  var x = 23;"
   1400                        "};"
   1401                        "bar();";
   1402   Handle<String> foo_name = factory->InternalizeUtf8String("foo");
   1403   Handle<String> bar_name = factory->InternalizeUtf8String("bar");
   1404 
   1405   // Perfrom one initial GC to enable code flushing.
   1406   CcTest::heap()->CollectAllGarbage();
   1407 
   1408   // This compile will add the code to the compilation cache.
   1409   { v8::HandleScope scope(CcTest::isolate());
   1410     CompileRun(source);
   1411   }
   1412 
   1413   // Check functions are compiled.
   1414   Handle<Object> func_value =
   1415       Object::GetProperty(isolate->global_object(), foo_name).ToHandleChecked();
   1416   CHECK(func_value->IsJSFunction());
   1417   Handle<JSFunction> function = Handle<JSFunction>::cast(func_value);
   1418   CHECK(function->shared()->is_compiled());
   1419   Handle<Object> func_value2 =
   1420       Object::GetProperty(isolate->global_object(), bar_name).ToHandleChecked();
   1421   CHECK(func_value2->IsJSFunction());
   1422   Handle<JSFunction> function2 = Handle<JSFunction>::cast(func_value2);
   1423   CHECK(function2->shared()->is_compiled());
   1424 
   1425   // Clear references to functions so that one of them can die.
   1426   { v8::HandleScope scope(CcTest::isolate());
   1427     CompileRun("foo = 0; bar = 0;");
   1428   }
   1429 
   1430   // Bump the code age so that flushing is triggered while the function
   1431   // object is still located in new-space.
   1432   const int kAgingThreshold = 6;
   1433   for (int i = 0; i < kAgingThreshold; i++) {
   1434     function->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
   1435     function2->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
   1436   }
   1437 
   1438   // Simulate incremental marking so that the functions are enqueued as
   1439   // code flushing candidates. Then kill one of the functions. Finally
   1440   // perform a scavenge while incremental marking is still running.
   1441   SimulateIncrementalMarking(CcTest::heap());
   1442   *function2.location() = NULL;
   1443   CcTest::heap()->CollectGarbage(NEW_SPACE, "test scavenge while marking");
   1444 
   1445   // Simulate one final GC to make sure the candidate queue is sane.
   1446   CcTest::heap()->CollectAllGarbage();
   1447   CHECK(!function->shared()->is_compiled() || function->IsOptimized());
   1448   CHECK(!function->is_compiled() || function->IsOptimized());
   1449 }
   1450 
   1451 
   1452 TEST(TestCodeFlushingIncrementalAbort) {
   1453   // If we do not flush code this test is invalid.
   1454   if (!FLAG_flush_code) return;
   1455   i::FLAG_allow_natives_syntax = true;
   1456   i::FLAG_optimize_for_size = false;
   1457   CcTest::InitializeVM();
   1458   Isolate* isolate = CcTest::i_isolate();
   1459   Factory* factory = isolate->factory();
   1460   Heap* heap = isolate->heap();
   1461   v8::HandleScope scope(CcTest::isolate());
   1462   const char* source = "function foo() {"
   1463                        "  var x = 42;"
   1464                        "  var y = 42;"
   1465                        "  var z = x + y;"
   1466                        "};"
   1467                        "foo()";
   1468   Handle<String> foo_name = factory->InternalizeUtf8String("foo");
   1469 
   1470   // This compile will add the code to the compilation cache.
   1471   { v8::HandleScope scope(CcTest::isolate());
   1472     CompileRun(source);
   1473   }
   1474 
   1475   // Check function is compiled.
   1476   Handle<Object> func_value =
   1477       Object::GetProperty(isolate->global_object(), foo_name).ToHandleChecked();
   1478   CHECK(func_value->IsJSFunction());
   1479   Handle<JSFunction> function = Handle<JSFunction>::cast(func_value);
   1480   CHECK(function->shared()->is_compiled());
   1481 
   1482   // The code will survive at least two GCs.
   1483   heap->CollectAllGarbage();
   1484   heap->CollectAllGarbage();
   1485   CHECK(function->shared()->is_compiled());
   1486 
   1487   // Bump the code age so that flushing is triggered.
   1488   const int kAgingThreshold = 6;
   1489   for (int i = 0; i < kAgingThreshold; i++) {
   1490     function->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
   1491   }
   1492 
   1493   // Simulate incremental marking so that the function is enqueued as
   1494   // code flushing candidate.
   1495   SimulateIncrementalMarking(heap);
   1496 
   1497   // Enable the debugger and add a breakpoint while incremental marking
   1498   // is running so that incremental marking aborts and code flushing is
   1499   // disabled.
   1500   int position = 0;
   1501   Handle<Object> breakpoint_object(Smi::FromInt(0), isolate);
   1502   EnableDebugger(CcTest::isolate());
   1503   isolate->debug()->SetBreakPoint(function, breakpoint_object, &position);
   1504   isolate->debug()->ClearAllBreakPoints();
   1505   DisableDebugger(CcTest::isolate());
   1506 
   1507   // Force optimization now that code flushing is disabled.
   1508   { v8::HandleScope scope(CcTest::isolate());
   1509     CompileRun("%OptimizeFunctionOnNextCall(foo); foo();");
   1510   }
   1511 
   1512   // Simulate one final GC to make sure the candidate queue is sane.
   1513   heap->CollectAllGarbage();
   1514   CHECK(function->shared()->is_compiled() || !function->IsOptimized());
   1515   CHECK(function->is_compiled() || !function->IsOptimized());
   1516 }
   1517 
   1518 
   1519 TEST(CompilationCacheCachingBehavior) {
   1520   // If we do not flush code, or have the compilation cache turned off, this
   1521   // test is invalid.
   1522   if (!FLAG_flush_code || !FLAG_compilation_cache) {
   1523     return;
   1524   }
   1525   CcTest::InitializeVM();
   1526   Isolate* isolate = CcTest::i_isolate();
   1527   Factory* factory = isolate->factory();
   1528   Heap* heap = isolate->heap();
   1529   CompilationCache* compilation_cache = isolate->compilation_cache();
   1530   LanguageMode language_mode =
   1531       construct_language_mode(FLAG_use_strict, FLAG_use_strong);
   1532 
   1533   v8::HandleScope scope(CcTest::isolate());
   1534   const char* raw_source =
   1535       "function foo() {"
   1536       "  var x = 42;"
   1537       "  var y = 42;"
   1538       "  var z = x + y;"
   1539       "};"
   1540       "foo()";
   1541   Handle<String> source = factory->InternalizeUtf8String(raw_source);
   1542   Handle<Context> native_context = isolate->native_context();
   1543 
   1544   {
   1545     v8::HandleScope scope(CcTest::isolate());
   1546     CompileRun(raw_source);
   1547   }
   1548 
   1549   // On first compilation, only a hash is inserted in the code cache. We can't
   1550   // find that value.
   1551   MaybeHandle<SharedFunctionInfo> info = compilation_cache->LookupScript(
   1552       source, Handle<Object>(), 0, 0,
   1553       v8::ScriptOriginOptions(false, true, false), native_context,
   1554       language_mode);
   1555   CHECK(info.is_null());
   1556 
   1557   {
   1558     v8::HandleScope scope(CcTest::isolate());
   1559     CompileRun(raw_source);
   1560   }
   1561 
   1562   // On second compilation, the hash is replaced by a real cache entry mapping
   1563   // the source to the shared function info containing the code.
   1564   info = compilation_cache->LookupScript(
   1565       source, Handle<Object>(), 0, 0,
   1566       v8::ScriptOriginOptions(false, true, false), native_context,
   1567       language_mode);
   1568   CHECK(!info.is_null());
   1569 
   1570   // Check that the code cache entry survives at least on GC.
   1571   // (Unless --optimize-for-size, in which case it might get collected
   1572   // immediately.)
   1573   if (!FLAG_optimize_for_size) {
   1574     heap->CollectAllGarbage();
   1575     info = compilation_cache->LookupScript(
   1576         source, Handle<Object>(), 0, 0,
   1577         v8::ScriptOriginOptions(false, true, false), native_context,
   1578         language_mode);
   1579     CHECK(!info.is_null());
   1580   }
   1581 
   1582   // Progress code age until it's old and ready for GC.
   1583   while (!info.ToHandleChecked()->code()->IsOld()) {
   1584     // To guarantee progress, we have to MakeOlder with different parities.
   1585     // We can't just use NO_MARKING_PARITY, since e.g. kExecutedOnceCodeAge is
   1586     // always NO_MARKING_PARITY and the code age only progresses if the parity
   1587     // is different.
   1588     info.ToHandleChecked()->code()->MakeOlder(ODD_MARKING_PARITY);
   1589     info.ToHandleChecked()->code()->MakeOlder(EVEN_MARKING_PARITY);
   1590   }
   1591 
   1592   heap->CollectAllGarbage();
   1593   // Ensure code aging cleared the entry from the cache.
   1594   info = compilation_cache->LookupScript(
   1595       source, Handle<Object>(), 0, 0,
   1596       v8::ScriptOriginOptions(false, true, false), native_context,
   1597       language_mode);
   1598   CHECK(info.is_null());
   1599 
   1600   {
   1601     v8::HandleScope scope(CcTest::isolate());
   1602     CompileRun(raw_source);
   1603   }
   1604 
   1605   // On first compilation, only a hash is inserted in the code cache. We can't
   1606   // find that value.
   1607   info = compilation_cache->LookupScript(
   1608       source, Handle<Object>(), 0, 0,
   1609       v8::ScriptOriginOptions(false, true, false), native_context,
   1610       language_mode);
   1611   CHECK(info.is_null());
   1612 
   1613   for (int i = 0; i < CompilationCacheTable::kHashGenerations; i++) {
   1614     compilation_cache->MarkCompactPrologue();
   1615   }
   1616 
   1617   {
   1618     v8::HandleScope scope(CcTest::isolate());
   1619     CompileRun(raw_source);
   1620   }
   1621 
   1622   // If we aged the cache before caching the script, ensure that we didn't cache
   1623   // on next compilation.
   1624   info = compilation_cache->LookupScript(
   1625       source, Handle<Object>(), 0, 0,
   1626       v8::ScriptOriginOptions(false, true, false), native_context,
   1627       language_mode);
   1628   CHECK(info.is_null());
   1629 }
   1630 
   1631 
   1632 static void OptimizeEmptyFunction(const char* name) {
   1633   HandleScope scope(CcTest::i_isolate());
   1634   EmbeddedVector<char, 256> source;
   1635   SNPrintF(source,
   1636            "function %s() { return 0; }"
   1637            "%s(); %s();"
   1638            "%%OptimizeFunctionOnNextCall(%s);"
   1639            "%s();",
   1640            name, name, name, name, name);
   1641   CompileRun(source.start());
   1642 }
   1643 
   1644 
   1645 // Count the number of native contexts in the weak list of native contexts.
   1646 int CountNativeContexts() {
   1647   int count = 0;
   1648   Object* object = CcTest::heap()->native_contexts_list();
   1649   while (!object->IsUndefined()) {
   1650     count++;
   1651     object = Context::cast(object)->get(Context::NEXT_CONTEXT_LINK);
   1652   }
   1653   return count;
   1654 }
   1655 
   1656 
   1657 // Count the number of user functions in the weak list of optimized
   1658 // functions attached to a native context.
   1659 static int CountOptimizedUserFunctions(v8::Local<v8::Context> context) {
   1660   int count = 0;
   1661   Handle<Context> icontext = v8::Utils::OpenHandle(*context);
   1662   Object* object = icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST);
   1663   while (object->IsJSFunction() &&
   1664          !JSFunction::cast(object)->shared()->IsBuiltin()) {
   1665     count++;
   1666     object = JSFunction::cast(object)->next_function_link();
   1667   }
   1668   return count;
   1669 }
   1670 
   1671 
   1672 TEST(TestInternalWeakLists) {
   1673   FLAG_always_opt = false;
   1674   FLAG_allow_natives_syntax = true;
   1675   v8::V8::Initialize();
   1676 
   1677   // Some flags turn Scavenge collections into Mark-sweep collections
   1678   // and hence are incompatible with this test case.
   1679   if (FLAG_gc_global || FLAG_stress_compaction) return;
   1680   FLAG_retain_maps_for_n_gc = 0;
   1681 
   1682   static const int kNumTestContexts = 10;
   1683 
   1684   Isolate* isolate = CcTest::i_isolate();
   1685   Heap* heap = isolate->heap();
   1686   HandleScope scope(isolate);
   1687   v8::Local<v8::Context> ctx[kNumTestContexts];
   1688   if (!isolate->use_crankshaft()) return;
   1689 
   1690   CHECK_EQ(0, CountNativeContexts());
   1691 
   1692   // Create a number of global contests which gets linked together.
   1693   for (int i = 0; i < kNumTestContexts; i++) {
   1694     ctx[i] = v8::Context::New(CcTest::isolate());
   1695 
   1696     // Collect garbage that might have been created by one of the
   1697     // installed extensions.
   1698     isolate->compilation_cache()->Clear();
   1699     heap->CollectAllGarbage();
   1700 
   1701     CHECK_EQ(i + 1, CountNativeContexts());
   1702 
   1703     ctx[i]->Enter();
   1704 
   1705     // Create a handle scope so no function objects get stuck in the outer
   1706     // handle scope.
   1707     HandleScope scope(isolate);
   1708     CHECK_EQ(0, CountOptimizedUserFunctions(ctx[i]));
   1709     OptimizeEmptyFunction("f1");
   1710     CHECK_EQ(1, CountOptimizedUserFunctions(ctx[i]));
   1711     OptimizeEmptyFunction("f2");
   1712     CHECK_EQ(2, CountOptimizedUserFunctions(ctx[i]));
   1713     OptimizeEmptyFunction("f3");
   1714     CHECK_EQ(3, CountOptimizedUserFunctions(ctx[i]));
   1715     OptimizeEmptyFunction("f4");
   1716     CHECK_EQ(4, CountOptimizedUserFunctions(ctx[i]));
   1717     OptimizeEmptyFunction("f5");
   1718     CHECK_EQ(5, CountOptimizedUserFunctions(ctx[i]));
   1719 
   1720     // Remove function f1, and
   1721     CompileRun("f1=null");
   1722 
   1723     // Scavenge treats these references as strong.
   1724     for (int j = 0; j < 10; j++) {
   1725       CcTest::heap()->CollectGarbage(NEW_SPACE);
   1726       CHECK_EQ(5, CountOptimizedUserFunctions(ctx[i]));
   1727     }
   1728 
   1729     // Mark compact handles the weak references.
   1730     isolate->compilation_cache()->Clear();
   1731     heap->CollectAllGarbage();
   1732     CHECK_EQ(4, CountOptimizedUserFunctions(ctx[i]));
   1733 
   1734     // Get rid of f3 and f5 in the same way.
   1735     CompileRun("f3=null");
   1736     for (int j = 0; j < 10; j++) {
   1737       CcTest::heap()->CollectGarbage(NEW_SPACE);
   1738       CHECK_EQ(4, CountOptimizedUserFunctions(ctx[i]));
   1739     }
   1740     CcTest::heap()->CollectAllGarbage();
   1741     CHECK_EQ(3, CountOptimizedUserFunctions(ctx[i]));
   1742     CompileRun("f5=null");
   1743     for (int j = 0; j < 10; j++) {
   1744       CcTest::heap()->CollectGarbage(NEW_SPACE);
   1745       CHECK_EQ(3, CountOptimizedUserFunctions(ctx[i]));
   1746     }
   1747     CcTest::heap()->CollectAllGarbage();
   1748     CHECK_EQ(2, CountOptimizedUserFunctions(ctx[i]));
   1749 
   1750     ctx[i]->Exit();
   1751   }
   1752 
   1753   // Force compilation cache cleanup.
   1754   CcTest::heap()->NotifyContextDisposed(true);
   1755   CcTest::heap()->CollectAllGarbage();
   1756 
   1757   // Dispose the native contexts one by one.
   1758   for (int i = 0; i < kNumTestContexts; i++) {
   1759     // TODO(dcarney): is there a better way to do this?
   1760     i::Object** unsafe = reinterpret_cast<i::Object**>(*ctx[i]);
   1761     *unsafe = CcTest::heap()->undefined_value();
   1762     ctx[i].Clear();
   1763 
   1764     // Scavenge treats these references as strong.
   1765     for (int j = 0; j < 10; j++) {
   1766       CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   1767       CHECK_EQ(kNumTestContexts - i, CountNativeContexts());
   1768     }
   1769 
   1770     // Mark compact handles the weak references.
   1771     CcTest::heap()->CollectAllGarbage();
   1772     CHECK_EQ(kNumTestContexts - i - 1, CountNativeContexts());
   1773   }
   1774 
   1775   CHECK_EQ(0, CountNativeContexts());
   1776 }
   1777 
   1778 
   1779 // Count the number of native contexts in the weak list of native contexts
   1780 // causing a GC after the specified number of elements.
   1781 static int CountNativeContextsWithGC(Isolate* isolate, int n) {
   1782   Heap* heap = isolate->heap();
   1783   int count = 0;
   1784   Handle<Object> object(heap->native_contexts_list(), isolate);
   1785   while (!object->IsUndefined()) {
   1786     count++;
   1787     if (count == n) heap->CollectAllGarbage();
   1788     object =
   1789         Handle<Object>(Context::cast(*object)->get(Context::NEXT_CONTEXT_LINK),
   1790                        isolate);
   1791   }
   1792   return count;
   1793 }
   1794 
   1795 
   1796 // Count the number of user functions in the weak list of optimized
   1797 // functions attached to a native context causing a GC after the
   1798 // specified number of elements.
   1799 static int CountOptimizedUserFunctionsWithGC(v8::Local<v8::Context> context,
   1800                                              int n) {
   1801   int count = 0;
   1802   Handle<Context> icontext = v8::Utils::OpenHandle(*context);
   1803   Isolate* isolate = icontext->GetIsolate();
   1804   Handle<Object> object(icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST),
   1805                         isolate);
   1806   while (object->IsJSFunction() &&
   1807          !Handle<JSFunction>::cast(object)->shared()->IsBuiltin()) {
   1808     count++;
   1809     if (count == n) isolate->heap()->CollectAllGarbage();
   1810     object = Handle<Object>(
   1811         Object::cast(JSFunction::cast(*object)->next_function_link()),
   1812         isolate);
   1813   }
   1814   return count;
   1815 }
   1816 
   1817 
   1818 TEST(TestInternalWeakListsTraverseWithGC) {
   1819   FLAG_always_opt = false;
   1820   FLAG_allow_natives_syntax = true;
   1821   v8::V8::Initialize();
   1822 
   1823   static const int kNumTestContexts = 10;
   1824 
   1825   Isolate* isolate = CcTest::i_isolate();
   1826   HandleScope scope(isolate);
   1827   v8::Local<v8::Context> ctx[kNumTestContexts];
   1828   if (!isolate->use_crankshaft()) return;
   1829 
   1830   CHECK_EQ(0, CountNativeContexts());
   1831 
   1832   // Create an number of contexts and check the length of the weak list both
   1833   // with and without GCs while iterating the list.
   1834   for (int i = 0; i < kNumTestContexts; i++) {
   1835     ctx[i] = v8::Context::New(CcTest::isolate());
   1836     CHECK_EQ(i + 1, CountNativeContexts());
   1837     CHECK_EQ(i + 1, CountNativeContextsWithGC(isolate, i / 2 + 1));
   1838   }
   1839 
   1840   ctx[0]->Enter();
   1841 
   1842   // Compile a number of functions the length of the weak list of optimized
   1843   // functions both with and without GCs while iterating the list.
   1844   CHECK_EQ(0, CountOptimizedUserFunctions(ctx[0]));
   1845   OptimizeEmptyFunction("f1");
   1846   CHECK_EQ(1, CountOptimizedUserFunctions(ctx[0]));
   1847   CHECK_EQ(1, CountOptimizedUserFunctionsWithGC(ctx[0], 1));
   1848   OptimizeEmptyFunction("f2");
   1849   CHECK_EQ(2, CountOptimizedUserFunctions(ctx[0]));
   1850   CHECK_EQ(2, CountOptimizedUserFunctionsWithGC(ctx[0], 1));
   1851   OptimizeEmptyFunction("f3");
   1852   CHECK_EQ(3, CountOptimizedUserFunctions(ctx[0]));
   1853   CHECK_EQ(3, CountOptimizedUserFunctionsWithGC(ctx[0], 1));
   1854   OptimizeEmptyFunction("f4");
   1855   CHECK_EQ(4, CountOptimizedUserFunctions(ctx[0]));
   1856   CHECK_EQ(4, CountOptimizedUserFunctionsWithGC(ctx[0], 2));
   1857   OptimizeEmptyFunction("f5");
   1858   CHECK_EQ(5, CountOptimizedUserFunctions(ctx[0]));
   1859   CHECK_EQ(5, CountOptimizedUserFunctionsWithGC(ctx[0], 4));
   1860 
   1861   ctx[0]->Exit();
   1862 }
   1863 
   1864 
   1865 TEST(TestSizeOfRegExpCode) {
   1866   if (!FLAG_regexp_optimization) return;
   1867 
   1868   v8::V8::Initialize();
   1869 
   1870   Isolate* isolate = CcTest::i_isolate();
   1871   HandleScope scope(isolate);
   1872 
   1873   LocalContext context;
   1874 
   1875   // Adjust source below and this check to match
   1876   // RegExpImple::kRegExpTooLargeToOptimize.
   1877   CHECK_EQ(i::RegExpImpl::kRegExpTooLargeToOptimize, 20 * KB);
   1878 
   1879   // Compile a regexp that is much larger if we are using regexp optimizations.
   1880   CompileRun(
   1881       "var reg_exp_source = '(?:a|bc|def|ghij|klmno|pqrstu)';"
   1882       "var half_size_reg_exp;"
   1883       "while (reg_exp_source.length < 20 * 1024) {"
   1884       "  half_size_reg_exp = reg_exp_source;"
   1885       "  reg_exp_source = reg_exp_source + reg_exp_source;"
   1886       "}"
   1887       // Flatten string.
   1888       "reg_exp_source.match(/f/);");
   1889 
   1890   // Get initial heap size after several full GCs, which will stabilize
   1891   // the heap size and return with sweeping finished completely.
   1892   CcTest::heap()->CollectAllGarbage();
   1893   CcTest::heap()->CollectAllGarbage();
   1894   CcTest::heap()->CollectAllGarbage();
   1895   CcTest::heap()->CollectAllGarbage();
   1896   CcTest::heap()->CollectAllGarbage();
   1897   MarkCompactCollector* collector = CcTest::heap()->mark_compact_collector();
   1898   if (collector->sweeping_in_progress()) {
   1899     collector->EnsureSweepingCompleted();
   1900   }
   1901   int initial_size = static_cast<int>(CcTest::heap()->SizeOfObjects());
   1902 
   1903   CompileRun("'foo'.match(reg_exp_source);");
   1904   CcTest::heap()->CollectAllGarbage();
   1905   int size_with_regexp = static_cast<int>(CcTest::heap()->SizeOfObjects());
   1906 
   1907   CompileRun("'foo'.match(half_size_reg_exp);");
   1908   CcTest::heap()->CollectAllGarbage();
   1909   int size_with_optimized_regexp =
   1910       static_cast<int>(CcTest::heap()->SizeOfObjects());
   1911 
   1912   int size_of_regexp_code = size_with_regexp - initial_size;
   1913 
   1914   // On some platforms the debug-code flag causes huge amounts of regexp code
   1915   // to be emitted, breaking this test.
   1916   if (!FLAG_debug_code) {
   1917     CHECK_LE(size_of_regexp_code, 1 * MB);
   1918   }
   1919 
   1920   // Small regexp is half the size, but compiles to more than twice the code
   1921   // due to the optimization steps.
   1922   CHECK_GE(size_with_optimized_regexp,
   1923            size_with_regexp + size_of_regexp_code * 2);
   1924 }
   1925 
   1926 
   1927 HEAP_TEST(TestSizeOfObjects) {
   1928   v8::V8::Initialize();
   1929 
   1930   // Get initial heap size after several full GCs, which will stabilize
   1931   // the heap size and return with sweeping finished completely.
   1932   CcTest::heap()->CollectAllGarbage();
   1933   CcTest::heap()->CollectAllGarbage();
   1934   CcTest::heap()->CollectAllGarbage();
   1935   CcTest::heap()->CollectAllGarbage();
   1936   CcTest::heap()->CollectAllGarbage();
   1937   MarkCompactCollector* collector = CcTest::heap()->mark_compact_collector();
   1938   if (collector->sweeping_in_progress()) {
   1939     collector->EnsureSweepingCompleted();
   1940   }
   1941   int initial_size = static_cast<int>(CcTest::heap()->SizeOfObjects());
   1942 
   1943   {
   1944     // Allocate objects on several different old-space pages so that
   1945     // concurrent sweeper threads will be busy sweeping the old space on
   1946     // subsequent GC runs.
   1947     AlwaysAllocateScope always_allocate(CcTest::i_isolate());
   1948     int filler_size = static_cast<int>(FixedArray::SizeFor(8192));
   1949     for (int i = 1; i <= 100; i++) {
   1950       CcTest::heap()->AllocateFixedArray(8192, TENURED).ToObjectChecked();
   1951       CHECK_EQ(initial_size + i * filler_size,
   1952                static_cast<int>(CcTest::heap()->SizeOfObjects()));
   1953     }
   1954   }
   1955 
   1956   // The heap size should go back to initial size after a full GC, even
   1957   // though sweeping didn't finish yet.
   1958   CcTest::heap()->CollectAllGarbage();
   1959 
   1960   // Normally sweeping would not be complete here, but no guarantees.
   1961 
   1962   CHECK_EQ(initial_size, static_cast<int>(CcTest::heap()->SizeOfObjects()));
   1963 
   1964   // Waiting for sweeper threads should not change heap size.
   1965   if (collector->sweeping_in_progress()) {
   1966     collector->EnsureSweepingCompleted();
   1967   }
   1968   CHECK_EQ(initial_size, static_cast<int>(CcTest::heap()->SizeOfObjects()));
   1969 }
   1970 
   1971 
   1972 TEST(TestAlignmentCalculations) {
   1973   // Maximum fill amounts are consistent.
   1974   int maximum_double_misalignment = kDoubleSize - kPointerSize;
   1975   int maximum_simd128_misalignment = kSimd128Size - kPointerSize;
   1976   int max_word_fill = Heap::GetMaximumFillToAlign(kWordAligned);
   1977   CHECK_EQ(0, max_word_fill);
   1978   int max_double_fill = Heap::GetMaximumFillToAlign(kDoubleAligned);
   1979   CHECK_EQ(maximum_double_misalignment, max_double_fill);
   1980   int max_double_unaligned_fill = Heap::GetMaximumFillToAlign(kDoubleUnaligned);
   1981   CHECK_EQ(maximum_double_misalignment, max_double_unaligned_fill);
   1982   int max_simd128_unaligned_fill =
   1983       Heap::GetMaximumFillToAlign(kSimd128Unaligned);
   1984   CHECK_EQ(maximum_simd128_misalignment, max_simd128_unaligned_fill);
   1985 
   1986   Address base = static_cast<Address>(NULL);
   1987   int fill = 0;
   1988 
   1989   // Word alignment never requires fill.
   1990   fill = Heap::GetFillToAlign(base, kWordAligned);
   1991   CHECK_EQ(0, fill);
   1992   fill = Heap::GetFillToAlign(base + kPointerSize, kWordAligned);
   1993   CHECK_EQ(0, fill);
   1994 
   1995   // No fill is required when address is double aligned.
   1996   fill = Heap::GetFillToAlign(base, kDoubleAligned);
   1997   CHECK_EQ(0, fill);
   1998   // Fill is required if address is not double aligned.
   1999   fill = Heap::GetFillToAlign(base + kPointerSize, kDoubleAligned);
   2000   CHECK_EQ(maximum_double_misalignment, fill);
   2001   // kDoubleUnaligned has the opposite fill amounts.
   2002   fill = Heap::GetFillToAlign(base, kDoubleUnaligned);
   2003   CHECK_EQ(maximum_double_misalignment, fill);
   2004   fill = Heap::GetFillToAlign(base + kPointerSize, kDoubleUnaligned);
   2005   CHECK_EQ(0, fill);
   2006 
   2007   // 128 bit SIMD types have 2 or 4 possible alignments, depending on platform.
   2008   fill = Heap::GetFillToAlign(base, kSimd128Unaligned);
   2009   CHECK_EQ((3 * kPointerSize) & kSimd128AlignmentMask, fill);
   2010   fill = Heap::GetFillToAlign(base + kPointerSize, kSimd128Unaligned);
   2011   CHECK_EQ((2 * kPointerSize) & kSimd128AlignmentMask, fill);
   2012   fill = Heap::GetFillToAlign(base + 2 * kPointerSize, kSimd128Unaligned);
   2013   CHECK_EQ(kPointerSize, fill);
   2014   fill = Heap::GetFillToAlign(base + 3 * kPointerSize, kSimd128Unaligned);
   2015   CHECK_EQ(0, fill);
   2016 }
   2017 
   2018 
   2019 static HeapObject* NewSpaceAllocateAligned(int size,
   2020                                            AllocationAlignment alignment) {
   2021   Heap* heap = CcTest::heap();
   2022   AllocationResult allocation =
   2023       heap->new_space()->AllocateRawAligned(size, alignment);
   2024   HeapObject* obj = NULL;
   2025   allocation.To(&obj);
   2026   heap->CreateFillerObjectAt(obj->address(), size);
   2027   return obj;
   2028 }
   2029 
   2030 
   2031 // Get new space allocation into the desired alignment.
   2032 static Address AlignNewSpace(AllocationAlignment alignment, int offset) {
   2033   Address* top_addr = CcTest::heap()->new_space()->allocation_top_address();
   2034   int fill = Heap::GetFillToAlign(*top_addr, alignment);
   2035   if (fill) {
   2036     NewSpaceAllocateAligned(fill + offset, kWordAligned);
   2037   }
   2038   return *top_addr;
   2039 }
   2040 
   2041 
   2042 TEST(TestAlignedAllocation) {
   2043   // Double misalignment is 4 on 32-bit platforms, 0 on 64-bit ones.
   2044   const intptr_t double_misalignment = kDoubleSize - kPointerSize;
   2045   Address* top_addr = CcTest::heap()->new_space()->allocation_top_address();
   2046   Address start;
   2047   HeapObject* obj;
   2048   HeapObject* filler;
   2049   if (double_misalignment) {
   2050     // Allocate a pointer sized object that must be double aligned at an
   2051     // aligned address.
   2052     start = AlignNewSpace(kDoubleAligned, 0);
   2053     obj = NewSpaceAllocateAligned(kPointerSize, kDoubleAligned);
   2054     CHECK(IsAddressAligned(obj->address(), kDoubleAlignment));
   2055     // There is no filler.
   2056     CHECK_EQ(kPointerSize, *top_addr - start);
   2057 
   2058     // Allocate a second pointer sized object that must be double aligned at an
   2059     // unaligned address.
   2060     start = AlignNewSpace(kDoubleAligned, kPointerSize);
   2061     obj = NewSpaceAllocateAligned(kPointerSize, kDoubleAligned);
   2062     CHECK(IsAddressAligned(obj->address(), kDoubleAlignment));
   2063     // There is a filler object before the object.
   2064     filler = HeapObject::FromAddress(start);
   2065     CHECK(obj != filler && filler->IsFiller() &&
   2066           filler->Size() == kPointerSize);
   2067     CHECK_EQ(kPointerSize + double_misalignment, *top_addr - start);
   2068 
   2069     // Similarly for kDoubleUnaligned.
   2070     start = AlignNewSpace(kDoubleUnaligned, 0);
   2071     obj = NewSpaceAllocateAligned(kPointerSize, kDoubleUnaligned);
   2072     CHECK(IsAddressAligned(obj->address(), kDoubleAlignment, kPointerSize));
   2073     CHECK_EQ(kPointerSize, *top_addr - start);
   2074     start = AlignNewSpace(kDoubleUnaligned, kPointerSize);
   2075     obj = NewSpaceAllocateAligned(kPointerSize, kDoubleUnaligned);
   2076     CHECK(IsAddressAligned(obj->address(), kDoubleAlignment, kPointerSize));
   2077     // There is a filler object before the object.
   2078     filler = HeapObject::FromAddress(start);
   2079     CHECK(obj != filler && filler->IsFiller() &&
   2080           filler->Size() == kPointerSize);
   2081     CHECK_EQ(kPointerSize + double_misalignment, *top_addr - start);
   2082   }
   2083 
   2084   // Now test SIMD alignment. There are 2 or 4 possible alignments, depending
   2085   // on platform.
   2086   start = AlignNewSpace(kSimd128Unaligned, 0);
   2087   obj = NewSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
   2088   CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
   2089   // There is no filler.
   2090   CHECK_EQ(kPointerSize, *top_addr - start);
   2091   start = AlignNewSpace(kSimd128Unaligned, kPointerSize);
   2092   obj = NewSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
   2093   CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
   2094   // There is a filler object before the object.
   2095   filler = HeapObject::FromAddress(start);
   2096   CHECK(obj != filler && filler->IsFiller() &&
   2097         filler->Size() == kSimd128Size - kPointerSize);
   2098   CHECK_EQ(kPointerSize + kSimd128Size - kPointerSize, *top_addr - start);
   2099 
   2100   if (double_misalignment) {
   2101     // Test the 2 other alignments possible on 32 bit platforms.
   2102     start = AlignNewSpace(kSimd128Unaligned, 2 * kPointerSize);
   2103     obj = NewSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
   2104     CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
   2105     // There is a filler object before the object.
   2106     filler = HeapObject::FromAddress(start);
   2107     CHECK(obj != filler && filler->IsFiller() &&
   2108           filler->Size() == 2 * kPointerSize);
   2109     CHECK_EQ(kPointerSize + 2 * kPointerSize, *top_addr - start);
   2110     start = AlignNewSpace(kSimd128Unaligned, 3 * kPointerSize);
   2111     obj = NewSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
   2112     CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
   2113     // There is a filler object before the object.
   2114     filler = HeapObject::FromAddress(start);
   2115     CHECK(obj != filler && filler->IsFiller() &&
   2116           filler->Size() == kPointerSize);
   2117     CHECK_EQ(kPointerSize + kPointerSize, *top_addr - start);
   2118   }
   2119 }
   2120 
   2121 
   2122 static HeapObject* OldSpaceAllocateAligned(int size,
   2123                                            AllocationAlignment alignment) {
   2124   Heap* heap = CcTest::heap();
   2125   AllocationResult allocation =
   2126       heap->old_space()->AllocateRawAligned(size, alignment);
   2127   HeapObject* obj = NULL;
   2128   allocation.To(&obj);
   2129   heap->CreateFillerObjectAt(obj->address(), size);
   2130   return obj;
   2131 }
   2132 
   2133 
   2134 // Get old space allocation into the desired alignment.
   2135 static Address AlignOldSpace(AllocationAlignment alignment, int offset) {
   2136   Address* top_addr = CcTest::heap()->old_space()->allocation_top_address();
   2137   int fill = Heap::GetFillToAlign(*top_addr, alignment);
   2138   int allocation = fill + offset;
   2139   if (allocation) {
   2140     OldSpaceAllocateAligned(allocation, kWordAligned);
   2141   }
   2142   Address top = *top_addr;
   2143   // Now force the remaining allocation onto the free list.
   2144   CcTest::heap()->old_space()->EmptyAllocationInfo();
   2145   return top;
   2146 }
   2147 
   2148 
   2149 // Test the case where allocation must be done from the free list, so filler
   2150 // may precede or follow the object.
   2151 TEST(TestAlignedOverAllocation) {
   2152   // Double misalignment is 4 on 32-bit platforms, 0 on 64-bit ones.
   2153   const intptr_t double_misalignment = kDoubleSize - kPointerSize;
   2154   Address start;
   2155   HeapObject* obj;
   2156   HeapObject* filler1;
   2157   HeapObject* filler2;
   2158   if (double_misalignment) {
   2159     start = AlignOldSpace(kDoubleAligned, 0);
   2160     obj = OldSpaceAllocateAligned(kPointerSize, kDoubleAligned);
   2161     // The object is aligned, and a filler object is created after.
   2162     CHECK(IsAddressAligned(obj->address(), kDoubleAlignment));
   2163     filler1 = HeapObject::FromAddress(start + kPointerSize);
   2164     CHECK(obj != filler1 && filler1->IsFiller() &&
   2165           filler1->Size() == kPointerSize);
   2166     // Try the opposite alignment case.
   2167     start = AlignOldSpace(kDoubleAligned, kPointerSize);
   2168     obj = OldSpaceAllocateAligned(kPointerSize, kDoubleAligned);
   2169     CHECK(IsAddressAligned(obj->address(), kDoubleAlignment));
   2170     filler1 = HeapObject::FromAddress(start);
   2171     CHECK(obj != filler1);
   2172     CHECK(filler1->IsFiller());
   2173     CHECK(filler1->Size() == kPointerSize);
   2174     CHECK(obj != filler1 && filler1->IsFiller() &&
   2175           filler1->Size() == kPointerSize);
   2176 
   2177     // Similarly for kDoubleUnaligned.
   2178     start = AlignOldSpace(kDoubleUnaligned, 0);
   2179     obj = OldSpaceAllocateAligned(kPointerSize, kDoubleUnaligned);
   2180     // The object is aligned, and a filler object is created after.
   2181     CHECK(IsAddressAligned(obj->address(), kDoubleAlignment, kPointerSize));
   2182     filler1 = HeapObject::FromAddress(start + kPointerSize);
   2183     CHECK(obj != filler1 && filler1->IsFiller() &&
   2184           filler1->Size() == kPointerSize);
   2185     // Try the opposite alignment case.
   2186     start = AlignOldSpace(kDoubleUnaligned, kPointerSize);
   2187     obj = OldSpaceAllocateAligned(kPointerSize, kDoubleUnaligned);
   2188     CHECK(IsAddressAligned(obj->address(), kDoubleAlignment, kPointerSize));
   2189     filler1 = HeapObject::FromAddress(start);
   2190     CHECK(obj != filler1 && filler1->IsFiller() &&
   2191           filler1->Size() == kPointerSize);
   2192   }
   2193 
   2194   // Now test SIMD alignment. There are 2 or 4 possible alignments, depending
   2195   // on platform.
   2196   start = AlignOldSpace(kSimd128Unaligned, 0);
   2197   obj = OldSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
   2198   CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
   2199   // There is a filler object after the object.
   2200   filler1 = HeapObject::FromAddress(start + kPointerSize);
   2201   CHECK(obj != filler1 && filler1->IsFiller() &&
   2202         filler1->Size() == kSimd128Size - kPointerSize);
   2203   start = AlignOldSpace(kSimd128Unaligned, kPointerSize);
   2204   obj = OldSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
   2205   CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
   2206   // There is a filler object before the object.
   2207   filler1 = HeapObject::FromAddress(start);
   2208   CHECK(obj != filler1 && filler1->IsFiller() &&
   2209         filler1->Size() == kSimd128Size - kPointerSize);
   2210 
   2211   if (double_misalignment) {
   2212     // Test the 2 other alignments possible on 32 bit platforms.
   2213     start = AlignOldSpace(kSimd128Unaligned, 2 * kPointerSize);
   2214     obj = OldSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
   2215     CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
   2216     // There are filler objects before and after the object.
   2217     filler1 = HeapObject::FromAddress(start);
   2218     CHECK(obj != filler1 && filler1->IsFiller() &&
   2219           filler1->Size() == 2 * kPointerSize);
   2220     filler2 = HeapObject::FromAddress(start + 3 * kPointerSize);
   2221     CHECK(obj != filler2 && filler2->IsFiller() &&
   2222           filler2->Size() == kPointerSize);
   2223     start = AlignOldSpace(kSimd128Unaligned, 3 * kPointerSize);
   2224     obj = OldSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
   2225     CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
   2226     // There are filler objects before and after the object.
   2227     filler1 = HeapObject::FromAddress(start);
   2228     CHECK(obj != filler1 && filler1->IsFiller() &&
   2229           filler1->Size() == kPointerSize);
   2230     filler2 = HeapObject::FromAddress(start + 2 * kPointerSize);
   2231     CHECK(obj != filler2 && filler2->IsFiller() &&
   2232           filler2->Size() == 2 * kPointerSize);
   2233   }
   2234 }
   2235 
   2236 
   2237 TEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
   2238   CcTest::InitializeVM();
   2239   HeapIterator iterator(CcTest::heap());
   2240   intptr_t size_of_objects_1 = CcTest::heap()->SizeOfObjects();
   2241   intptr_t size_of_objects_2 = 0;
   2242   for (HeapObject* obj = iterator.next();
   2243        obj != NULL;
   2244        obj = iterator.next()) {
   2245     if (!obj->IsFreeSpace()) {
   2246       size_of_objects_2 += obj->Size();
   2247     }
   2248   }
   2249   // Delta must be within 5% of the larger result.
   2250   // TODO(gc): Tighten this up by distinguishing between byte
   2251   // arrays that are real and those that merely mark free space
   2252   // on the heap.
   2253   if (size_of_objects_1 > size_of_objects_2) {
   2254     intptr_t delta = size_of_objects_1 - size_of_objects_2;
   2255     PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, "
   2256            "Iterator: %" V8_PTR_PREFIX "d, "
   2257            "delta: %" V8_PTR_PREFIX "d\n",
   2258            size_of_objects_1, size_of_objects_2, delta);
   2259     CHECK_GT(size_of_objects_1 / 20, delta);
   2260   } else {
   2261     intptr_t delta = size_of_objects_2 - size_of_objects_1;
   2262     PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, "
   2263            "Iterator: %" V8_PTR_PREFIX "d, "
   2264            "delta: %" V8_PTR_PREFIX "d\n",
   2265            size_of_objects_1, size_of_objects_2, delta);
   2266     CHECK_GT(size_of_objects_2 / 20, delta);
   2267   }
   2268 }
   2269 
   2270 
   2271 static void FillUpNewSpace(NewSpace* new_space) {
   2272   // Fill up new space to the point that it is completely full. Make sure
   2273   // that the scavenger does not undo the filling.
   2274   Heap* heap = new_space->heap();
   2275   Isolate* isolate = heap->isolate();
   2276   Factory* factory = isolate->factory();
   2277   HandleScope scope(isolate);
   2278   AlwaysAllocateScope always_allocate(isolate);
   2279   intptr_t available = new_space->Capacity() - new_space->Size();
   2280   intptr_t number_of_fillers = (available / FixedArray::SizeFor(32)) - 1;
   2281   for (intptr_t i = 0; i < number_of_fillers; i++) {
   2282     CHECK(heap->InNewSpace(*factory->NewFixedArray(32, NOT_TENURED)));
   2283   }
   2284 }
   2285 
   2286 
   2287 TEST(GrowAndShrinkNewSpace) {
   2288   CcTest::InitializeVM();
   2289   Heap* heap = CcTest::heap();
   2290   NewSpace* new_space = heap->new_space();
   2291 
   2292   if (heap->ReservedSemiSpaceSize() == heap->InitialSemiSpaceSize() ||
   2293       heap->MaxSemiSpaceSize() == heap->InitialSemiSpaceSize()) {
   2294     // The max size cannot exceed the reserved size, since semispaces must be
   2295     // always within the reserved space.  We can't test new space growing and
   2296     // shrinking if the reserved size is the same as the minimum (initial) size.
   2297     return;
   2298   }
   2299 
   2300   // Explicitly growing should double the space capacity.
   2301   intptr_t old_capacity, new_capacity;
   2302   old_capacity = new_space->TotalCapacity();
   2303   new_space->Grow();
   2304   new_capacity = new_space->TotalCapacity();
   2305   CHECK(2 * old_capacity == new_capacity);
   2306 
   2307   old_capacity = new_space->TotalCapacity();
   2308   FillUpNewSpace(new_space);
   2309   new_capacity = new_space->TotalCapacity();
   2310   CHECK(old_capacity == new_capacity);
   2311 
   2312   // Explicitly shrinking should not affect space capacity.
   2313   old_capacity = new_space->TotalCapacity();
   2314   new_space->Shrink();
   2315   new_capacity = new_space->TotalCapacity();
   2316   CHECK(old_capacity == new_capacity);
   2317 
   2318   // Let the scavenger empty the new space.
   2319   heap->CollectGarbage(NEW_SPACE);
   2320   CHECK_LE(new_space->Size(), old_capacity);
   2321 
   2322   // Explicitly shrinking should halve the space capacity.
   2323   old_capacity = new_space->TotalCapacity();
   2324   new_space->Shrink();
   2325   new_capacity = new_space->TotalCapacity();
   2326   CHECK(old_capacity == 2 * new_capacity);
   2327 
   2328   // Consecutive shrinking should not affect space capacity.
   2329   old_capacity = new_space->TotalCapacity();
   2330   new_space->Shrink();
   2331   new_space->Shrink();
   2332   new_space->Shrink();
   2333   new_capacity = new_space->TotalCapacity();
   2334   CHECK(old_capacity == new_capacity);
   2335 }
   2336 
   2337 
   2338 TEST(CollectingAllAvailableGarbageShrinksNewSpace) {
   2339   CcTest::InitializeVM();
   2340   Heap* heap = CcTest::heap();
   2341   if (heap->ReservedSemiSpaceSize() == heap->InitialSemiSpaceSize() ||
   2342       heap->MaxSemiSpaceSize() == heap->InitialSemiSpaceSize()) {
   2343     // The max size cannot exceed the reserved size, since semispaces must be
   2344     // always within the reserved space.  We can't test new space growing and
   2345     // shrinking if the reserved size is the same as the minimum (initial) size.
   2346     return;
   2347   }
   2348 
   2349   v8::HandleScope scope(CcTest::isolate());
   2350   NewSpace* new_space = heap->new_space();
   2351   intptr_t old_capacity, new_capacity;
   2352   old_capacity = new_space->TotalCapacity();
   2353   new_space->Grow();
   2354   new_capacity = new_space->TotalCapacity();
   2355   CHECK(2 * old_capacity == new_capacity);
   2356   FillUpNewSpace(new_space);
   2357   heap->CollectAllAvailableGarbage();
   2358   new_capacity = new_space->TotalCapacity();
   2359   CHECK(old_capacity == new_capacity);
   2360 }
   2361 
   2362 
   2363 static int NumberOfGlobalObjects() {
   2364   int count = 0;
   2365   HeapIterator iterator(CcTest::heap());
   2366   for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
   2367     if (obj->IsJSGlobalObject()) count++;
   2368   }
   2369   return count;
   2370 }
   2371 
   2372 
   2373 // Test that we don't embed maps from foreign contexts into
   2374 // optimized code.
   2375 TEST(LeakNativeContextViaMap) {
   2376   i::FLAG_allow_natives_syntax = true;
   2377   v8::Isolate* isolate = CcTest::isolate();
   2378   v8::HandleScope outer_scope(isolate);
   2379   v8::Persistent<v8::Context> ctx1p;
   2380   v8::Persistent<v8::Context> ctx2p;
   2381   {
   2382     v8::HandleScope scope(isolate);
   2383     ctx1p.Reset(isolate, v8::Context::New(isolate));
   2384     ctx2p.Reset(isolate, v8::Context::New(isolate));
   2385     v8::Local<v8::Context>::New(isolate, ctx1p)->Enter();
   2386   }
   2387 
   2388   CcTest::heap()->CollectAllAvailableGarbage();
   2389   CHECK_EQ(2, NumberOfGlobalObjects());
   2390 
   2391   {
   2392     v8::HandleScope inner_scope(isolate);
   2393     CompileRun("var v = {x: 42}");
   2394     v8::Local<v8::Context> ctx1 = v8::Local<v8::Context>::New(isolate, ctx1p);
   2395     v8::Local<v8::Context> ctx2 = v8::Local<v8::Context>::New(isolate, ctx2p);
   2396     v8::Local<v8::Value> v =
   2397         ctx1->Global()->Get(ctx1, v8_str("v")).ToLocalChecked();
   2398     ctx2->Enter();
   2399     CHECK(ctx2->Global()->Set(ctx2, v8_str("o"), v).FromJust());
   2400     v8::Local<v8::Value> res = CompileRun(
   2401         "function f() { return o.x; }"
   2402         "for (var i = 0; i < 10; ++i) f();"
   2403         "%OptimizeFunctionOnNextCall(f);"
   2404         "f();");
   2405     CHECK_EQ(42, res->Int32Value(ctx2).FromJust());
   2406     CHECK(ctx2->Global()
   2407               ->Set(ctx2, v8_str("o"), v8::Int32::New(isolate, 0))
   2408               .FromJust());
   2409     ctx2->Exit();
   2410     v8::Local<v8::Context>::New(isolate, ctx1)->Exit();
   2411     ctx1p.Reset();
   2412     isolate->ContextDisposedNotification();
   2413   }
   2414   CcTest::heap()->CollectAllAvailableGarbage();
   2415   CHECK_EQ(1, NumberOfGlobalObjects());
   2416   ctx2p.Reset();
   2417   CcTest::heap()->CollectAllAvailableGarbage();
   2418   CHECK_EQ(0, NumberOfGlobalObjects());
   2419 }
   2420 
   2421 
   2422 // Test that we don't embed functions from foreign contexts into
   2423 // optimized code.
   2424 TEST(LeakNativeContextViaFunction) {
   2425   i::FLAG_allow_natives_syntax = true;
   2426   v8::Isolate* isolate = CcTest::isolate();
   2427   v8::HandleScope outer_scope(isolate);
   2428   v8::Persistent<v8::Context> ctx1p;
   2429   v8::Persistent<v8::Context> ctx2p;
   2430   {
   2431     v8::HandleScope scope(isolate);
   2432     ctx1p.Reset(isolate, v8::Context::New(isolate));
   2433     ctx2p.Reset(isolate, v8::Context::New(isolate));
   2434     v8::Local<v8::Context>::New(isolate, ctx1p)->Enter();
   2435   }
   2436 
   2437   CcTest::heap()->CollectAllAvailableGarbage();
   2438   CHECK_EQ(2, NumberOfGlobalObjects());
   2439 
   2440   {
   2441     v8::HandleScope inner_scope(isolate);
   2442     CompileRun("var v = function() { return 42; }");
   2443     v8::Local<v8::Context> ctx1 = v8::Local<v8::Context>::New(isolate, ctx1p);
   2444     v8::Local<v8::Context> ctx2 = v8::Local<v8::Context>::New(isolate, ctx2p);
   2445     v8::Local<v8::Value> v =
   2446         ctx1->Global()->Get(ctx1, v8_str("v")).ToLocalChecked();
   2447     ctx2->Enter();
   2448     CHECK(ctx2->Global()->Set(ctx2, v8_str("o"), v).FromJust());
   2449     v8::Local<v8::Value> res = CompileRun(
   2450         "function f(x) { return x(); }"
   2451         "for (var i = 0; i < 10; ++i) f(o);"
   2452         "%OptimizeFunctionOnNextCall(f);"
   2453         "f(o);");
   2454     CHECK_EQ(42, res->Int32Value(ctx2).FromJust());
   2455     CHECK(ctx2->Global()
   2456               ->Set(ctx2, v8_str("o"), v8::Int32::New(isolate, 0))
   2457               .FromJust());
   2458     ctx2->Exit();
   2459     ctx1->Exit();
   2460     ctx1p.Reset();
   2461     isolate->ContextDisposedNotification();
   2462   }
   2463   CcTest::heap()->CollectAllAvailableGarbage();
   2464   CHECK_EQ(1, NumberOfGlobalObjects());
   2465   ctx2p.Reset();
   2466   CcTest::heap()->CollectAllAvailableGarbage();
   2467   CHECK_EQ(0, NumberOfGlobalObjects());
   2468 }
   2469 
   2470 
   2471 TEST(LeakNativeContextViaMapKeyed) {
   2472   i::FLAG_allow_natives_syntax = true;
   2473   v8::Isolate* isolate = CcTest::isolate();
   2474   v8::HandleScope outer_scope(isolate);
   2475   v8::Persistent<v8::Context> ctx1p;
   2476   v8::Persistent<v8::Context> ctx2p;
   2477   {
   2478     v8::HandleScope scope(isolate);
   2479     ctx1p.Reset(isolate, v8::Context::New(isolate));
   2480     ctx2p.Reset(isolate, v8::Context::New(isolate));
   2481     v8::Local<v8::Context>::New(isolate, ctx1p)->Enter();
   2482   }
   2483 
   2484   CcTest::heap()->CollectAllAvailableGarbage();
   2485   CHECK_EQ(2, NumberOfGlobalObjects());
   2486 
   2487   {
   2488     v8::HandleScope inner_scope(isolate);
   2489     CompileRun("var v = [42, 43]");
   2490     v8::Local<v8::Context> ctx1 = v8::Local<v8::Context>::New(isolate, ctx1p);
   2491     v8::Local<v8::Context> ctx2 = v8::Local<v8::Context>::New(isolate, ctx2p);
   2492     v8::Local<v8::Value> v =
   2493         ctx1->Global()->Get(ctx1, v8_str("v")).ToLocalChecked();
   2494     ctx2->Enter();
   2495     CHECK(ctx2->Global()->Set(ctx2, v8_str("o"), v).FromJust());
   2496     v8::Local<v8::Value> res = CompileRun(
   2497         "function f() { return o[0]; }"
   2498         "for (var i = 0; i < 10; ++i) f();"
   2499         "%OptimizeFunctionOnNextCall(f);"
   2500         "f();");
   2501     CHECK_EQ(42, res->Int32Value(ctx2).FromJust());
   2502     CHECK(ctx2->Global()
   2503               ->Set(ctx2, v8_str("o"), v8::Int32::New(isolate, 0))
   2504               .FromJust());
   2505     ctx2->Exit();
   2506     ctx1->Exit();
   2507     ctx1p.Reset();
   2508     isolate->ContextDisposedNotification();
   2509   }
   2510   CcTest::heap()->CollectAllAvailableGarbage();
   2511   CHECK_EQ(1, NumberOfGlobalObjects());
   2512   ctx2p.Reset();
   2513   CcTest::heap()->CollectAllAvailableGarbage();
   2514   CHECK_EQ(0, NumberOfGlobalObjects());
   2515 }
   2516 
   2517 
   2518 TEST(LeakNativeContextViaMapProto) {
   2519   i::FLAG_allow_natives_syntax = true;
   2520   v8::Isolate* isolate = CcTest::isolate();
   2521   v8::HandleScope outer_scope(isolate);
   2522   v8::Persistent<v8::Context> ctx1p;
   2523   v8::Persistent<v8::Context> ctx2p;
   2524   {
   2525     v8::HandleScope scope(isolate);
   2526     ctx1p.Reset(isolate, v8::Context::New(isolate));
   2527     ctx2p.Reset(isolate, v8::Context::New(isolate));
   2528     v8::Local<v8::Context>::New(isolate, ctx1p)->Enter();
   2529   }
   2530 
   2531   CcTest::heap()->CollectAllAvailableGarbage();
   2532   CHECK_EQ(2, NumberOfGlobalObjects());
   2533 
   2534   {
   2535     v8::HandleScope inner_scope(isolate);
   2536     CompileRun("var v = { y: 42}");
   2537     v8::Local<v8::Context> ctx1 = v8::Local<v8::Context>::New(isolate, ctx1p);
   2538     v8::Local<v8::Context> ctx2 = v8::Local<v8::Context>::New(isolate, ctx2p);
   2539     v8::Local<v8::Value> v =
   2540         ctx1->Global()->Get(ctx1, v8_str("v")).ToLocalChecked();
   2541     ctx2->Enter();
   2542     CHECK(ctx2->Global()->Set(ctx2, v8_str("o"), v).FromJust());
   2543     v8::Local<v8::Value> res = CompileRun(
   2544         "function f() {"
   2545         "  var p = {x: 42};"
   2546         "  p.__proto__ = o;"
   2547         "  return p.x;"
   2548         "}"
   2549         "for (var i = 0; i < 10; ++i) f();"
   2550         "%OptimizeFunctionOnNextCall(f);"
   2551         "f();");
   2552     CHECK_EQ(42, res->Int32Value(ctx2).FromJust());
   2553     CHECK(ctx2->Global()
   2554               ->Set(ctx2, v8_str("o"), v8::Int32::New(isolate, 0))
   2555               .FromJust());
   2556     ctx2->Exit();
   2557     ctx1->Exit();
   2558     ctx1p.Reset();
   2559     isolate->ContextDisposedNotification();
   2560   }
   2561   CcTest::heap()->CollectAllAvailableGarbage();
   2562   CHECK_EQ(1, NumberOfGlobalObjects());
   2563   ctx2p.Reset();
   2564   CcTest::heap()->CollectAllAvailableGarbage();
   2565   CHECK_EQ(0, NumberOfGlobalObjects());
   2566 }
   2567 
   2568 
   2569 TEST(InstanceOfStubWriteBarrier) {
   2570   i::FLAG_allow_natives_syntax = true;
   2571 #ifdef VERIFY_HEAP
   2572   i::FLAG_verify_heap = true;
   2573 #endif
   2574 
   2575   CcTest::InitializeVM();
   2576   if (!CcTest::i_isolate()->use_crankshaft()) return;
   2577   if (i::FLAG_force_marking_deque_overflows) return;
   2578   v8::HandleScope outer_scope(CcTest::isolate());
   2579   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   2580 
   2581   {
   2582     v8::HandleScope scope(CcTest::isolate());
   2583     CompileRun(
   2584         "function foo () { }"
   2585         "function mkbar () { return new (new Function(\"\")) (); }"
   2586         "function f (x) { return (x instanceof foo); }"
   2587         "function g () { f(mkbar()); }"
   2588         "f(new foo()); f(new foo());"
   2589         "%OptimizeFunctionOnNextCall(f);"
   2590         "f(new foo()); g();");
   2591   }
   2592 
   2593   IncrementalMarking* marking = CcTest::heap()->incremental_marking();
   2594   marking->Stop();
   2595   CcTest::heap()->StartIncrementalMarking();
   2596 
   2597   i::Handle<JSFunction> f = i::Handle<JSFunction>::cast(
   2598       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   2599           CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
   2600 
   2601   CHECK(f->IsOptimized());
   2602 
   2603   while (!Marking::IsBlack(Marking::MarkBitFrom(f->code())) &&
   2604          !marking->IsStopped()) {
   2605     // Discard any pending GC requests otherwise we will get GC when we enter
   2606     // code below.
   2607     marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
   2608   }
   2609 
   2610   CHECK(marking->IsMarking());
   2611 
   2612   {
   2613     v8::HandleScope scope(CcTest::isolate());
   2614     v8::Local<v8::Object> global = CcTest::global();
   2615     v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   2616         global->Get(ctx, v8_str("g")).ToLocalChecked());
   2617     g->Call(ctx, global, 0, nullptr).ToLocalChecked();
   2618   }
   2619 
   2620   CcTest::heap()->incremental_marking()->set_should_hurry(true);
   2621   CcTest::heap()->CollectGarbage(OLD_SPACE);
   2622 }
   2623 
   2624 
   2625 TEST(ResetSharedFunctionInfoCountersDuringIncrementalMarking) {
   2626   i::FLAG_stress_compaction = false;
   2627   i::FLAG_allow_natives_syntax = true;
   2628 #ifdef VERIFY_HEAP
   2629   i::FLAG_verify_heap = true;
   2630 #endif
   2631 
   2632   CcTest::InitializeVM();
   2633   if (!CcTest::i_isolate()->use_crankshaft()) return;
   2634   v8::HandleScope outer_scope(CcTest::isolate());
   2635   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   2636 
   2637   {
   2638     v8::HandleScope scope(CcTest::isolate());
   2639     CompileRun(
   2640         "function f () {"
   2641         "  var s = 0;"
   2642         "  for (var i = 0; i < 100; i++)  s += i;"
   2643         "  return s;"
   2644         "}"
   2645         "f(); f();"
   2646         "%OptimizeFunctionOnNextCall(f);"
   2647         "f();");
   2648   }
   2649   i::Handle<JSFunction> f = i::Handle<JSFunction>::cast(
   2650       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   2651           CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
   2652   CHECK(f->IsOptimized());
   2653 
   2654   IncrementalMarking* marking = CcTest::heap()->incremental_marking();
   2655   marking->Stop();
   2656   CcTest::heap()->StartIncrementalMarking();
   2657   // The following calls will increment CcTest::heap()->global_ic_age().
   2658   CcTest::isolate()->ContextDisposedNotification();
   2659   SimulateIncrementalMarking(CcTest::heap());
   2660   CcTest::heap()->CollectAllGarbage();
   2661   CHECK_EQ(CcTest::heap()->global_ic_age(), f->shared()->ic_age());
   2662   CHECK_EQ(0, f->shared()->opt_count());
   2663   CHECK_EQ(0, f->shared()->code()->profiler_ticks());
   2664 }
   2665 
   2666 
   2667 TEST(ResetSharedFunctionInfoCountersDuringMarkSweep) {
   2668   i::FLAG_stress_compaction = false;
   2669   i::FLAG_allow_natives_syntax = true;
   2670 #ifdef VERIFY_HEAP
   2671   i::FLAG_verify_heap = true;
   2672 #endif
   2673 
   2674   CcTest::InitializeVM();
   2675   if (!CcTest::i_isolate()->use_crankshaft()) return;
   2676   v8::HandleScope outer_scope(CcTest::isolate());
   2677   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   2678 
   2679   {
   2680     v8::HandleScope scope(CcTest::isolate());
   2681     CompileRun(
   2682         "function f () {"
   2683         "  var s = 0;"
   2684         "  for (var i = 0; i < 100; i++)  s += i;"
   2685         "  return s;"
   2686         "}"
   2687         "f(); f();"
   2688         "%OptimizeFunctionOnNextCall(f);"
   2689         "f();");
   2690   }
   2691   i::Handle<JSFunction> f = i::Handle<JSFunction>::cast(
   2692       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   2693           CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
   2694 
   2695   CHECK(f->IsOptimized());
   2696 
   2697   CcTest::heap()->incremental_marking()->Stop();
   2698 
   2699   // The following two calls will increment CcTest::heap()->global_ic_age().
   2700   CcTest::isolate()->ContextDisposedNotification();
   2701   CcTest::heap()->CollectAllGarbage();
   2702 
   2703   CHECK_EQ(CcTest::heap()->global_ic_age(), f->shared()->ic_age());
   2704   CHECK_EQ(0, f->shared()->opt_count());
   2705   CHECK_EQ(0, f->shared()->code()->profiler_ticks());
   2706 }
   2707 
   2708 
   2709 HEAP_TEST(GCFlags) {
   2710   CcTest::InitializeVM();
   2711   Heap* heap = CcTest::heap();
   2712 
   2713   heap->set_current_gc_flags(Heap::kNoGCFlags);
   2714   CHECK_EQ(Heap::kNoGCFlags, heap->current_gc_flags_);
   2715 
   2716   // Set the flags to check whether we appropriately resets them after the GC.
   2717   heap->set_current_gc_flags(Heap::kAbortIncrementalMarkingMask);
   2718   heap->CollectAllGarbage(Heap::kReduceMemoryFootprintMask);
   2719   CHECK_EQ(Heap::kNoGCFlags, heap->current_gc_flags_);
   2720 
   2721   MarkCompactCollector* collector = heap->mark_compact_collector();
   2722   if (collector->sweeping_in_progress()) {
   2723     collector->EnsureSweepingCompleted();
   2724   }
   2725 
   2726   IncrementalMarking* marking = heap->incremental_marking();
   2727   marking->Stop();
   2728   heap->StartIncrementalMarking(Heap::kReduceMemoryFootprintMask);
   2729   CHECK_NE(0, heap->current_gc_flags_ & Heap::kReduceMemoryFootprintMask);
   2730 
   2731   heap->CollectGarbage(NEW_SPACE);
   2732   // NewSpace scavenges should not overwrite the flags.
   2733   CHECK_NE(0, heap->current_gc_flags_ & Heap::kReduceMemoryFootprintMask);
   2734 
   2735   heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
   2736   CHECK_EQ(Heap::kNoGCFlags, heap->current_gc_flags_);
   2737 }
   2738 
   2739 
   2740 TEST(IdleNotificationFinishMarking) {
   2741   i::FLAG_allow_natives_syntax = true;
   2742   CcTest::InitializeVM();
   2743   SimulateFullSpace(CcTest::heap()->old_space());
   2744   IncrementalMarking* marking = CcTest::heap()->incremental_marking();
   2745   marking->Stop();
   2746   CcTest::heap()->StartIncrementalMarking();
   2747 
   2748   CHECK_EQ(CcTest::heap()->gc_count(), 0);
   2749 
   2750   // TODO(hpayer): We cannot write proper unit test right now for heap.
   2751   // The ideal test would call kMaxIdleMarkingDelayCounter to test the
   2752   // marking delay counter.
   2753 
   2754   // Perform a huge incremental marking step but don't complete marking.
   2755   intptr_t bytes_processed = 0;
   2756   do {
   2757     bytes_processed =
   2758         marking->Step(1 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD,
   2759                       IncrementalMarking::FORCE_MARKING,
   2760                       IncrementalMarking::DO_NOT_FORCE_COMPLETION);
   2761     CHECK(!marking->IsIdleMarkingDelayCounterLimitReached());
   2762   } while (bytes_processed);
   2763 
   2764   // The next invocations of incremental marking are not going to complete
   2765   // marking
   2766   // since the completion threshold is not reached
   2767   for (size_t i = 0; i < IncrementalMarking::kMaxIdleMarkingDelayCounter - 2;
   2768        i++) {
   2769     marking->Step(1 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD,
   2770                   IncrementalMarking::FORCE_MARKING,
   2771                   IncrementalMarking::DO_NOT_FORCE_COMPLETION);
   2772     CHECK(!marking->IsIdleMarkingDelayCounterLimitReached());
   2773   }
   2774 
   2775   marking->SetWeakClosureWasOverApproximatedForTesting(true);
   2776 
   2777   // The next idle notification has to finish incremental marking.
   2778   const double kLongIdleTime = 1000.0;
   2779   CcTest::isolate()->IdleNotificationDeadline(
   2780       (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
   2781        static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
   2782       kLongIdleTime);
   2783   CHECK_EQ(CcTest::heap()->gc_count(), 1);
   2784 }
   2785 
   2786 
   2787 // Test that HAllocateObject will always return an object in new-space.
   2788 TEST(OptimizedAllocationAlwaysInNewSpace) {
   2789   i::FLAG_allow_natives_syntax = true;
   2790   CcTest::InitializeVM();
   2791   if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
   2792   if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
   2793   v8::HandleScope scope(CcTest::isolate());
   2794   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   2795   SimulateFullSpace(CcTest::heap()->new_space());
   2796   AlwaysAllocateScope always_allocate(CcTest::i_isolate());
   2797   v8::Local<v8::Value> res = CompileRun(
   2798       "function c(x) {"
   2799       "  this.x = x;"
   2800       "  for (var i = 0; i < 32; i++) {"
   2801       "    this['x' + i] = x;"
   2802       "  }"
   2803       "}"
   2804       "function f(x) { return new c(x); };"
   2805       "f(1); f(2); f(3);"
   2806       "%OptimizeFunctionOnNextCall(f);"
   2807       "f(4);");
   2808 
   2809   CHECK_EQ(4, res.As<v8::Object>()
   2810                   ->GetRealNamedProperty(ctx, v8_str("x"))
   2811                   .ToLocalChecked()
   2812                   ->Int32Value(ctx)
   2813                   .FromJust());
   2814 
   2815   i::Handle<JSReceiver> o =
   2816       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(res));
   2817 
   2818   CHECK(CcTest::heap()->InNewSpace(*o));
   2819 }
   2820 
   2821 
   2822 TEST(OptimizedPretenuringAllocationFolding) {
   2823   i::FLAG_allow_natives_syntax = true;
   2824   i::FLAG_expose_gc = true;
   2825   CcTest::InitializeVM();
   2826   if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
   2827   if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
   2828   v8::HandleScope scope(CcTest::isolate());
   2829   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   2830   // Grow new space unitl maximum capacity reached.
   2831   while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
   2832     CcTest::heap()->new_space()->Grow();
   2833   }
   2834 
   2835   i::ScopedVector<char> source(1024);
   2836   i::SNPrintF(
   2837       source,
   2838       "var number_elements = %d;"
   2839       "var elements = new Array();"
   2840       "function f() {"
   2841       "  for (var i = 0; i < number_elements; i++) {"
   2842       "    elements[i] = [[{}], [1.1]];"
   2843       "  }"
   2844       "  return elements[number_elements-1]"
   2845       "};"
   2846       "f(); gc();"
   2847       "f(); f();"
   2848       "%%OptimizeFunctionOnNextCall(f);"
   2849       "f();",
   2850       AllocationSite::kPretenureMinimumCreated);
   2851 
   2852   v8::Local<v8::Value> res = CompileRun(source.start());
   2853 
   2854   v8::Local<v8::Value> int_array =
   2855       v8::Object::Cast(*res)->Get(ctx, v8_str("0")).ToLocalChecked();
   2856   i::Handle<JSObject> int_array_handle = i::Handle<JSObject>::cast(
   2857       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(int_array)));
   2858   v8::Local<v8::Value> double_array =
   2859       v8::Object::Cast(*res)->Get(ctx, v8_str("1")).ToLocalChecked();
   2860   i::Handle<JSObject> double_array_handle = i::Handle<JSObject>::cast(
   2861       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(double_array)));
   2862 
   2863   i::Handle<JSReceiver> o =
   2864       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(res));
   2865   CHECK(CcTest::heap()->InOldSpace(*o));
   2866   CHECK(CcTest::heap()->InOldSpace(*int_array_handle));
   2867   CHECK(CcTest::heap()->InOldSpace(int_array_handle->elements()));
   2868   CHECK(CcTest::heap()->InOldSpace(*double_array_handle));
   2869   CHECK(CcTest::heap()->InOldSpace(double_array_handle->elements()));
   2870 }
   2871 
   2872 
   2873 TEST(OptimizedPretenuringObjectArrayLiterals) {
   2874   i::FLAG_allow_natives_syntax = true;
   2875   i::FLAG_expose_gc = true;
   2876   CcTest::InitializeVM();
   2877   if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
   2878   if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
   2879   v8::HandleScope scope(CcTest::isolate());
   2880 
   2881   // Grow new space unitl maximum capacity reached.
   2882   while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
   2883     CcTest::heap()->new_space()->Grow();
   2884   }
   2885 
   2886   i::ScopedVector<char> source(1024);
   2887   i::SNPrintF(
   2888       source,
   2889       "var number_elements = %d;"
   2890       "var elements = new Array(number_elements);"
   2891       "function f() {"
   2892       "  for (var i = 0; i < number_elements; i++) {"
   2893       "    elements[i] = [{}, {}, {}];"
   2894       "  }"
   2895       "  return elements[number_elements - 1];"
   2896       "};"
   2897       "f(); gc();"
   2898       "f(); f();"
   2899       "%%OptimizeFunctionOnNextCall(f);"
   2900       "f();",
   2901       AllocationSite::kPretenureMinimumCreated);
   2902 
   2903   v8::Local<v8::Value> res = CompileRun(source.start());
   2904 
   2905   i::Handle<JSObject> o = Handle<JSObject>::cast(
   2906       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(res)));
   2907 
   2908   CHECK(CcTest::heap()->InOldSpace(o->elements()));
   2909   CHECK(CcTest::heap()->InOldSpace(*o));
   2910 }
   2911 
   2912 
   2913 TEST(OptimizedPretenuringMixedInObjectProperties) {
   2914   i::FLAG_allow_natives_syntax = true;
   2915   i::FLAG_expose_gc = true;
   2916   CcTest::InitializeVM();
   2917   if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
   2918   if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
   2919   v8::HandleScope scope(CcTest::isolate());
   2920 
   2921   // Grow new space unitl maximum capacity reached.
   2922   while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
   2923     CcTest::heap()->new_space()->Grow();
   2924   }
   2925 
   2926 
   2927   i::ScopedVector<char> source(1024);
   2928   i::SNPrintF(
   2929       source,
   2930       "var number_elements = %d;"
   2931       "var elements = new Array(number_elements);"
   2932       "function f() {"
   2933       "  for (var i = 0; i < number_elements; i++) {"
   2934       "    elements[i] = {a: {c: 2.2, d: {}}, b: 1.1};"
   2935       "  }"
   2936       "  return elements[number_elements - 1];"
   2937       "};"
   2938       "f(); gc();"
   2939       "f(); f();"
   2940       "%%OptimizeFunctionOnNextCall(f);"
   2941       "f();",
   2942       AllocationSite::kPretenureMinimumCreated);
   2943 
   2944   v8::Local<v8::Value> res = CompileRun(source.start());
   2945 
   2946   i::Handle<JSObject> o = Handle<JSObject>::cast(
   2947       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(res)));
   2948 
   2949   CHECK(CcTest::heap()->InOldSpace(*o));
   2950   FieldIndex idx1 = FieldIndex::ForPropertyIndex(o->map(), 0);
   2951   FieldIndex idx2 = FieldIndex::ForPropertyIndex(o->map(), 1);
   2952   CHECK(CcTest::heap()->InOldSpace(o->RawFastPropertyAt(idx1)));
   2953   if (!o->IsUnboxedDoubleField(idx2)) {
   2954     CHECK(CcTest::heap()->InOldSpace(o->RawFastPropertyAt(idx2)));
   2955   } else {
   2956     CHECK_EQ(1.1, o->RawFastDoublePropertyAt(idx2));
   2957   }
   2958 
   2959   JSObject* inner_object =
   2960       reinterpret_cast<JSObject*>(o->RawFastPropertyAt(idx1));
   2961   CHECK(CcTest::heap()->InOldSpace(inner_object));
   2962   if (!inner_object->IsUnboxedDoubleField(idx1)) {
   2963     CHECK(CcTest::heap()->InOldSpace(inner_object->RawFastPropertyAt(idx1)));
   2964   } else {
   2965     CHECK_EQ(2.2, inner_object->RawFastDoublePropertyAt(idx1));
   2966   }
   2967   CHECK(CcTest::heap()->InOldSpace(inner_object->RawFastPropertyAt(idx2)));
   2968 }
   2969 
   2970 
   2971 TEST(OptimizedPretenuringDoubleArrayProperties) {
   2972   i::FLAG_allow_natives_syntax = true;
   2973   i::FLAG_expose_gc = true;
   2974   CcTest::InitializeVM();
   2975   if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
   2976   if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
   2977   v8::HandleScope scope(CcTest::isolate());
   2978 
   2979   // Grow new space unitl maximum capacity reached.
   2980   while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
   2981     CcTest::heap()->new_space()->Grow();
   2982   }
   2983 
   2984   i::ScopedVector<char> source(1024);
   2985   i::SNPrintF(
   2986       source,
   2987       "var number_elements = %d;"
   2988       "var elements = new Array(number_elements);"
   2989       "function f() {"
   2990       "  for (var i = 0; i < number_elements; i++) {"
   2991       "    elements[i] = {a: 1.1, b: 2.2};"
   2992       "  }"
   2993       "  return elements[i - 1];"
   2994       "};"
   2995       "f(); gc();"
   2996       "f(); f();"
   2997       "%%OptimizeFunctionOnNextCall(f);"
   2998       "f();",
   2999       AllocationSite::kPretenureMinimumCreated);
   3000 
   3001   v8::Local<v8::Value> res = CompileRun(source.start());
   3002 
   3003   i::Handle<JSObject> o = Handle<JSObject>::cast(
   3004       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(res)));
   3005 
   3006   CHECK(CcTest::heap()->InOldSpace(*o));
   3007   CHECK(CcTest::heap()->InOldSpace(o->properties()));
   3008 }
   3009 
   3010 
   3011 TEST(OptimizedPretenuringdoubleArrayLiterals) {
   3012   i::FLAG_allow_natives_syntax = true;
   3013   i::FLAG_expose_gc = true;
   3014   CcTest::InitializeVM();
   3015   if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
   3016   if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
   3017   v8::HandleScope scope(CcTest::isolate());
   3018 
   3019   // Grow new space unitl maximum capacity reached.
   3020   while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
   3021     CcTest::heap()->new_space()->Grow();
   3022   }
   3023 
   3024   i::ScopedVector<char> source(1024);
   3025   i::SNPrintF(
   3026       source,
   3027       "var number_elements = %d;"
   3028       "var elements = new Array(number_elements);"
   3029       "function f() {"
   3030       "  for (var i = 0; i < number_elements; i++) {"
   3031       "    elements[i] = [1.1, 2.2, 3.3];"
   3032       "  }"
   3033       "  return elements[number_elements - 1];"
   3034       "};"
   3035       "f(); gc();"
   3036       "f(); f();"
   3037       "%%OptimizeFunctionOnNextCall(f);"
   3038       "f();",
   3039       AllocationSite::kPretenureMinimumCreated);
   3040 
   3041   v8::Local<v8::Value> res = CompileRun(source.start());
   3042 
   3043   i::Handle<JSObject> o = Handle<JSObject>::cast(
   3044       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(res)));
   3045 
   3046   CHECK(CcTest::heap()->InOldSpace(o->elements()));
   3047   CHECK(CcTest::heap()->InOldSpace(*o));
   3048 }
   3049 
   3050 
   3051 TEST(OptimizedPretenuringNestedMixedArrayLiterals) {
   3052   i::FLAG_allow_natives_syntax = true;
   3053   i::FLAG_expose_gc = true;
   3054   CcTest::InitializeVM();
   3055   if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
   3056   if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
   3057   v8::HandleScope scope(CcTest::isolate());
   3058   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   3059   // Grow new space unitl maximum capacity reached.
   3060   while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
   3061     CcTest::heap()->new_space()->Grow();
   3062   }
   3063 
   3064   i::ScopedVector<char> source(1024);
   3065   i::SNPrintF(
   3066       source,
   3067       "var number_elements = 100;"
   3068       "var elements = new Array(number_elements);"
   3069       "function f() {"
   3070       "  for (var i = 0; i < number_elements; i++) {"
   3071       "    elements[i] = [[{}, {}, {}], [1.1, 2.2, 3.3]];"
   3072       "  }"
   3073       "  return elements[number_elements - 1];"
   3074       "};"
   3075       "f(); gc();"
   3076       "f(); f();"
   3077       "%%OptimizeFunctionOnNextCall(f);"
   3078       "f();");
   3079 
   3080   v8::Local<v8::Value> res = CompileRun(source.start());
   3081 
   3082   v8::Local<v8::Value> int_array =
   3083       v8::Object::Cast(*res)->Get(ctx, v8_str("0")).ToLocalChecked();
   3084   i::Handle<JSObject> int_array_handle = i::Handle<JSObject>::cast(
   3085       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(int_array)));
   3086   v8::Local<v8::Value> double_array =
   3087       v8::Object::Cast(*res)->Get(ctx, v8_str("1")).ToLocalChecked();
   3088   i::Handle<JSObject> double_array_handle = i::Handle<JSObject>::cast(
   3089       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(double_array)));
   3090 
   3091   Handle<JSObject> o = Handle<JSObject>::cast(
   3092       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(res)));
   3093   CHECK(CcTest::heap()->InOldSpace(*o));
   3094   CHECK(CcTest::heap()->InOldSpace(*int_array_handle));
   3095   CHECK(CcTest::heap()->InOldSpace(int_array_handle->elements()));
   3096   CHECK(CcTest::heap()->InOldSpace(*double_array_handle));
   3097   CHECK(CcTest::heap()->InOldSpace(double_array_handle->elements()));
   3098 }
   3099 
   3100 
   3101 TEST(OptimizedPretenuringNestedObjectLiterals) {
   3102   i::FLAG_allow_natives_syntax = true;
   3103   i::FLAG_expose_gc = true;
   3104   CcTest::InitializeVM();
   3105   if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
   3106   if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
   3107   v8::HandleScope scope(CcTest::isolate());
   3108   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   3109   // Grow new space unitl maximum capacity reached.
   3110   while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
   3111     CcTest::heap()->new_space()->Grow();
   3112   }
   3113 
   3114   i::ScopedVector<char> source(1024);
   3115   i::SNPrintF(
   3116       source,
   3117       "var number_elements = %d;"
   3118       "var elements = new Array(number_elements);"
   3119       "function f() {"
   3120       "  for (var i = 0; i < number_elements; i++) {"
   3121       "    elements[i] = [[{}, {}, {}],[{}, {}, {}]];"
   3122       "  }"
   3123       "  return elements[number_elements - 1];"
   3124       "};"
   3125       "f(); gc();"
   3126       "f(); f();"
   3127       "%%OptimizeFunctionOnNextCall(f);"
   3128       "f();",
   3129       AllocationSite::kPretenureMinimumCreated);
   3130 
   3131   v8::Local<v8::Value> res = CompileRun(source.start());
   3132 
   3133   v8::Local<v8::Value> int_array_1 =
   3134       v8::Object::Cast(*res)->Get(ctx, v8_str("0")).ToLocalChecked();
   3135   Handle<JSObject> int_array_handle_1 = Handle<JSObject>::cast(
   3136       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(int_array_1)));
   3137   v8::Local<v8::Value> int_array_2 =
   3138       v8::Object::Cast(*res)->Get(ctx, v8_str("1")).ToLocalChecked();
   3139   Handle<JSObject> int_array_handle_2 = Handle<JSObject>::cast(
   3140       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(int_array_2)));
   3141 
   3142   Handle<JSObject> o = Handle<JSObject>::cast(
   3143       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(res)));
   3144   CHECK(CcTest::heap()->InOldSpace(*o));
   3145   CHECK(CcTest::heap()->InOldSpace(*int_array_handle_1));
   3146   CHECK(CcTest::heap()->InOldSpace(int_array_handle_1->elements()));
   3147   CHECK(CcTest::heap()->InOldSpace(*int_array_handle_2));
   3148   CHECK(CcTest::heap()->InOldSpace(int_array_handle_2->elements()));
   3149 }
   3150 
   3151 
   3152 TEST(OptimizedPretenuringNestedDoubleLiterals) {
   3153   i::FLAG_allow_natives_syntax = true;
   3154   i::FLAG_expose_gc = true;
   3155   CcTest::InitializeVM();
   3156   if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
   3157   if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
   3158   v8::HandleScope scope(CcTest::isolate());
   3159   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   3160   // Grow new space unitl maximum capacity reached.
   3161   while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) {
   3162     CcTest::heap()->new_space()->Grow();
   3163   }
   3164 
   3165   i::ScopedVector<char> source(1024);
   3166   i::SNPrintF(
   3167       source,
   3168       "var number_elements = %d;"
   3169       "var elements = new Array(number_elements);"
   3170       "function f() {"
   3171       "  for (var i = 0; i < number_elements; i++) {"
   3172       "    elements[i] = [[1.1, 1.2, 1.3],[2.1, 2.2, 2.3]];"
   3173       "  }"
   3174       "  return elements[number_elements - 1];"
   3175       "};"
   3176       "f(); gc();"
   3177       "f(); f();"
   3178       "%%OptimizeFunctionOnNextCall(f);"
   3179       "f();",
   3180       AllocationSite::kPretenureMinimumCreated);
   3181 
   3182   v8::Local<v8::Value> res = CompileRun(source.start());
   3183 
   3184   v8::Local<v8::Value> double_array_1 =
   3185       v8::Object::Cast(*res)->Get(ctx, v8_str("0")).ToLocalChecked();
   3186   i::Handle<JSObject> double_array_handle_1 = i::Handle<JSObject>::cast(
   3187       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(double_array_1)));
   3188   v8::Local<v8::Value> double_array_2 =
   3189       v8::Object::Cast(*res)->Get(ctx, v8_str("1")).ToLocalChecked();
   3190   i::Handle<JSObject> double_array_handle_2 = Handle<JSObject>::cast(
   3191       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(double_array_2)));
   3192 
   3193   i::Handle<JSObject> o = Handle<JSObject>::cast(
   3194       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(res)));
   3195   CHECK(CcTest::heap()->InOldSpace(*o));
   3196   CHECK(CcTest::heap()->InOldSpace(*double_array_handle_1));
   3197   CHECK(CcTest::heap()->InOldSpace(double_array_handle_1->elements()));
   3198   CHECK(CcTest::heap()->InOldSpace(*double_array_handle_2));
   3199   CHECK(CcTest::heap()->InOldSpace(double_array_handle_2->elements()));
   3200 }
   3201 
   3202 
   3203 // Test regular array literals allocation.
   3204 TEST(OptimizedAllocationArrayLiterals) {
   3205   i::FLAG_allow_natives_syntax = true;
   3206   CcTest::InitializeVM();
   3207   if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
   3208   if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
   3209   v8::HandleScope scope(CcTest::isolate());
   3210   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   3211   v8::Local<v8::Value> res = CompileRun(
   3212       "function f() {"
   3213       "  var numbers = new Array(1, 2, 3);"
   3214       "  numbers[0] = 3.14;"
   3215       "  return numbers;"
   3216       "};"
   3217       "f(); f(); f();"
   3218       "%OptimizeFunctionOnNextCall(f);"
   3219       "f();");
   3220   CHECK_EQ(static_cast<int>(3.14), v8::Object::Cast(*res)
   3221                                        ->Get(ctx, v8_str("0"))
   3222                                        .ToLocalChecked()
   3223                                        ->Int32Value(ctx)
   3224                                        .FromJust());
   3225 
   3226   i::Handle<JSObject> o = Handle<JSObject>::cast(
   3227       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(res)));
   3228 
   3229   CHECK(CcTest::heap()->InNewSpace(o->elements()));
   3230 }
   3231 
   3232 
   3233 static int CountMapTransitions(Map* map) {
   3234   return TransitionArray::NumberOfTransitions(map->raw_transitions());
   3235 }
   3236 
   3237 
   3238 // Test that map transitions are cleared and maps are collected with
   3239 // incremental marking as well.
   3240 TEST(Regress1465) {
   3241   i::FLAG_stress_compaction = false;
   3242   i::FLAG_allow_natives_syntax = true;
   3243   i::FLAG_trace_incremental_marking = true;
   3244   i::FLAG_retain_maps_for_n_gc = 0;
   3245   CcTest::InitializeVM();
   3246   v8::HandleScope scope(CcTest::isolate());
   3247   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   3248   static const int transitions_count = 256;
   3249 
   3250   CompileRun("function F() {}");
   3251   {
   3252     AlwaysAllocateScope always_allocate(CcTest::i_isolate());
   3253     for (int i = 0; i < transitions_count; i++) {
   3254       EmbeddedVector<char, 64> buffer;
   3255       SNPrintF(buffer, "var o = new F; o.prop%d = %d;", i, i);
   3256       CompileRun(buffer.start());
   3257     }
   3258     CompileRun("var root = new F;");
   3259   }
   3260 
   3261   i::Handle<JSReceiver> root =
   3262       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(
   3263           CcTest::global()->Get(ctx, v8_str("root")).ToLocalChecked()));
   3264 
   3265   // Count number of live transitions before marking.
   3266   int transitions_before = CountMapTransitions(root->map());
   3267   CompileRun("%DebugPrint(root);");
   3268   CHECK_EQ(transitions_count, transitions_before);
   3269 
   3270   SimulateIncrementalMarking(CcTest::heap());
   3271   CcTest::heap()->CollectAllGarbage();
   3272 
   3273   // Count number of live transitions after marking.  Note that one transition
   3274   // is left, because 'o' still holds an instance of one transition target.
   3275   int transitions_after = CountMapTransitions(root->map());
   3276   CompileRun("%DebugPrint(root);");
   3277   CHECK_EQ(1, transitions_after);
   3278 }
   3279 
   3280 
   3281 #ifdef DEBUG
   3282 static void AddTransitions(int transitions_count) {
   3283   AlwaysAllocateScope always_allocate(CcTest::i_isolate());
   3284   for (int i = 0; i < transitions_count; i++) {
   3285     EmbeddedVector<char, 64> buffer;
   3286     SNPrintF(buffer, "var o = new F; o.prop%d = %d;", i, i);
   3287     CompileRun(buffer.start());
   3288   }
   3289 }
   3290 
   3291 
   3292 static i::Handle<JSObject> GetByName(const char* name) {
   3293   return i::Handle<JSObject>::cast(
   3294       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(
   3295           CcTest::global()
   3296               ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
   3297               .ToLocalChecked())));
   3298 }
   3299 
   3300 
   3301 static void AddPropertyTo(
   3302     int gc_count, Handle<JSObject> object, const char* property_name) {
   3303   Isolate* isolate = CcTest::i_isolate();
   3304   Factory* factory = isolate->factory();
   3305   Handle<String> prop_name = factory->InternalizeUtf8String(property_name);
   3306   Handle<Smi> twenty_three(Smi::FromInt(23), isolate);
   3307   i::FLAG_gc_interval = gc_count;
   3308   i::FLAG_gc_global = true;
   3309   i::FLAG_retain_maps_for_n_gc = 0;
   3310   CcTest::heap()->set_allocation_timeout(gc_count);
   3311   JSReceiver::SetProperty(object, prop_name, twenty_three, SLOPPY).Check();
   3312 }
   3313 
   3314 
   3315 TEST(TransitionArrayShrinksDuringAllocToZero) {
   3316   i::FLAG_stress_compaction = false;
   3317   i::FLAG_allow_natives_syntax = true;
   3318   CcTest::InitializeVM();
   3319   v8::HandleScope scope(CcTest::isolate());
   3320   static const int transitions_count = 10;
   3321   CompileRun("function F() { }");
   3322   AddTransitions(transitions_count);
   3323   CompileRun("var root = new F;");
   3324   Handle<JSObject> root = GetByName("root");
   3325 
   3326   // Count number of live transitions before marking.
   3327   int transitions_before = CountMapTransitions(root->map());
   3328   CHECK_EQ(transitions_count, transitions_before);
   3329 
   3330   // Get rid of o
   3331   CompileRun("o = new F;"
   3332              "root = new F");
   3333   root = GetByName("root");
   3334   AddPropertyTo(2, root, "funny");
   3335   CcTest::heap()->CollectGarbage(NEW_SPACE);
   3336 
   3337   // Count number of live transitions after marking.  Note that one transition
   3338   // is left, because 'o' still holds an instance of one transition target.
   3339   int transitions_after = CountMapTransitions(
   3340       Map::cast(root->map()->GetBackPointer()));
   3341   CHECK_EQ(1, transitions_after);
   3342 }
   3343 
   3344 
   3345 TEST(TransitionArrayShrinksDuringAllocToOne) {
   3346   i::FLAG_stress_compaction = false;
   3347   i::FLAG_allow_natives_syntax = true;
   3348   CcTest::InitializeVM();
   3349   v8::HandleScope scope(CcTest::isolate());
   3350   static const int transitions_count = 10;
   3351   CompileRun("function F() {}");
   3352   AddTransitions(transitions_count);
   3353   CompileRun("var root = new F;");
   3354   Handle<JSObject> root = GetByName("root");
   3355 
   3356   // Count number of live transitions before marking.
   3357   int transitions_before = CountMapTransitions(root->map());
   3358   CHECK_EQ(transitions_count, transitions_before);
   3359 
   3360   root = GetByName("root");
   3361   AddPropertyTo(2, root, "funny");
   3362   CcTest::heap()->CollectGarbage(NEW_SPACE);
   3363 
   3364   // Count number of live transitions after marking.  Note that one transition
   3365   // is left, because 'o' still holds an instance of one transition target.
   3366   int transitions_after = CountMapTransitions(
   3367       Map::cast(root->map()->GetBackPointer()));
   3368   CHECK_EQ(2, transitions_after);
   3369 }
   3370 
   3371 
   3372 TEST(TransitionArrayShrinksDuringAllocToOnePropertyFound) {
   3373   i::FLAG_stress_compaction = false;
   3374   i::FLAG_allow_natives_syntax = true;
   3375   CcTest::InitializeVM();
   3376   v8::HandleScope scope(CcTest::isolate());
   3377   static const int transitions_count = 10;
   3378   CompileRun("function F() {}");
   3379   AddTransitions(transitions_count);
   3380   CompileRun("var root = new F;");
   3381   Handle<JSObject> root = GetByName("root");
   3382 
   3383   // Count number of live transitions before marking.
   3384   int transitions_before = CountMapTransitions(root->map());
   3385   CHECK_EQ(transitions_count, transitions_before);
   3386 
   3387   root = GetByName("root");
   3388   AddPropertyTo(0, root, "prop9");
   3389   CcTest::i_isolate()->heap()->CollectGarbage(OLD_SPACE);
   3390 
   3391   // Count number of live transitions after marking.  Note that one transition
   3392   // is left, because 'o' still holds an instance of one transition target.
   3393   int transitions_after = CountMapTransitions(
   3394       Map::cast(root->map()->GetBackPointer()));
   3395   CHECK_EQ(1, transitions_after);
   3396 }
   3397 
   3398 
   3399 TEST(TransitionArraySimpleToFull) {
   3400   i::FLAG_stress_compaction = false;
   3401   i::FLAG_allow_natives_syntax = true;
   3402   CcTest::InitializeVM();
   3403   v8::HandleScope scope(CcTest::isolate());
   3404   static const int transitions_count = 1;
   3405   CompileRun("function F() {}");
   3406   AddTransitions(transitions_count);
   3407   CompileRun("var root = new F;");
   3408   Handle<JSObject> root = GetByName("root");
   3409 
   3410   // Count number of live transitions before marking.
   3411   int transitions_before = CountMapTransitions(root->map());
   3412   CHECK_EQ(transitions_count, transitions_before);
   3413 
   3414   CompileRun("o = new F;"
   3415              "root = new F");
   3416   root = GetByName("root");
   3417   CHECK(TransitionArray::IsSimpleTransition(root->map()->raw_transitions()));
   3418   AddPropertyTo(2, root, "happy");
   3419 
   3420   // Count number of live transitions after marking.  Note that one transition
   3421   // is left, because 'o' still holds an instance of one transition target.
   3422   int transitions_after = CountMapTransitions(
   3423       Map::cast(root->map()->GetBackPointer()));
   3424   CHECK_EQ(1, transitions_after);
   3425 }
   3426 #endif  // DEBUG
   3427 
   3428 
   3429 TEST(Regress2143a) {
   3430   i::FLAG_incremental_marking = true;
   3431   CcTest::InitializeVM();
   3432   v8::HandleScope scope(CcTest::isolate());
   3433 
   3434   // Prepare a map transition from the root object together with a yet
   3435   // untransitioned root object.
   3436   CompileRun("var root = new Object;"
   3437              "root.foo = 0;"
   3438              "root = new Object;");
   3439 
   3440   SimulateIncrementalMarking(CcTest::heap());
   3441 
   3442   // Compile a StoreIC that performs the prepared map transition. This
   3443   // will restart incremental marking and should make sure the root is
   3444   // marked grey again.
   3445   CompileRun("function f(o) {"
   3446              "  o.foo = 0;"
   3447              "}"
   3448              "f(new Object);"
   3449              "f(root);");
   3450 
   3451   // This bug only triggers with aggressive IC clearing.
   3452   CcTest::heap()->AgeInlineCaches();
   3453 
   3454   // Explicitly request GC to perform final marking step and sweeping.
   3455   CcTest::heap()->CollectAllGarbage();
   3456 
   3457   Handle<JSReceiver> root = v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(
   3458       CcTest::global()
   3459           ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("root"))
   3460           .ToLocalChecked()));
   3461 
   3462   // The root object should be in a sane state.
   3463   CHECK(root->IsJSObject());
   3464   CHECK(root->map()->IsMap());
   3465 }
   3466 
   3467 
   3468 TEST(Regress2143b) {
   3469   i::FLAG_incremental_marking = true;
   3470   i::FLAG_allow_natives_syntax = true;
   3471   CcTest::InitializeVM();
   3472   v8::HandleScope scope(CcTest::isolate());
   3473 
   3474   // Prepare a map transition from the root object together with a yet
   3475   // untransitioned root object.
   3476   CompileRun("var root = new Object;"
   3477              "root.foo = 0;"
   3478              "root = new Object;");
   3479 
   3480   SimulateIncrementalMarking(CcTest::heap());
   3481 
   3482   // Compile an optimized LStoreNamedField that performs the prepared
   3483   // map transition. This will restart incremental marking and should
   3484   // make sure the root is marked grey again.
   3485   CompileRun("function f(o) {"
   3486              "  o.foo = 0;"
   3487              "}"
   3488              "f(new Object);"
   3489              "f(new Object);"
   3490              "%OptimizeFunctionOnNextCall(f);"
   3491              "f(root);"
   3492              "%DeoptimizeFunction(f);");
   3493 
   3494   // This bug only triggers with aggressive IC clearing.
   3495   CcTest::heap()->AgeInlineCaches();
   3496 
   3497   // Explicitly request GC to perform final marking step and sweeping.
   3498   CcTest::heap()->CollectAllGarbage();
   3499 
   3500   Handle<JSReceiver> root = v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(
   3501       CcTest::global()
   3502           ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("root"))
   3503           .ToLocalChecked()));
   3504 
   3505   // The root object should be in a sane state.
   3506   CHECK(root->IsJSObject());
   3507   CHECK(root->map()->IsMap());
   3508 }
   3509 
   3510 
   3511 TEST(ReleaseOverReservedPages) {
   3512   if (FLAG_never_compact) return;
   3513   i::FLAG_trace_gc = true;
   3514   // The optimizer can allocate stuff, messing up the test.
   3515   i::FLAG_crankshaft = false;
   3516   i::FLAG_always_opt = false;
   3517   CcTest::InitializeVM();
   3518   Isolate* isolate = CcTest::i_isolate();
   3519   Factory* factory = isolate->factory();
   3520   Heap* heap = isolate->heap();
   3521   v8::HandleScope scope(CcTest::isolate());
   3522   static const int number_of_test_pages = 20;
   3523 
   3524   // Prepare many pages with low live-bytes count.
   3525   PagedSpace* old_space = heap->old_space();
   3526   CHECK_EQ(1, old_space->CountTotalPages());
   3527   for (int i = 0; i < number_of_test_pages; i++) {
   3528     AlwaysAllocateScope always_allocate(isolate);
   3529     SimulateFullSpace(old_space);
   3530     factory->NewFixedArray(1, TENURED);
   3531   }
   3532   CHECK_EQ(number_of_test_pages + 1, old_space->CountTotalPages());
   3533 
   3534   // Triggering one GC will cause a lot of garbage to be discovered but
   3535   // even spread across all allocated pages.
   3536   heap->CollectAllGarbage(Heap::kFinalizeIncrementalMarkingMask,
   3537                           "triggered for preparation");
   3538   CHECK_GE(number_of_test_pages + 1, old_space->CountTotalPages());
   3539 
   3540   // Triggering subsequent GCs should cause at least half of the pages
   3541   // to be released to the OS after at most two cycles.
   3542   heap->CollectAllGarbage(Heap::kFinalizeIncrementalMarkingMask,
   3543                           "triggered by test 1");
   3544   CHECK_GE(number_of_test_pages + 1, old_space->CountTotalPages());
   3545   heap->CollectAllGarbage(Heap::kFinalizeIncrementalMarkingMask,
   3546                           "triggered by test 2");
   3547   CHECK_GE(number_of_test_pages + 1, old_space->CountTotalPages() * 2);
   3548 
   3549   // Triggering a last-resort GC should cause all pages to be released to the
   3550   // OS so that other processes can seize the memory.  If we get a failure here
   3551   // where there are 2 pages left instead of 1, then we should increase the
   3552   // size of the first page a little in SizeOfFirstPage in spaces.cc.  The
   3553   // first page should be small in order to reduce memory used when the VM
   3554   // boots, but if the 20 small arrays don't fit on the first page then that's
   3555   // an indication that it is too small.
   3556   heap->CollectAllAvailableGarbage("triggered really hard");
   3557   CHECK_EQ(1, old_space->CountTotalPages());
   3558 }
   3559 
   3560 static int forced_gc_counter = 0;
   3561 
   3562 void MockUseCounterCallback(v8::Isolate* isolate,
   3563                             v8::Isolate::UseCounterFeature feature) {
   3564   isolate->GetCurrentContext();
   3565   if (feature == v8::Isolate::kForcedGC) {
   3566     forced_gc_counter++;
   3567   }
   3568 }
   3569 
   3570 
   3571 TEST(CountForcedGC) {
   3572   i::FLAG_expose_gc = true;
   3573   CcTest::InitializeVM();
   3574   Isolate* isolate = CcTest::i_isolate();
   3575   v8::HandleScope scope(CcTest::isolate());
   3576 
   3577   isolate->SetUseCounterCallback(MockUseCounterCallback);
   3578 
   3579   forced_gc_counter = 0;
   3580   const char* source = "gc();";
   3581   CompileRun(source);
   3582   CHECK_GT(forced_gc_counter, 0);
   3583 }
   3584 
   3585 
   3586 #ifdef OBJECT_PRINT
   3587 TEST(PrintSharedFunctionInfo) {
   3588   CcTest::InitializeVM();
   3589   v8::HandleScope scope(CcTest::isolate());
   3590   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   3591   const char* source = "f = function() { return 987654321; }\n"
   3592                        "g = function() { return 123456789; }\n";
   3593   CompileRun(source);
   3594   i::Handle<JSFunction> g = i::Handle<JSFunction>::cast(
   3595       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   3596           CcTest::global()->Get(ctx, v8_str("g")).ToLocalChecked())));
   3597 
   3598   OFStream os(stdout);
   3599   g->shared()->Print(os);
   3600   os << std::endl;
   3601 }
   3602 #endif  // OBJECT_PRINT
   3603 
   3604 
   3605 TEST(IncrementalMarkingPreservesMonomorphicCallIC) {
   3606   if (i::FLAG_always_opt) return;
   3607   CcTest::InitializeVM();
   3608   v8::HandleScope scope(CcTest::isolate());
   3609   v8::Local<v8::Value> fun1, fun2;
   3610   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   3611   {
   3612     CompileRun("function fun() {};");
   3613     fun1 = CcTest::global()->Get(ctx, v8_str("fun")).ToLocalChecked();
   3614   }
   3615 
   3616   {
   3617     CompileRun("function fun() {};");
   3618     fun2 = CcTest::global()->Get(ctx, v8_str("fun")).ToLocalChecked();
   3619   }
   3620 
   3621   // Prepare function f that contains type feedback for the two closures.
   3622   CHECK(CcTest::global()->Set(ctx, v8_str("fun1"), fun1).FromJust());
   3623   CHECK(CcTest::global()->Set(ctx, v8_str("fun2"), fun2).FromJust());
   3624   CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);");
   3625 
   3626   Handle<JSFunction> f = Handle<JSFunction>::cast(
   3627       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   3628           CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
   3629 
   3630   Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector());
   3631   FeedbackVectorHelper feedback_helper(feedback_vector);
   3632 
   3633   int expected_slots = 2;
   3634   CHECK_EQ(expected_slots, feedback_helper.slot_count());
   3635   int slot1 = 0;
   3636   int slot2 = 1;
   3637   CHECK(feedback_vector->Get(feedback_helper.slot(slot1))->IsWeakCell());
   3638   CHECK(feedback_vector->Get(feedback_helper.slot(slot2))->IsWeakCell());
   3639 
   3640   SimulateIncrementalMarking(CcTest::heap());
   3641   CcTest::heap()->CollectAllGarbage();
   3642 
   3643   CHECK(!WeakCell::cast(feedback_vector->Get(feedback_helper.slot(slot1)))
   3644              ->cleared());
   3645   CHECK(!WeakCell::cast(feedback_vector->Get(feedback_helper.slot(slot2)))
   3646              ->cleared());
   3647 }
   3648 
   3649 
   3650 static Code* FindFirstIC(Code* code, Code::Kind kind) {
   3651   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
   3652              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
   3653   for (RelocIterator it(code, mask); !it.done(); it.next()) {
   3654     RelocInfo* info = it.rinfo();
   3655     Code* target = Code::GetCodeFromTargetAddress(info->target_address());
   3656     if (target->is_inline_cache_stub() && target->kind() == kind) {
   3657       return target;
   3658     }
   3659   }
   3660   return NULL;
   3661 }
   3662 
   3663 
   3664 static void CheckVectorIC(Handle<JSFunction> f, int slot_index,
   3665                           InlineCacheState desired_state) {
   3666   Handle<TypeFeedbackVector> vector =
   3667       Handle<TypeFeedbackVector>(f->shared()->feedback_vector());
   3668   FeedbackVectorHelper helper(vector);
   3669   FeedbackVectorSlot slot = helper.slot(slot_index);
   3670   if (vector->GetKind(slot) == FeedbackVectorSlotKind::LOAD_IC) {
   3671     LoadICNexus nexus(vector, slot);
   3672     CHECK(nexus.StateFromFeedback() == desired_state);
   3673   } else {
   3674     CHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot));
   3675     KeyedLoadICNexus nexus(vector, slot);
   3676     CHECK(nexus.StateFromFeedback() == desired_state);
   3677   }
   3678 }
   3679 
   3680 
   3681 static void CheckVectorICCleared(Handle<JSFunction> f, int slot_index) {
   3682   Handle<TypeFeedbackVector> vector =
   3683       Handle<TypeFeedbackVector>(f->shared()->feedback_vector());
   3684   FeedbackVectorSlot slot(slot_index);
   3685   LoadICNexus nexus(vector, slot);
   3686   CHECK(IC::IsCleared(&nexus));
   3687 }
   3688 
   3689 
   3690 TEST(IncrementalMarkingPreservesMonomorphicConstructor) {
   3691   if (i::FLAG_always_opt) return;
   3692   CcTest::InitializeVM();
   3693   v8::HandleScope scope(CcTest::isolate());
   3694   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   3695   // Prepare function f that contains a monomorphic IC for object
   3696   // originating from the same native context.
   3697   CompileRun(
   3698       "function fun() { this.x = 1; };"
   3699       "function f(o) { return new o(); } f(fun); f(fun);");
   3700   Handle<JSFunction> f = Handle<JSFunction>::cast(
   3701       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   3702           CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
   3703 
   3704   Handle<TypeFeedbackVector> vector(f->shared()->feedback_vector());
   3705   CHECK(vector->Get(FeedbackVectorSlot(0))->IsWeakCell());
   3706 
   3707   SimulateIncrementalMarking(CcTest::heap());
   3708   CcTest::heap()->CollectAllGarbage();
   3709 
   3710   CHECK(vector->Get(FeedbackVectorSlot(0))->IsWeakCell());
   3711 }
   3712 
   3713 
   3714 TEST(IncrementalMarkingClearsMonomorphicConstructor) {
   3715   if (i::FLAG_always_opt) return;
   3716   CcTest::InitializeVM();
   3717   Isolate* isolate = CcTest::i_isolate();
   3718   v8::HandleScope scope(CcTest::isolate());
   3719   v8::Local<v8::Value> fun1;
   3720   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   3721 
   3722   {
   3723     LocalContext env;
   3724     CompileRun("function fun() { this.x = 1; };");
   3725     fun1 = env->Global()->Get(env.local(), v8_str("fun")).ToLocalChecked();
   3726   }
   3727 
   3728   // Prepare function f that contains a monomorphic constructor for object
   3729   // originating from a different native context.
   3730   CHECK(CcTest::global()->Set(ctx, v8_str("fun1"), fun1).FromJust());
   3731   CompileRun(
   3732       "function fun() { this.x = 1; };"
   3733       "function f(o) { return new o(); } f(fun1); f(fun1);");
   3734   Handle<JSFunction> f = Handle<JSFunction>::cast(
   3735       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   3736           CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
   3737 
   3738 
   3739   Handle<TypeFeedbackVector> vector(f->shared()->feedback_vector());
   3740   CHECK(vector->Get(FeedbackVectorSlot(0))->IsWeakCell());
   3741 
   3742   // Fire context dispose notification.
   3743   CcTest::isolate()->ContextDisposedNotification();
   3744   SimulateIncrementalMarking(CcTest::heap());
   3745   CcTest::heap()->CollectAllGarbage();
   3746 
   3747   CHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(isolate),
   3748            vector->Get(FeedbackVectorSlot(0)));
   3749 }
   3750 
   3751 
   3752 TEST(IncrementalMarkingPreservesMonomorphicIC) {
   3753   if (i::FLAG_always_opt) return;
   3754   CcTest::InitializeVM();
   3755   v8::HandleScope scope(CcTest::isolate());
   3756   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   3757   // Prepare function f that contains a monomorphic IC for object
   3758   // originating from the same native context.
   3759   CompileRun("function fun() { this.x = 1; }; var obj = new fun();"
   3760              "function f(o) { return o.x; } f(obj); f(obj);");
   3761   Handle<JSFunction> f = Handle<JSFunction>::cast(
   3762       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   3763           CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
   3764 
   3765   CheckVectorIC(f, 0, MONOMORPHIC);
   3766 
   3767   SimulateIncrementalMarking(CcTest::heap());
   3768   CcTest::heap()->CollectAllGarbage();
   3769 
   3770   CheckVectorIC(f, 0, MONOMORPHIC);
   3771 }
   3772 
   3773 
   3774 TEST(IncrementalMarkingClearsMonomorphicIC) {
   3775   if (i::FLAG_always_opt) return;
   3776   CcTest::InitializeVM();
   3777   v8::HandleScope scope(CcTest::isolate());
   3778   v8::Local<v8::Value> obj1;
   3779   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   3780 
   3781   {
   3782     LocalContext env;
   3783     CompileRun("function fun() { this.x = 1; }; var obj = new fun();");
   3784     obj1 = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   3785   }
   3786 
   3787   // Prepare function f that contains a monomorphic IC for object
   3788   // originating from a different native context.
   3789   CHECK(CcTest::global()->Set(ctx, v8_str("obj1"), obj1).FromJust());
   3790   CompileRun("function f(o) { return o.x; } f(obj1); f(obj1);");
   3791   Handle<JSFunction> f = Handle<JSFunction>::cast(
   3792       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   3793           CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
   3794 
   3795   CheckVectorIC(f, 0, MONOMORPHIC);
   3796 
   3797   // Fire context dispose notification.
   3798   CcTest::isolate()->ContextDisposedNotification();
   3799   SimulateIncrementalMarking(CcTest::heap());
   3800   CcTest::heap()->CollectAllGarbage();
   3801 
   3802   CheckVectorICCleared(f, 0);
   3803 }
   3804 
   3805 
   3806 TEST(IncrementalMarkingPreservesPolymorphicIC) {
   3807   if (i::FLAG_always_opt) return;
   3808   CcTest::InitializeVM();
   3809   v8::HandleScope scope(CcTest::isolate());
   3810   v8::Local<v8::Value> obj1, obj2;
   3811   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   3812 
   3813   {
   3814     LocalContext env;
   3815     CompileRun("function fun() { this.x = 1; }; var obj = new fun();");
   3816     obj1 = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   3817   }
   3818 
   3819   {
   3820     LocalContext env;
   3821     CompileRun("function fun() { this.x = 2; }; var obj = new fun();");
   3822     obj2 = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   3823   }
   3824 
   3825   // Prepare function f that contains a polymorphic IC for objects
   3826   // originating from two different native contexts.
   3827   CHECK(CcTest::global()->Set(ctx, v8_str("obj1"), obj1).FromJust());
   3828   CHECK(CcTest::global()->Set(ctx, v8_str("obj2"), obj2).FromJust());
   3829   CompileRun("function f(o) { return o.x; } f(obj1); f(obj1); f(obj2);");
   3830   Handle<JSFunction> f = Handle<JSFunction>::cast(
   3831       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   3832           CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
   3833 
   3834   CheckVectorIC(f, 0, POLYMORPHIC);
   3835 
   3836   // Fire context dispose notification.
   3837   SimulateIncrementalMarking(CcTest::heap());
   3838   CcTest::heap()->CollectAllGarbage();
   3839 
   3840   CheckVectorIC(f, 0, POLYMORPHIC);
   3841 }
   3842 
   3843 
   3844 TEST(IncrementalMarkingClearsPolymorphicIC) {
   3845   if (i::FLAG_always_opt) return;
   3846   CcTest::InitializeVM();
   3847   v8::HandleScope scope(CcTest::isolate());
   3848   v8::Local<v8::Value> obj1, obj2;
   3849   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
   3850 
   3851   {
   3852     LocalContext env;
   3853     CompileRun("function fun() { this.x = 1; }; var obj = new fun();");
   3854     obj1 = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   3855   }
   3856 
   3857   {
   3858     LocalContext env;
   3859     CompileRun("function fun() { this.x = 2; }; var obj = new fun();");
   3860     obj2 = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   3861   }
   3862 
   3863   // Prepare function f that contains a polymorphic IC for objects
   3864   // originating from two different native contexts.
   3865   CHECK(CcTest::global()->Set(ctx, v8_str("obj1"), obj1).FromJust());
   3866   CHECK(CcTest::global()->Set(ctx, v8_str("obj2"), obj2).FromJust());
   3867   CompileRun("function f(o) { return o.x; } f(obj1); f(obj1); f(obj2);");
   3868   Handle<JSFunction> f = Handle<JSFunction>::cast(
   3869       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   3870           CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
   3871 
   3872   CheckVectorIC(f, 0, POLYMORPHIC);
   3873 
   3874   // Fire context dispose notification.
   3875   CcTest::isolate()->ContextDisposedNotification();
   3876   SimulateIncrementalMarking(CcTest::heap());
   3877   CcTest::heap()->CollectAllGarbage();
   3878 
   3879   CheckVectorICCleared(f, 0);
   3880 }
   3881 
   3882 
   3883 class SourceResource : public v8::String::ExternalOneByteStringResource {
   3884  public:
   3885   explicit SourceResource(const char* data)
   3886     : data_(data), length_(strlen(data)) { }
   3887 
   3888   virtual void Dispose() {
   3889     i::DeleteArray(data_);
   3890     data_ = NULL;
   3891   }
   3892 
   3893   const char* data() const { return data_; }
   3894 
   3895   size_t length() const { return length_; }
   3896 
   3897   bool IsDisposed() { return data_ == NULL; }
   3898 
   3899  private:
   3900   const char* data_;
   3901   size_t length_;
   3902 };
   3903 
   3904 
   3905 void ReleaseStackTraceDataTest(v8::Isolate* isolate, const char* source,
   3906                                const char* accessor) {
   3907   // Test that the data retained by the Error.stack accessor is released
   3908   // after the first time the accessor is fired.  We use external string
   3909   // to check whether the data is being released since the external string
   3910   // resource's callback is fired when the external string is GC'ed.
   3911   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   3912   v8::HandleScope scope(isolate);
   3913   SourceResource* resource = new SourceResource(i::StrDup(source));
   3914   {
   3915     v8::HandleScope scope(isolate);
   3916     v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
   3917     v8::Local<v8::String> source_string =
   3918         v8::String::NewExternalOneByte(isolate, resource).ToLocalChecked();
   3919     i_isolate->heap()->CollectAllAvailableGarbage();
   3920     v8::Script::Compile(ctx, source_string)
   3921         .ToLocalChecked()
   3922         ->Run(ctx)
   3923         .ToLocalChecked();
   3924     CHECK(!resource->IsDisposed());
   3925   }
   3926   // i_isolate->heap()->CollectAllAvailableGarbage();
   3927   CHECK(!resource->IsDisposed());
   3928 
   3929   CompileRun(accessor);
   3930   i_isolate->heap()->CollectAllAvailableGarbage();
   3931 
   3932   // External source has been released.
   3933   CHECK(resource->IsDisposed());
   3934   delete resource;
   3935 }
   3936 
   3937 
   3938 UNINITIALIZED_TEST(ReleaseStackTraceData) {
   3939   if (i::FLAG_always_opt) {
   3940     // TODO(ulan): Remove this once the memory leak via code_next_link is fixed.
   3941     // See: https://codereview.chromium.org/181833004/
   3942     return;
   3943   }
   3944   FLAG_use_ic = false;  // ICs retain objects.
   3945   FLAG_concurrent_recompilation = false;
   3946   v8::Isolate::CreateParams create_params;
   3947   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   3948   v8::Isolate* isolate = v8::Isolate::New(create_params);
   3949   {
   3950     v8::Isolate::Scope isolate_scope(isolate);
   3951     v8::HandleScope handle_scope(isolate);
   3952     v8::Context::New(isolate)->Enter();
   3953     static const char* source1 = "var error = null;            "
   3954     /* Normal Error */           "try {                        "
   3955                                  "  throw new Error();         "
   3956                                  "} catch (e) {                "
   3957                                  "  error = e;                 "
   3958                                  "}                            ";
   3959     static const char* source2 = "var error = null;            "
   3960     /* Stack overflow */         "try {                        "
   3961                                  "  (function f() { f(); })(); "
   3962                                  "} catch (e) {                "
   3963                                  "  error = e;                 "
   3964                                  "}                            ";
   3965     static const char* source3 = "var error = null;            "
   3966     /* Normal Error */           "try {                        "
   3967     /* as prototype */           "  throw new Error();         "
   3968                                  "} catch (e) {                "
   3969                                  "  error = {};                "
   3970                                  "  error.__proto__ = e;       "
   3971                                  "}                            ";
   3972     static const char* source4 = "var error = null;            "
   3973     /* Stack overflow */         "try {                        "
   3974     /* as prototype   */         "  (function f() { f(); })(); "
   3975                                  "} catch (e) {                "
   3976                                  "  error = {};                "
   3977                                  "  error.__proto__ = e;       "
   3978                                  "}                            ";
   3979     static const char* getter = "error.stack";
   3980     static const char* setter = "error.stack = 0";
   3981 
   3982     ReleaseStackTraceDataTest(isolate, source1, setter);
   3983     ReleaseStackTraceDataTest(isolate, source2, setter);
   3984     // We do not test source3 and source4 with setter, since the setter is
   3985     // supposed to (untypically) write to the receiver, not the holder.  This is
   3986     // to emulate the behavior of a data property.
   3987 
   3988     ReleaseStackTraceDataTest(isolate, source1, getter);
   3989     ReleaseStackTraceDataTest(isolate, source2, getter);
   3990     ReleaseStackTraceDataTest(isolate, source3, getter);
   3991     ReleaseStackTraceDataTest(isolate, source4, getter);
   3992   }
   3993   isolate->Dispose();
   3994 }
   3995 
   3996 
   3997 TEST(Regress159140) {
   3998   i::FLAG_allow_natives_syntax = true;
   3999   CcTest::InitializeVM();
   4000   Isolate* isolate = CcTest::i_isolate();
   4001   LocalContext env;
   4002   Heap* heap = isolate->heap();
   4003   HandleScope scope(isolate);
   4004 
   4005   // Perform one initial GC to enable code flushing.
   4006   heap->CollectAllGarbage();
   4007 
   4008   // Prepare several closures that are all eligible for code flushing
   4009   // because all reachable ones are not optimized. Make sure that the
   4010   // optimized code object is directly reachable through a handle so
   4011   // that it is marked black during incremental marking.
   4012   Handle<Code> code;
   4013   {
   4014     HandleScope inner_scope(isolate);
   4015     CompileRun("function h(x) {}"
   4016                "function mkClosure() {"
   4017                "  return function(x) { return x + 1; };"
   4018                "}"
   4019                "var f = mkClosure();"
   4020                "var g = mkClosure();"
   4021                "f(1); f(2);"
   4022                "g(1); g(2);"
   4023                "h(1); h(2);"
   4024                "%OptimizeFunctionOnNextCall(f); f(3);"
   4025                "%OptimizeFunctionOnNextCall(h); h(3);");
   4026 
   4027     Handle<JSFunction> f = Handle<JSFunction>::cast(
   4028         v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   4029             CcTest::global()->Get(env.local(), v8_str("f")).ToLocalChecked())));
   4030     CHECK(f->is_compiled());
   4031     CompileRun("f = null;");
   4032 
   4033     Handle<JSFunction> g = Handle<JSFunction>::cast(
   4034         v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   4035             CcTest::global()->Get(env.local(), v8_str("g")).ToLocalChecked())));
   4036     CHECK(g->is_compiled());
   4037     const int kAgingThreshold = 6;
   4038     for (int i = 0; i < kAgingThreshold; i++) {
   4039       g->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
   4040     }
   4041 
   4042     code = inner_scope.CloseAndEscape(Handle<Code>(f->code()));
   4043   }
   4044 
   4045   // Simulate incremental marking so that the functions are enqueued as
   4046   // code flushing candidates. Then optimize one function. Finally
   4047   // finish the GC to complete code flushing.
   4048   SimulateIncrementalMarking(heap);
   4049   CompileRun("%OptimizeFunctionOnNextCall(g); g(3);");
   4050   heap->CollectAllGarbage();
   4051 
   4052   // Unoptimized code is missing and the deoptimizer will go ballistic.
   4053   CompileRun("g('bozo');");
   4054 }
   4055 
   4056 
   4057 TEST(Regress165495) {
   4058   i::FLAG_allow_natives_syntax = true;
   4059   CcTest::InitializeVM();
   4060   Isolate* isolate = CcTest::i_isolate();
   4061   Heap* heap = isolate->heap();
   4062   HandleScope scope(isolate);
   4063 
   4064   // Perform one initial GC to enable code flushing.
   4065   heap->CollectAllGarbage();
   4066 
   4067   // Prepare an optimized closure that the optimized code map will get
   4068   // populated. Then age the unoptimized code to trigger code flushing
   4069   // but make sure the optimized code is unreachable.
   4070   {
   4071     HandleScope inner_scope(isolate);
   4072     LocalContext env;
   4073     CompileRun("function mkClosure() {"
   4074                "  return function(x) { return x + 1; };"
   4075                "}"
   4076                "var f = mkClosure();"
   4077                "f(1); f(2);"
   4078                "%OptimizeFunctionOnNextCall(f); f(3);");
   4079 
   4080     Handle<JSFunction> f = Handle<JSFunction>::cast(
   4081         v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   4082             CcTest::global()->Get(env.local(), v8_str("f")).ToLocalChecked())));
   4083     CHECK(f->is_compiled());
   4084     const int kAgingThreshold = 6;
   4085     for (int i = 0; i < kAgingThreshold; i++) {
   4086       f->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
   4087     }
   4088 
   4089     CompileRun("f = null;");
   4090   }
   4091 
   4092   // Simulate incremental marking so that unoptimized code is flushed
   4093   // even though it still is cached in the optimized code map.
   4094   SimulateIncrementalMarking(heap);
   4095   heap->CollectAllGarbage();
   4096 
   4097   // Make a new closure that will get code installed from the code map.
   4098   // Unoptimized code is missing and the deoptimizer will go ballistic.
   4099   CompileRun("var g = mkClosure(); g('bozo');");
   4100 }
   4101 
   4102 
   4103 TEST(Regress169209) {
   4104   i::FLAG_stress_compaction = false;
   4105   i::FLAG_allow_natives_syntax = true;
   4106 
   4107   CcTest::InitializeVM();
   4108   Isolate* isolate = CcTest::i_isolate();
   4109   Heap* heap = isolate->heap();
   4110   HandleScope scope(isolate);
   4111 
   4112   // Perform one initial GC to enable code flushing.
   4113   heap->CollectAllGarbage();
   4114 
   4115   // Prepare a shared function info eligible for code flushing for which
   4116   // the unoptimized code will be replaced during optimization.
   4117   Handle<SharedFunctionInfo> shared1;
   4118   {
   4119     HandleScope inner_scope(isolate);
   4120     LocalContext env;
   4121     CompileRun("function f() { return 'foobar'; }"
   4122                "function g(x) { if (x) f(); }"
   4123                "f();"
   4124                "g(false);"
   4125                "g(false);");
   4126 
   4127     Handle<JSFunction> f = Handle<JSFunction>::cast(
   4128         v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   4129             CcTest::global()->Get(env.local(), v8_str("f")).ToLocalChecked())));
   4130     CHECK(f->is_compiled());
   4131     const int kAgingThreshold = 6;
   4132     for (int i = 0; i < kAgingThreshold; i++) {
   4133       f->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
   4134     }
   4135 
   4136     shared1 = inner_scope.CloseAndEscape(handle(f->shared(), isolate));
   4137   }
   4138 
   4139   // Prepare a shared function info eligible for code flushing that will
   4140   // represent the dangling tail of the candidate list.
   4141   Handle<SharedFunctionInfo> shared2;
   4142   {
   4143     HandleScope inner_scope(isolate);
   4144     LocalContext env;
   4145     CompileRun("function flushMe() { return 0; }"
   4146                "flushMe(1);");
   4147 
   4148     Handle<JSFunction> f = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
   4149         *v8::Local<v8::Function>::Cast(CcTest::global()
   4150                                            ->Get(env.local(), v8_str("flushMe"))
   4151                                            .ToLocalChecked())));
   4152     CHECK(f->is_compiled());
   4153     const int kAgingThreshold = 6;
   4154     for (int i = 0; i < kAgingThreshold; i++) {
   4155       f->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
   4156     }
   4157 
   4158     shared2 = inner_scope.CloseAndEscape(handle(f->shared(), isolate));
   4159   }
   4160 
   4161   // Simulate incremental marking and collect code flushing candidates.
   4162   SimulateIncrementalMarking(heap);
   4163   CHECK(shared1->code()->gc_metadata() != NULL);
   4164 
   4165   // Optimize function and make sure the unoptimized code is replaced.
   4166 #ifdef DEBUG
   4167   FLAG_stop_at = "f";
   4168 #endif
   4169   CompileRun("%OptimizeFunctionOnNextCall(g);"
   4170              "g(false);");
   4171 
   4172   // Finish garbage collection cycle.
   4173   heap->CollectAllGarbage();
   4174   CHECK(shared1->code()->gc_metadata() == NULL);
   4175 }
   4176 
   4177 
   4178 TEST(Regress169928) {
   4179   i::FLAG_allow_natives_syntax = true;
   4180   i::FLAG_crankshaft = false;
   4181   CcTest::InitializeVM();
   4182   Isolate* isolate = CcTest::i_isolate();
   4183   LocalContext env;
   4184   Factory* factory = isolate->factory();
   4185   v8::HandleScope scope(CcTest::isolate());
   4186 
   4187   // Some flags turn Scavenge collections into Mark-sweep collections
   4188   // and hence are incompatible with this test case.
   4189   if (FLAG_gc_global || FLAG_stress_compaction) return;
   4190 
   4191   // Prepare the environment
   4192   CompileRun("function fastliteralcase(literal, value) {"
   4193              "    literal[0] = value;"
   4194              "    return literal;"
   4195              "}"
   4196              "function get_standard_literal() {"
   4197              "    var literal = [1, 2, 3];"
   4198              "    return literal;"
   4199              "}"
   4200              "obj = fastliteralcase(get_standard_literal(), 1);"
   4201              "obj = fastliteralcase(get_standard_literal(), 1.5);"
   4202              "obj = fastliteralcase(get_standard_literal(), 2);");
   4203 
   4204   // prepare the heap
   4205   v8::Local<v8::String> mote_code_string =
   4206       v8_str("fastliteralcase(mote, 2.5);");
   4207 
   4208   v8::Local<v8::String> array_name = v8_str("mote");
   4209   CHECK(CcTest::global()
   4210             ->Set(env.local(), array_name, v8::Int32::New(CcTest::isolate(), 0))
   4211             .FromJust());
   4212 
   4213   // First make sure we flip spaces
   4214   CcTest::heap()->CollectGarbage(NEW_SPACE);
   4215 
   4216   // Allocate the object.
   4217   Handle<FixedArray> array_data = factory->NewFixedArray(2, NOT_TENURED);
   4218   array_data->set(0, Smi::FromInt(1));
   4219   array_data->set(1, Smi::FromInt(2));
   4220 
   4221   AllocateAllButNBytes(CcTest::heap()->new_space(),
   4222                        JSArray::kSize + AllocationMemento::kSize +
   4223                        kPointerSize);
   4224 
   4225   Handle<JSArray> array =
   4226       factory->NewJSArrayWithElements(array_data, FAST_SMI_ELEMENTS);
   4227 
   4228   CHECK_EQ(Smi::FromInt(2), array->length());
   4229   CHECK(array->HasFastSmiOrObjectElements());
   4230 
   4231   // We need filler the size of AllocationMemento object, plus an extra
   4232   // fill pointer value.
   4233   HeapObject* obj = NULL;
   4234   AllocationResult allocation =
   4235       CcTest::heap()->new_space()->AllocateRawUnaligned(
   4236           AllocationMemento::kSize + kPointerSize);
   4237   CHECK(allocation.To(&obj));
   4238   Address addr_obj = obj->address();
   4239   CcTest::heap()->CreateFillerObjectAt(
   4240       addr_obj, AllocationMemento::kSize + kPointerSize);
   4241 
   4242   // Give the array a name, making sure not to allocate strings.
   4243   v8::Local<v8::Object> array_obj = v8::Utils::ToLocal(array);
   4244   CHECK(CcTest::global()->Set(env.local(), array_name, array_obj).FromJust());
   4245 
   4246   // This should crash with a protection violation if we are running a build
   4247   // with the bug.
   4248   AlwaysAllocateScope aa_scope(isolate);
   4249   v8::Script::Compile(env.local(), mote_code_string)
   4250       .ToLocalChecked()
   4251       ->Run(env.local())
   4252       .ToLocalChecked();
   4253 }
   4254 
   4255 
   4256 #ifdef DEBUG
   4257 TEST(Regress513507) {
   4258   i::FLAG_flush_optimized_code_cache = false;
   4259   i::FLAG_allow_natives_syntax = true;
   4260   i::FLAG_gc_global = true;
   4261   CcTest::InitializeVM();
   4262   Isolate* isolate = CcTest::i_isolate();
   4263   LocalContext env;
   4264   Heap* heap = isolate->heap();
   4265   HandleScope scope(isolate);
   4266 
   4267   // Prepare function whose optimized code map we can use.
   4268   Handle<SharedFunctionInfo> shared;
   4269   {
   4270     HandleScope inner_scope(isolate);
   4271     CompileRun("function f() { return 1 }"
   4272                "f(); %OptimizeFunctionOnNextCall(f); f();");
   4273 
   4274     Handle<JSFunction> f = Handle<JSFunction>::cast(
   4275         v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   4276             CcTest::global()->Get(env.local(), v8_str("f")).ToLocalChecked())));
   4277     shared = inner_scope.CloseAndEscape(handle(f->shared(), isolate));
   4278     CompileRun("f = null");
   4279   }
   4280 
   4281   // Prepare optimized code that we can use.
   4282   Handle<Code> code;
   4283   {
   4284     HandleScope inner_scope(isolate);
   4285     CompileRun("function g() { return 2 }"
   4286                "g(); %OptimizeFunctionOnNextCall(g); g();");
   4287 
   4288     Handle<JSFunction> g = Handle<JSFunction>::cast(
   4289         v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   4290             CcTest::global()->Get(env.local(), v8_str("g")).ToLocalChecked())));
   4291     code = inner_scope.CloseAndEscape(handle(g->code(), isolate));
   4292     if (!code->is_optimized_code()) return;
   4293   }
   4294 
   4295   Handle<TypeFeedbackVector> vector = handle(shared->feedback_vector());
   4296   Handle<LiteralsArray> lit =
   4297       LiteralsArray::New(isolate, vector, shared->num_literals(), TENURED);
   4298   Handle<Context> context(isolate->context());
   4299 
   4300   // Add the new code several times to the optimized code map and also set an
   4301   // allocation timeout so that expanding the code map will trigger a GC.
   4302   heap->set_allocation_timeout(5);
   4303   FLAG_gc_interval = 1000;
   4304   for (int i = 0; i < 10; ++i) {
   4305     BailoutId id = BailoutId(i);
   4306     SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, lit, id);
   4307   }
   4308 }
   4309 #endif  // DEBUG
   4310 
   4311 
   4312 TEST(Regress514122) {
   4313   i::FLAG_flush_optimized_code_cache = false;
   4314   i::FLAG_allow_natives_syntax = true;
   4315   CcTest::InitializeVM();
   4316   Isolate* isolate = CcTest::i_isolate();
   4317   LocalContext env;
   4318   Heap* heap = isolate->heap();
   4319   HandleScope scope(isolate);
   4320 
   4321   // Perfrom one initial GC to enable code flushing.
   4322   CcTest::heap()->CollectAllGarbage();
   4323 
   4324   // Prepare function whose optimized code map we can use.
   4325   Handle<SharedFunctionInfo> shared;
   4326   {
   4327     HandleScope inner_scope(isolate);
   4328     CompileRun("function f() { return 1 }"
   4329                "f(); %OptimizeFunctionOnNextCall(f); f();");
   4330 
   4331     Handle<JSFunction> f = Handle<JSFunction>::cast(
   4332         v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   4333             CcTest::global()->Get(env.local(), v8_str("f")).ToLocalChecked())));
   4334     shared = inner_scope.CloseAndEscape(handle(f->shared(), isolate));
   4335     CompileRun("f = null");
   4336   }
   4337 
   4338   // Prepare optimized code that we can use.
   4339   Handle<Code> code;
   4340   {
   4341     HandleScope inner_scope(isolate);
   4342     CompileRun("function g() { return 2 }"
   4343                "g(); %OptimizeFunctionOnNextCall(g); g();");
   4344 
   4345     Handle<JSFunction> g = Handle<JSFunction>::cast(
   4346         v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   4347             CcTest::global()->Get(env.local(), v8_str("g")).ToLocalChecked())));
   4348     code = inner_scope.CloseAndEscape(handle(g->code(), isolate));
   4349     if (!code->is_optimized_code()) return;
   4350   }
   4351 
   4352   Handle<TypeFeedbackVector> vector = handle(shared->feedback_vector());
   4353   Handle<LiteralsArray> lit =
   4354       LiteralsArray::New(isolate, vector, shared->num_literals(), TENURED);
   4355   Handle<Context> context(isolate->context());
   4356 
   4357   // Add the code several times to the optimized code map.
   4358   for (int i = 0; i < 3; ++i) {
   4359     HandleScope inner_scope(isolate);
   4360     BailoutId id = BailoutId(i);
   4361     SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, lit, id);
   4362   }
   4363   shared->optimized_code_map()->Print();
   4364 
   4365   // Add the code with a literals array to be evacuated.
   4366   Page* evac_page;
   4367   {
   4368     HandleScope inner_scope(isolate);
   4369     AlwaysAllocateScope always_allocate(isolate);
   4370     // Make sure literal is placed on an old-space evacuation candidate.
   4371     SimulateFullSpace(heap->old_space());
   4372 
   4373     // Make sure there the number of literals is > 0.
   4374     Handle<LiteralsArray> lit =
   4375         LiteralsArray::New(isolate, vector, 23, TENURED);
   4376 
   4377     evac_page = Page::FromAddress(lit->address());
   4378     BailoutId id = BailoutId(100);
   4379     SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, lit, id);
   4380   }
   4381 
   4382   // Heap is ready, force {lit_page} to become an evacuation candidate and
   4383   // simulate incremental marking to enqueue optimized code map.
   4384   FLAG_manual_evacuation_candidates_selection = true;
   4385   evac_page->SetFlag(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
   4386   SimulateIncrementalMarking(heap);
   4387 
   4388   // No matter whether reachable or not, {boomer} is doomed.
   4389   Handle<Object> boomer(shared->optimized_code_map(), isolate);
   4390 
   4391   // Add the code several times to the optimized code map. This will leave old
   4392   // copies of the optimized code map unreachable but still marked.
   4393   for (int i = 3; i < 6; ++i) {
   4394     HandleScope inner_scope(isolate);
   4395     BailoutId id = BailoutId(i);
   4396     SharedFunctionInfo::AddToOptimizedCodeMap(shared, context, code, lit, id);
   4397   }
   4398 
   4399   // Trigger a GC to flush out the bug.
   4400   heap->CollectGarbage(i::OLD_SPACE, "fire in the hole");
   4401   boomer->Print();
   4402 }
   4403 
   4404 
   4405 TEST(OptimizedCodeMapReuseEntries) {
   4406   i::FLAG_flush_optimized_code_cache = false;
   4407   i::FLAG_allow_natives_syntax = true;
   4408   // BUG(v8:4598): Since TurboFan doesn't treat maps in code weakly, we can't
   4409   // run this test.
   4410   if (i::FLAG_turbo) return;
   4411   CcTest::InitializeVM();
   4412   v8::Isolate* v8_isolate = CcTest::isolate();
   4413   Isolate* isolate = CcTest::i_isolate();
   4414   Heap* heap = isolate->heap();
   4415   HandleScope scope(isolate);
   4416 
   4417   // Create 3 contexts, allow the 2nd one to be disposed, and verify that
   4418   // a 4th context will re-use the weak slots in the optimized code map
   4419   // to hold data, rather than expanding the map.
   4420   v8::Local<v8::Context> c1 = v8::Context::New(v8_isolate);
   4421   const char* source = "function foo(x) { var l = [1]; return x+l[0]; }";
   4422   v8::ScriptCompiler::Source script_source(
   4423       v8::String::NewFromUtf8(v8_isolate, source, v8::NewStringType::kNormal)
   4424           .ToLocalChecked());
   4425   v8::Local<v8::UnboundScript> indep =
   4426       v8::ScriptCompiler::CompileUnboundScript(v8_isolate, &script_source)
   4427           .ToLocalChecked();
   4428   const char* toplevel = "foo(3); %OptimizeFunctionOnNextCall(foo); foo(3);";
   4429   // Perfrom one initial GC to enable code flushing.
   4430   heap->CollectAllGarbage();
   4431 
   4432   c1->Enter();
   4433   indep->BindToCurrentContext()->Run(c1).ToLocalChecked();
   4434   CompileRun(toplevel);
   4435 
   4436   Handle<SharedFunctionInfo> shared;
   4437   Handle<JSFunction> foo = Handle<JSFunction>::cast(
   4438       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   4439           CcTest::global()->Get(c1, v8_str("foo")).ToLocalChecked())));
   4440   CHECK(foo->shared()->is_compiled());
   4441   shared = handle(foo->shared());
   4442   c1->Exit();
   4443 
   4444   {
   4445     HandleScope scope(isolate);
   4446     v8::Local<v8::Context> c2 = v8::Context::New(v8_isolate);
   4447     c2->Enter();
   4448     indep->BindToCurrentContext()->Run(c2).ToLocalChecked();
   4449     CompileRun(toplevel);
   4450     c2->Exit();
   4451   }
   4452 
   4453   {
   4454     HandleScope scope(isolate);
   4455     v8::Local<v8::Context> c3 = v8::Context::New(v8_isolate);
   4456     c3->Enter();
   4457     indep->BindToCurrentContext()->Run(c3).ToLocalChecked();
   4458     CompileRun(toplevel);
   4459     c3->Exit();
   4460 
   4461     // Now, collect garbage. Context c2 should have no roots to it, and it's
   4462     // entry in the optimized code map should be free for a new context.
   4463     for (int i = 0; i < 4; i++) {
   4464       heap->CollectAllGarbage();
   4465     }
   4466 
   4467     Handle<FixedArray> optimized_code_map =
   4468         handle(shared->optimized_code_map());
   4469     // There should be 3 entries in the map.
   4470     CHECK_EQ(
   4471         3, ((optimized_code_map->length() - SharedFunctionInfo::kEntriesStart) /
   4472             SharedFunctionInfo::kEntryLength));
   4473     // But one of them (formerly for c2) should be cleared.
   4474     int cleared_count = 0;
   4475     for (int i = SharedFunctionInfo::kEntriesStart;
   4476          i < optimized_code_map->length();
   4477          i += SharedFunctionInfo::kEntryLength) {
   4478       cleared_count +=
   4479           WeakCell::cast(
   4480               optimized_code_map->get(i + SharedFunctionInfo::kContextOffset))
   4481                   ->cleared()
   4482               ? 1
   4483               : 0;
   4484     }
   4485     CHECK_EQ(1, cleared_count);
   4486 
   4487     // Verify that a new context uses the cleared entry rather than creating a
   4488     // new
   4489     // optimized code map array.
   4490     v8::Local<v8::Context> c4 = v8::Context::New(v8_isolate);
   4491     c4->Enter();
   4492     indep->BindToCurrentContext()->Run(c4).ToLocalChecked();
   4493     CompileRun(toplevel);
   4494     c4->Exit();
   4495     CHECK_EQ(*optimized_code_map, shared->optimized_code_map());
   4496 
   4497     // Now each entry is in use.
   4498     cleared_count = 0;
   4499     for (int i = SharedFunctionInfo::kEntriesStart;
   4500          i < optimized_code_map->length();
   4501          i += SharedFunctionInfo::kEntryLength) {
   4502       cleared_count +=
   4503           WeakCell::cast(
   4504               optimized_code_map->get(i + SharedFunctionInfo::kContextOffset))
   4505                   ->cleared()
   4506               ? 1
   4507               : 0;
   4508     }
   4509     CHECK_EQ(0, cleared_count);
   4510   }
   4511 }
   4512 
   4513 
   4514 TEST(Regress513496) {
   4515   i::FLAG_flush_optimized_code_cache = false;
   4516   i::FLAG_allow_natives_syntax = true;
   4517   CcTest::InitializeVM();
   4518   Isolate* isolate = CcTest::i_isolate();
   4519   Heap* heap = isolate->heap();
   4520   HandleScope scope(isolate);
   4521 
   4522   // Perfrom one initial GC to enable code flushing.
   4523   CcTest::heap()->CollectAllGarbage();
   4524 
   4525   // Prepare an optimized closure with containing an inlined function. Then age
   4526   // the inlined unoptimized code to trigger code flushing but make sure the
   4527   // outer optimized code is kept in the optimized code map.
   4528   Handle<SharedFunctionInfo> shared;
   4529   {
   4530     LocalContext context;
   4531     HandleScope inner_scope(isolate);
   4532     CompileRun(
   4533         "function g(x) { return x + 1 }"
   4534         "function mkClosure() {"
   4535         "  return function(x) { return g(x); };"
   4536         "}"
   4537         "var f = mkClosure();"
   4538         "f(1); f(2);"
   4539         "%OptimizeFunctionOnNextCall(f); f(3);");
   4540 
   4541     Handle<JSFunction> g = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
   4542         *v8::Local<v8::Function>::Cast(CcTest::global()
   4543                                            ->Get(context.local(), v8_str("g"))
   4544                                            .ToLocalChecked())));
   4545     CHECK(g->shared()->is_compiled());
   4546     const int kAgingThreshold = 6;
   4547     for (int i = 0; i < kAgingThreshold; i++) {
   4548       g->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
   4549     }
   4550 
   4551     Handle<JSFunction> f = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
   4552         *v8::Local<v8::Function>::Cast(CcTest::global()
   4553                                            ->Get(context.local(), v8_str("f"))
   4554                                            .ToLocalChecked())));
   4555     CHECK(f->is_compiled());
   4556     shared = inner_scope.CloseAndEscape(handle(f->shared(), isolate));
   4557     CompileRun("f = null");
   4558   }
   4559 
   4560   // Lookup the optimized code and keep it alive.
   4561   CodeAndLiterals result = shared->SearchOptimizedCodeMap(
   4562       isolate->context()->native_context(), BailoutId::None());
   4563   Handle<Code> optimized_code(result.code, isolate);
   4564 
   4565   // Finish a full GC cycle so that the unoptimized code of 'g' is flushed even
   4566   // though the optimized code for 'f' is reachable via the optimized code map.
   4567   heap->CollectAllGarbage();
   4568 
   4569   // Make a new closure that will get code installed from the code map.
   4570   // Unoptimized code is missing and the deoptimizer will go ballistic.
   4571   CompileRun("var h = mkClosure(); h('bozo');");
   4572 }
   4573 
   4574 
   4575 TEST(LargeObjectSlotRecording) {
   4576   FLAG_manual_evacuation_candidates_selection = true;
   4577   CcTest::InitializeVM();
   4578   Isolate* isolate = CcTest::i_isolate();
   4579   Heap* heap = isolate->heap();
   4580   HandleScope scope(isolate);
   4581 
   4582   // Create an object on an evacuation candidate.
   4583   SimulateFullSpace(heap->old_space());
   4584   Handle<FixedArray> lit = isolate->factory()->NewFixedArray(4, TENURED);
   4585   Page* evac_page = Page::FromAddress(lit->address());
   4586   evac_page->SetFlag(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
   4587   FixedArray* old_location = *lit;
   4588 
   4589   // Allocate a large object.
   4590   int size = Max(1000000, Page::kMaxRegularHeapObjectSize + KB);
   4591   CHECK(size > Page::kMaxRegularHeapObjectSize);
   4592   Handle<FixedArray> lo = isolate->factory()->NewFixedArray(size, TENURED);
   4593   CHECK(heap->lo_space()->Contains(*lo));
   4594 
   4595   // Start incremental marking to active write barrier.
   4596   SimulateIncrementalMarking(heap, false);
   4597   heap->incremental_marking()->AdvanceIncrementalMarking(
   4598       10000000, 10000000, IncrementalMarking::IdleStepActions());
   4599 
   4600   // Create references from the large object to the object on the evacuation
   4601   // candidate.
   4602   const int kStep = size / 10;
   4603   for (int i = 0; i < size; i += kStep) {
   4604     lo->set(i, *lit);
   4605     CHECK(lo->get(i) == old_location);
   4606   }
   4607 
   4608   // Move the evaucation candidate object.
   4609   CcTest::heap()->CollectAllGarbage();
   4610 
   4611   // Verify that the pointers in the large object got updated.
   4612   for (int i = 0; i < size; i += kStep) {
   4613     CHECK_EQ(lo->get(i), *lit);
   4614     CHECK(lo->get(i) != old_location);
   4615   }
   4616 }
   4617 
   4618 
   4619 class DummyVisitor : public ObjectVisitor {
   4620  public:
   4621   void VisitPointers(Object** start, Object** end) override {}
   4622 };
   4623 
   4624 
   4625 TEST(DeferredHandles) {
   4626   CcTest::InitializeVM();
   4627   Isolate* isolate = CcTest::i_isolate();
   4628   Heap* heap = isolate->heap();
   4629   v8::HandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));
   4630   HandleScopeData* data = isolate->handle_scope_data();
   4631   Handle<Object> init(heap->empty_string(), isolate);
   4632   while (data->next < data->limit) {
   4633     Handle<Object> obj(heap->empty_string(), isolate);
   4634   }
   4635   // An entire block of handles has been filled.
   4636   // Next handle would require a new block.
   4637   CHECK(data->next == data->limit);
   4638 
   4639   DeferredHandleScope deferred(isolate);
   4640   DummyVisitor visitor;
   4641   isolate->handle_scope_implementer()->Iterate(&visitor);
   4642   delete deferred.Detach();
   4643 }
   4644 
   4645 
   4646 TEST(IncrementalMarkingStepMakesBigProgressWithLargeObjects) {
   4647   CcTest::InitializeVM();
   4648   v8::HandleScope scope(CcTest::isolate());
   4649   CompileRun("function f(n) {"
   4650              "    var a = new Array(n);"
   4651              "    for (var i = 0; i < n; i += 100) a[i] = i;"
   4652              "};"
   4653              "f(10 * 1024 * 1024);");
   4654   IncrementalMarking* marking = CcTest::heap()->incremental_marking();
   4655   if (marking->IsStopped()) {
   4656     CcTest::heap()->StartIncrementalMarking();
   4657   }
   4658   // This big step should be sufficient to mark the whole array.
   4659   marking->Step(100 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
   4660   CHECK(marking->IsComplete() ||
   4661         marking->IsReadyToOverApproximateWeakClosure());
   4662 }
   4663 
   4664 
   4665 TEST(DisableInlineAllocation) {
   4666   i::FLAG_allow_natives_syntax = true;
   4667   CcTest::InitializeVM();
   4668   v8::HandleScope scope(CcTest::isolate());
   4669   CompileRun("function test() {"
   4670              "  var x = [];"
   4671              "  for (var i = 0; i < 10; i++) {"
   4672              "    x[i] = [ {}, [1,2,3], [1,x,3] ];"
   4673              "  }"
   4674              "}"
   4675              "function run() {"
   4676              "  %OptimizeFunctionOnNextCall(test);"
   4677              "  test();"
   4678              "  %DeoptimizeFunction(test);"
   4679              "}");
   4680 
   4681   // Warm-up with inline allocation enabled.
   4682   CompileRun("test(); test(); run();");
   4683 
   4684   // Run test with inline allocation disabled.
   4685   CcTest::heap()->DisableInlineAllocation();
   4686   CompileRun("run()");
   4687 
   4688   // Run test with inline allocation re-enabled.
   4689   CcTest::heap()->EnableInlineAllocation();
   4690   CompileRun("run()");
   4691 }
   4692 
   4693 
   4694 static int AllocationSitesCount(Heap* heap) {
   4695   int count = 0;
   4696   for (Object* site = heap->allocation_sites_list();
   4697        !(site->IsUndefined());
   4698        site = AllocationSite::cast(site)->weak_next()) {
   4699     count++;
   4700   }
   4701   return count;
   4702 }
   4703 
   4704 
   4705 TEST(EnsureAllocationSiteDependentCodesProcessed) {
   4706   if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
   4707   i::FLAG_allow_natives_syntax = true;
   4708   CcTest::InitializeVM();
   4709   Isolate* isolate = CcTest::i_isolate();
   4710   v8::internal::Heap* heap = CcTest::heap();
   4711   GlobalHandles* global_handles = isolate->global_handles();
   4712 
   4713   if (!isolate->use_crankshaft()) return;
   4714 
   4715   // The allocation site at the head of the list is ours.
   4716   Handle<AllocationSite> site;
   4717   {
   4718     LocalContext context;
   4719     v8::HandleScope scope(context->GetIsolate());
   4720 
   4721     int count = AllocationSitesCount(heap);
   4722     CompileRun("var bar = function() { return (new Array()); };"
   4723                "var a = bar();"
   4724                "bar();"
   4725                "bar();");
   4726 
   4727     // One allocation site should have been created.
   4728     int new_count = AllocationSitesCount(heap);
   4729     CHECK_EQ(new_count, (count + 1));
   4730     site = Handle<AllocationSite>::cast(
   4731         global_handles->Create(
   4732             AllocationSite::cast(heap->allocation_sites_list())));
   4733 
   4734     CompileRun("%OptimizeFunctionOnNextCall(bar); bar();");
   4735 
   4736     CHECK_EQ(DependentCode::kAllocationSiteTransitionChangedGroup,
   4737              site->dependent_code()->group());
   4738     CHECK_EQ(1, site->dependent_code()->count());
   4739     CHECK(site->dependent_code()->object_at(0)->IsWeakCell());
   4740     Code* function_bar = Code::cast(
   4741         WeakCell::cast(site->dependent_code()->object_at(0))->value());
   4742     Handle<JSFunction> bar_handle = Handle<JSFunction>::cast(
   4743         v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   4744             CcTest::global()
   4745                 ->Get(context.local(), v8_str("bar"))
   4746                 .ToLocalChecked())));
   4747     CHECK_EQ(bar_handle->code(), function_bar);
   4748   }
   4749 
   4750   // Now make sure that a gc should get rid of the function, even though we
   4751   // still have the allocation site alive.
   4752   for (int i = 0; i < 4; i++) {
   4753     heap->CollectAllGarbage();
   4754   }
   4755 
   4756   // The site still exists because of our global handle, but the code is no
   4757   // longer referred to by dependent_code().
   4758   CHECK(site->dependent_code()->object_at(0)->IsWeakCell() &&
   4759         WeakCell::cast(site->dependent_code()->object_at(0))->cleared());
   4760 }
   4761 
   4762 
   4763 TEST(CellsInOptimizedCodeAreWeak) {
   4764   if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
   4765   i::FLAG_weak_embedded_objects_in_optimized_code = true;
   4766   i::FLAG_allow_natives_syntax = true;
   4767   CcTest::InitializeVM();
   4768   Isolate* isolate = CcTest::i_isolate();
   4769   v8::internal::Heap* heap = CcTest::heap();
   4770 
   4771   if (!isolate->use_crankshaft()) return;
   4772   HandleScope outer_scope(heap->isolate());
   4773   Handle<Code> code;
   4774   {
   4775     LocalContext context;
   4776     HandleScope scope(heap->isolate());
   4777 
   4778     CompileRun(
   4779         "bar = (function() {"
   4780         "  function bar() {"
   4781         "    return foo(1);"
   4782         "  };"
   4783         "  var foo = function(x) { with (x) { return 1 + x; } };"
   4784         "  %NeverOptimizeFunction(foo);"
   4785         "  bar(foo);"
   4786         "  bar(foo);"
   4787         "  bar(foo);"
   4788         "  %OptimizeFunctionOnNextCall(bar);"
   4789         "  bar(foo);"
   4790         "  return bar;})();");
   4791 
   4792     Handle<JSFunction> bar = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
   4793         *v8::Local<v8::Function>::Cast(CcTest::global()
   4794                                            ->Get(context.local(), v8_str("bar"))
   4795                                            .ToLocalChecked())));
   4796     code = scope.CloseAndEscape(Handle<Code>(bar->code()));
   4797   }
   4798 
   4799   // Now make sure that a gc should get rid of the function
   4800   for (int i = 0; i < 4; i++) {
   4801     heap->CollectAllGarbage();
   4802   }
   4803 
   4804   CHECK(code->marked_for_deoptimization());
   4805 }
   4806 
   4807 
   4808 TEST(ObjectsInOptimizedCodeAreWeak) {
   4809   if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
   4810   i::FLAG_weak_embedded_objects_in_optimized_code = true;
   4811   i::FLAG_allow_natives_syntax = true;
   4812   CcTest::InitializeVM();
   4813   Isolate* isolate = CcTest::i_isolate();
   4814   v8::internal::Heap* heap = CcTest::heap();
   4815 
   4816   if (!isolate->use_crankshaft()) return;
   4817   HandleScope outer_scope(heap->isolate());
   4818   Handle<Code> code;
   4819   {
   4820     LocalContext context;
   4821     HandleScope scope(heap->isolate());
   4822 
   4823     CompileRun(
   4824         "function bar() {"
   4825         "  return foo(1);"
   4826         "};"
   4827         "function foo(x) { with (x) { return 1 + x; } };"
   4828         "%NeverOptimizeFunction(foo);"
   4829         "bar();"
   4830         "bar();"
   4831         "bar();"
   4832         "%OptimizeFunctionOnNextCall(bar);"
   4833         "bar();");
   4834 
   4835     Handle<JSFunction> bar = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
   4836         *v8::Local<v8::Function>::Cast(CcTest::global()
   4837                                            ->Get(context.local(), v8_str("bar"))
   4838                                            .ToLocalChecked())));
   4839     code = scope.CloseAndEscape(Handle<Code>(bar->code()));
   4840   }
   4841 
   4842   // Now make sure that a gc should get rid of the function
   4843   for (int i = 0; i < 4; i++) {
   4844     heap->CollectAllGarbage();
   4845   }
   4846 
   4847   CHECK(code->marked_for_deoptimization());
   4848 }
   4849 
   4850 
   4851 TEST(NoWeakHashTableLeakWithIncrementalMarking) {
   4852   if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
   4853   if (!i::FLAG_incremental_marking) return;
   4854   i::FLAG_weak_embedded_objects_in_optimized_code = true;
   4855   i::FLAG_allow_natives_syntax = true;
   4856   i::FLAG_compilation_cache = false;
   4857   i::FLAG_retain_maps_for_n_gc = 0;
   4858   CcTest::InitializeVM();
   4859   Isolate* isolate = CcTest::i_isolate();
   4860 
   4861   // Do not run for no-snap builds.
   4862   if (!i::Snapshot::HaveASnapshotToStartFrom(isolate)) return;
   4863 
   4864   v8::internal::Heap* heap = CcTest::heap();
   4865 
   4866   // Get a clean slate regarding optimized functions on the heap.
   4867   i::Deoptimizer::DeoptimizeAll(isolate);
   4868   heap->CollectAllGarbage();
   4869 
   4870   if (!isolate->use_crankshaft()) return;
   4871   HandleScope outer_scope(heap->isolate());
   4872   for (int i = 0; i < 3; i++) {
   4873     SimulateIncrementalMarking(heap);
   4874     {
   4875       LocalContext context;
   4876       HandleScope scope(heap->isolate());
   4877       EmbeddedVector<char, 256> source;
   4878       SNPrintF(source,
   4879                "function bar%d() {"
   4880                "  return foo%d(1);"
   4881                "};"
   4882                "function foo%d(x) { with (x) { return 1 + x; } };"
   4883                "bar%d();"
   4884                "bar%d();"
   4885                "bar%d();"
   4886                "%%OptimizeFunctionOnNextCall(bar%d);"
   4887                "bar%d();",
   4888                i, i, i, i, i, i, i, i);
   4889       CompileRun(source.start());
   4890     }
   4891     heap->CollectAllGarbage();
   4892   }
   4893   int elements = 0;
   4894   if (heap->weak_object_to_code_table()->IsHashTable()) {
   4895     WeakHashTable* t = WeakHashTable::cast(heap->weak_object_to_code_table());
   4896     elements = t->NumberOfElements();
   4897   }
   4898   CHECK_EQ(0, elements);
   4899 }
   4900 
   4901 
   4902 static Handle<JSFunction> OptimizeDummyFunction(v8::Isolate* isolate,
   4903                                                 const char* name) {
   4904   EmbeddedVector<char, 256> source;
   4905   SNPrintF(source,
   4906           "function %s() { return 0; }"
   4907           "%s(); %s();"
   4908           "%%OptimizeFunctionOnNextCall(%s);"
   4909           "%s();", name, name, name, name, name);
   4910   CompileRun(source.start());
   4911   i::Handle<JSFunction> fun = Handle<JSFunction>::cast(
   4912       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   4913           CcTest::global()
   4914               ->Get(isolate->GetCurrentContext(), v8_str(name))
   4915               .ToLocalChecked())));
   4916   return fun;
   4917 }
   4918 
   4919 
   4920 static int GetCodeChainLength(Code* code) {
   4921   int result = 0;
   4922   while (code->next_code_link()->IsCode()) {
   4923     result++;
   4924     code = Code::cast(code->next_code_link());
   4925   }
   4926   return result;
   4927 }
   4928 
   4929 
   4930 TEST(NextCodeLinkIsWeak) {
   4931   i::FLAG_always_opt = false;
   4932   i::FLAG_allow_natives_syntax = true;
   4933   CcTest::InitializeVM();
   4934   Isolate* isolate = CcTest::i_isolate();
   4935   v8::internal::Heap* heap = CcTest::heap();
   4936 
   4937   if (!isolate->use_crankshaft()) return;
   4938   HandleScope outer_scope(heap->isolate());
   4939   Handle<Code> code;
   4940   heap->CollectAllAvailableGarbage();
   4941   int code_chain_length_before, code_chain_length_after;
   4942   {
   4943     HandleScope scope(heap->isolate());
   4944     Handle<JSFunction> mortal =
   4945         OptimizeDummyFunction(CcTest::isolate(), "mortal");
   4946     Handle<JSFunction> immortal =
   4947         OptimizeDummyFunction(CcTest::isolate(), "immortal");
   4948     CHECK_EQ(immortal->code()->next_code_link(), mortal->code());
   4949     code_chain_length_before = GetCodeChainLength(immortal->code());
   4950     // Keep the immortal code and let the mortal code die.
   4951     code = scope.CloseAndEscape(Handle<Code>(immortal->code()));
   4952     CompileRun("mortal = null; immortal = null;");
   4953   }
   4954   heap->CollectAllAvailableGarbage();
   4955   // Now mortal code should be dead.
   4956   code_chain_length_after = GetCodeChainLength(*code);
   4957   CHECK_EQ(code_chain_length_before - 1, code_chain_length_after);
   4958 }
   4959 
   4960 
   4961 static Handle<Code> DummyOptimizedCode(Isolate* isolate) {
   4962   i::byte buffer[i::Assembler::kMinimalBufferSize];
   4963   MacroAssembler masm(isolate, buffer, sizeof(buffer),
   4964                       v8::internal::CodeObjectRequired::kYes);
   4965   CodeDesc desc;
   4966   masm.Push(isolate->factory()->undefined_value());
   4967   masm.Drop(1);
   4968   masm.GetCode(&desc);
   4969   Handle<Object> undefined(isolate->heap()->undefined_value(), isolate);
   4970   Handle<Code> code = isolate->factory()->NewCode(
   4971       desc, Code::ComputeFlags(Code::OPTIMIZED_FUNCTION), undefined);
   4972   CHECK(code->IsCode());
   4973   return code;
   4974 }
   4975 
   4976 
   4977 TEST(NextCodeLinkIsWeak2) {
   4978   i::FLAG_allow_natives_syntax = true;
   4979   CcTest::InitializeVM();
   4980   Isolate* isolate = CcTest::i_isolate();
   4981   v8::internal::Heap* heap = CcTest::heap();
   4982 
   4983   if (!isolate->use_crankshaft()) return;
   4984   HandleScope outer_scope(heap->isolate());
   4985   heap->CollectAllAvailableGarbage();
   4986   Handle<Context> context(Context::cast(heap->native_contexts_list()), isolate);
   4987   Handle<Code> new_head;
   4988   Handle<Object> old_head(context->get(Context::OPTIMIZED_CODE_LIST), isolate);
   4989   {
   4990     HandleScope scope(heap->isolate());
   4991     Handle<Code> immortal = DummyOptimizedCode(isolate);
   4992     Handle<Code> mortal = DummyOptimizedCode(isolate);
   4993     mortal->set_next_code_link(*old_head);
   4994     immortal->set_next_code_link(*mortal);
   4995     context->set(Context::OPTIMIZED_CODE_LIST, *immortal);
   4996     new_head = scope.CloseAndEscape(immortal);
   4997   }
   4998   heap->CollectAllAvailableGarbage();
   4999   // Now mortal code should be dead.
   5000   CHECK_EQ(*old_head, new_head->next_code_link());
   5001 }
   5002 
   5003 
   5004 static bool weak_ic_cleared = false;
   5005 
   5006 static void ClearWeakIC(
   5007     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   5008   printf("clear weak is called\n");
   5009   weak_ic_cleared = true;
   5010   data.GetParameter()->Reset();
   5011 }
   5012 
   5013 
   5014 TEST(WeakFunctionInConstructor) {
   5015   if (i::FLAG_always_opt) return;
   5016   i::FLAG_stress_compaction = false;
   5017   CcTest::InitializeVM();
   5018   v8::Isolate* isolate = CcTest::isolate();
   5019   LocalContext env;
   5020   v8::HandleScope scope(isolate);
   5021   CompileRun(
   5022       "function createObj(obj) {"
   5023       "  return new obj();"
   5024       "}");
   5025   i::Handle<JSFunction> createObj = Handle<JSFunction>::cast(
   5026       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
   5027           CcTest::global()
   5028               ->Get(env.local(), v8_str("createObj"))
   5029               .ToLocalChecked())));
   5030 
   5031   v8::Persistent<v8::Object> garbage;
   5032   {
   5033     v8::HandleScope scope(isolate);
   5034     const char* source =
   5035         " (function() {"
   5036         "   function hat() { this.x = 5; }"
   5037         "   createObj(hat);"
   5038         "   createObj(hat);"
   5039         "   return hat;"
   5040         " })();";
   5041     garbage.Reset(isolate, CompileRun(env.local(), source)
   5042                                .ToLocalChecked()
   5043                                ->ToObject(env.local())
   5044                                .ToLocalChecked());
   5045   }
   5046   weak_ic_cleared = false;
   5047   garbage.SetWeak(&garbage, &ClearWeakIC, v8::WeakCallbackType::kParameter);
   5048   Heap* heap = CcTest::i_isolate()->heap();
   5049   heap->CollectAllGarbage();
   5050   CHECK(weak_ic_cleared);
   5051 
   5052   // We've determined the constructor in createObj has had it's weak cell
   5053   // cleared. Now, verify that one additional call with a new function
   5054   // allows monomorphicity.
   5055   Handle<TypeFeedbackVector> feedback_vector = Handle<TypeFeedbackVector>(
   5056       createObj->shared()->feedback_vector(), CcTest::i_isolate());
   5057   for (int i = 0; i < 20; i++) {
   5058     Object* slot_value = feedback_vector->Get(FeedbackVectorSlot(0));
   5059     CHECK(slot_value->IsWeakCell());
   5060     if (WeakCell::cast(slot_value)->cleared()) break;
   5061     heap->CollectAllGarbage();
   5062   }
   5063 
   5064   Object* slot_value = feedback_vector->Get(FeedbackVectorSlot(0));
   5065   CHECK(slot_value->IsWeakCell() && WeakCell::cast(slot_value)->cleared());
   5066   CompileRun(
   5067       "function coat() { this.x = 6; }"
   5068       "createObj(coat);");
   5069   slot_value = feedback_vector->Get(FeedbackVectorSlot(0));
   5070   CHECK(slot_value->IsWeakCell() && !WeakCell::cast(slot_value)->cleared());
   5071 }
   5072 
   5073 
   5074 // Checks that the value returned by execution of the source is weak.
   5075 void CheckWeakness(const char* source) {
   5076   i::FLAG_stress_compaction = false;
   5077   CcTest::InitializeVM();
   5078   v8::Isolate* isolate = CcTest::isolate();
   5079   LocalContext env;
   5080   v8::HandleScope scope(isolate);
   5081   v8::Persistent<v8::Object> garbage;
   5082   {
   5083     v8::HandleScope scope(isolate);
   5084     garbage.Reset(isolate, CompileRun(env.local(), source)
   5085                                .ToLocalChecked()
   5086                                ->ToObject(env.local())
   5087                                .ToLocalChecked());
   5088   }
   5089   weak_ic_cleared = false;
   5090   garbage.SetWeak(&garbage, &ClearWeakIC, v8::WeakCallbackType::kParameter);
   5091   Heap* heap = CcTest::i_isolate()->heap();
   5092   heap->CollectAllGarbage();
   5093   CHECK(weak_ic_cleared);
   5094 }
   5095 
   5096 
   5097 // Each of the following "weak IC" tests creates an IC that embeds a map with
   5098 // the prototype pointing to _proto_ and checks that the _proto_ dies on GC.
   5099 TEST(WeakMapInMonomorphicLoadIC) {
   5100   CheckWeakness("function loadIC(obj) {"
   5101                 "  return obj.name;"
   5102                 "}"
   5103                 " (function() {"
   5104                 "   var proto = {'name' : 'weak'};"
   5105                 "   var obj = Object.create(proto);"
   5106                 "   loadIC(obj);"
   5107                 "   loadIC(obj);"
   5108                 "   loadIC(obj);"
   5109                 "   return proto;"
   5110                 " })();");
   5111 }
   5112 
   5113 
   5114 TEST(WeakMapInPolymorphicLoadIC) {
   5115   CheckWeakness(
   5116       "function loadIC(obj) {"
   5117       "  return obj.name;"
   5118       "}"
   5119       " (function() {"
   5120       "   var proto = {'name' : 'weak'};"
   5121       "   var obj = Object.create(proto);"
   5122       "   loadIC(obj);"
   5123       "   loadIC(obj);"
   5124       "   loadIC(obj);"
   5125       "   var poly = Object.create(proto);"
   5126       "   poly.x = true;"
   5127       "   loadIC(poly);"
   5128       "   return proto;"
   5129       " })();");
   5130 }
   5131 
   5132 
   5133 TEST(WeakMapInMonomorphicKeyedLoadIC) {
   5134   CheckWeakness("function keyedLoadIC(obj, field) {"
   5135                 "  return obj[field];"
   5136                 "}"
   5137                 " (function() {"
   5138                 "   var proto = {'name' : 'weak'};"
   5139                 "   var obj = Object.create(proto);"
   5140                 "   keyedLoadIC(obj, 'name');"
   5141                 "   keyedLoadIC(obj, 'name');"
   5142                 "   keyedLoadIC(obj, 'name');"
   5143                 "   return proto;"
   5144                 " })();");
   5145 }
   5146 
   5147 
   5148 TEST(WeakMapInPolymorphicKeyedLoadIC) {
   5149   CheckWeakness(
   5150       "function keyedLoadIC(obj, field) {"
   5151       "  return obj[field];"
   5152       "}"
   5153       " (function() {"
   5154       "   var proto = {'name' : 'weak'};"
   5155       "   var obj = Object.create(proto);"
   5156       "   keyedLoadIC(obj, 'name');"
   5157       "   keyedLoadIC(obj, 'name');"
   5158       "   keyedLoadIC(obj, 'name');"
   5159       "   var poly = Object.create(proto);"
   5160       "   poly.x = true;"
   5161       "   keyedLoadIC(poly, 'name');"
   5162       "   return proto;"
   5163       " })();");
   5164 }
   5165 
   5166 
   5167 TEST(WeakMapInMonomorphicStoreIC) {
   5168   CheckWeakness("function storeIC(obj, value) {"
   5169                 "  obj.name = value;"
   5170                 "}"
   5171                 " (function() {"
   5172                 "   var proto = {'name' : 'weak'};"
   5173                 "   var obj = Object.create(proto);"
   5174                 "   storeIC(obj, 'x');"
   5175                 "   storeIC(obj, 'x');"
   5176                 "   storeIC(obj, 'x');"
   5177                 "   return proto;"
   5178                 " })();");
   5179 }
   5180 
   5181 
   5182 TEST(WeakMapInPolymorphicStoreIC) {
   5183   CheckWeakness(
   5184       "function storeIC(obj, value) {"
   5185       "  obj.name = value;"
   5186       "}"
   5187       " (function() {"
   5188       "   var proto = {'name' : 'weak'};"
   5189       "   var obj = Object.create(proto);"
   5190       "   storeIC(obj, 'x');"
   5191       "   storeIC(obj, 'x');"
   5192       "   storeIC(obj, 'x');"
   5193       "   var poly = Object.create(proto);"
   5194       "   poly.x = true;"
   5195       "   storeIC(poly, 'x');"
   5196       "   return proto;"
   5197       " })();");
   5198 }
   5199 
   5200 
   5201 TEST(WeakMapInMonomorphicKeyedStoreIC) {
   5202   CheckWeakness("function keyedStoreIC(obj, field, value) {"
   5203                 "  obj[field] = value;"
   5204                 "}"
   5205                 " (function() {"
   5206                 "   var proto = {'name' : 'weak'};"
   5207                 "   var obj = Object.create(proto);"
   5208                 "   keyedStoreIC(obj, 'x');"
   5209                 "   keyedStoreIC(obj, 'x');"
   5210                 "   keyedStoreIC(obj, 'x');"
   5211                 "   return proto;"
   5212                 " })();");
   5213 }
   5214 
   5215 
   5216 TEST(WeakMapInPolymorphicKeyedStoreIC) {
   5217   CheckWeakness(
   5218       "function keyedStoreIC(obj, field, value) {"
   5219       "  obj[field] = value;"
   5220       "}"
   5221       " (function() {"
   5222       "   var proto = {'name' : 'weak'};"
   5223       "   var obj = Object.create(proto);"
   5224       "   keyedStoreIC(obj, 'x');"
   5225       "   keyedStoreIC(obj, 'x');"
   5226       "   keyedStoreIC(obj, 'x');"
   5227       "   var poly = Object.create(proto);"
   5228       "   poly.x = true;"
   5229       "   keyedStoreIC(poly, 'x');"
   5230       "   return proto;"
   5231       " })();");
   5232 }
   5233 
   5234 
   5235 TEST(WeakMapInMonomorphicCompareNilIC) {
   5236   CheckWeakness("function compareNilIC(obj) {"
   5237                 "  return obj == null;"
   5238                 "}"
   5239                 " (function() {"
   5240                 "   var proto = {'name' : 'weak'};"
   5241                 "   var obj = Object.create(proto);"
   5242                 "   compareNilIC(obj);"
   5243                 "   compareNilIC(obj);"
   5244                 "   compareNilIC(obj);"
   5245                 "   return proto;"
   5246                 " })();");
   5247 }
   5248 
   5249 
   5250 Handle<JSFunction> GetFunctionByName(Isolate* isolate, const char* name) {
   5251   Handle<String> str = isolate->factory()->InternalizeUtf8String(name);
   5252   Handle<Object> obj =
   5253       Object::GetProperty(isolate->global_object(), str).ToHandleChecked();
   5254   return Handle<JSFunction>::cast(obj);
   5255 }
   5256 
   5257 
   5258 void CheckIC(Code* code, Code::Kind kind, SharedFunctionInfo* shared,
   5259              int slot_index, InlineCacheState state) {
   5260   if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC ||
   5261       kind == Code::CALL_IC) {
   5262     TypeFeedbackVector* vector = shared->feedback_vector();
   5263     FeedbackVectorSlot slot(slot_index);
   5264     if (kind == Code::LOAD_IC) {
   5265       LoadICNexus nexus(vector, slot);
   5266       CHECK_EQ(nexus.StateFromFeedback(), state);
   5267     } else if (kind == Code::KEYED_LOAD_IC) {
   5268       KeyedLoadICNexus nexus(vector, slot);
   5269       CHECK_EQ(nexus.StateFromFeedback(), state);
   5270     } else if (kind == Code::CALL_IC) {
   5271       CallICNexus nexus(vector, slot);
   5272       CHECK_EQ(nexus.StateFromFeedback(), state);
   5273     }
   5274   } else {
   5275     Code* ic = FindFirstIC(code, kind);
   5276     CHECK(ic->is_inline_cache_stub());
   5277     CHECK(ic->ic_state() == state);
   5278   }
   5279 }
   5280 
   5281 
   5282 TEST(MonomorphicStaysMonomorphicAfterGC) {
   5283   if (FLAG_always_opt) return;
   5284   CcTest::InitializeVM();
   5285   Isolate* isolate = CcTest::i_isolate();
   5286   Heap* heap = isolate->heap();
   5287   v8::HandleScope scope(CcTest::isolate());
   5288   CompileRun(
   5289       "function loadIC(obj) {"
   5290       "  return obj.name;"
   5291       "}"
   5292       "function testIC() {"
   5293       "  var proto = {'name' : 'weak'};"
   5294       "  var obj = Object.create(proto);"
   5295       "  loadIC(obj);"
   5296       "  loadIC(obj);"
   5297       "  loadIC(obj);"
   5298       "  return proto;"
   5299       "};");
   5300   Handle<JSFunction> loadIC = GetFunctionByName(isolate, "loadIC");
   5301   {
   5302     v8::HandleScope scope(CcTest::isolate());
   5303     CompileRun("(testIC())");
   5304   }
   5305   heap->CollectAllGarbage();
   5306   CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, MONOMORPHIC);
   5307   {
   5308     v8::HandleScope scope(CcTest::isolate());
   5309     CompileRun("(testIC())");
   5310   }
   5311   CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, MONOMORPHIC);
   5312 }
   5313 
   5314 
   5315 TEST(PolymorphicStaysPolymorphicAfterGC) {
   5316   if (FLAG_always_opt) return;
   5317   CcTest::InitializeVM();
   5318   Isolate* isolate = CcTest::i_isolate();
   5319   Heap* heap = isolate->heap();
   5320   v8::HandleScope scope(CcTest::isolate());
   5321   CompileRun(
   5322       "function loadIC(obj) {"
   5323       "  return obj.name;"
   5324       "}"
   5325       "function testIC() {"
   5326       "  var proto = {'name' : 'weak'};"
   5327       "  var obj = Object.create(proto);"
   5328       "  loadIC(obj);"
   5329       "  loadIC(obj);"
   5330       "  loadIC(obj);"
   5331       "  var poly = Object.create(proto);"
   5332       "  poly.x = true;"
   5333       "  loadIC(poly);"
   5334       "  return proto;"
   5335       "};");
   5336   Handle<JSFunction> loadIC = GetFunctionByName(isolate, "loadIC");
   5337   {
   5338     v8::HandleScope scope(CcTest::isolate());
   5339     CompileRun("(testIC())");
   5340   }
   5341   heap->CollectAllGarbage();
   5342   CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, POLYMORPHIC);
   5343   {
   5344     v8::HandleScope scope(CcTest::isolate());
   5345     CompileRun("(testIC())");
   5346   }
   5347   CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, POLYMORPHIC);
   5348 }
   5349 
   5350 
   5351 TEST(WeakCell) {
   5352   CcTest::InitializeVM();
   5353   Isolate* isolate = CcTest::i_isolate();
   5354   v8::internal::Heap* heap = CcTest::heap();
   5355   v8::internal::Factory* factory = isolate->factory();
   5356 
   5357   HandleScope outer_scope(isolate);
   5358   Handle<WeakCell> weak_cell1;
   5359   {
   5360     HandleScope inner_scope(isolate);
   5361     Handle<HeapObject> value = factory->NewFixedArray(1, NOT_TENURED);
   5362     weak_cell1 = inner_scope.CloseAndEscape(factory->NewWeakCell(value));
   5363   }
   5364 
   5365   Handle<FixedArray> survivor = factory->NewFixedArray(1, NOT_TENURED);
   5366   Handle<WeakCell> weak_cell2;
   5367   {
   5368     HandleScope inner_scope(isolate);
   5369     weak_cell2 = inner_scope.CloseAndEscape(factory->NewWeakCell(survivor));
   5370   }
   5371   CHECK(weak_cell1->value()->IsFixedArray());
   5372   CHECK_EQ(*survivor, weak_cell2->value());
   5373   heap->CollectGarbage(NEW_SPACE);
   5374   CHECK(weak_cell1->value()->IsFixedArray());
   5375   CHECK_EQ(*survivor, weak_cell2->value());
   5376   heap->CollectGarbage(NEW_SPACE);
   5377   CHECK(weak_cell1->value()->IsFixedArray());
   5378   CHECK_EQ(*survivor, weak_cell2->value());
   5379   heap->CollectAllAvailableGarbage();
   5380   CHECK(weak_cell1->cleared());
   5381   CHECK_EQ(*survivor, weak_cell2->value());
   5382 }
   5383 
   5384 
   5385 TEST(WeakCellsWithIncrementalMarking) {
   5386   CcTest::InitializeVM();
   5387   Isolate* isolate = CcTest::i_isolate();
   5388   v8::internal::Heap* heap = CcTest::heap();
   5389   v8::internal::Factory* factory = isolate->factory();
   5390 
   5391   const int N = 16;
   5392   HandleScope outer_scope(isolate);
   5393   Handle<FixedArray> survivor = factory->NewFixedArray(1, NOT_TENURED);
   5394   Handle<WeakCell> weak_cells[N];
   5395 
   5396   for (int i = 0; i < N; i++) {
   5397     HandleScope inner_scope(isolate);
   5398     Handle<HeapObject> value =
   5399         i == 0 ? survivor : factory->NewFixedArray(1, NOT_TENURED);
   5400     Handle<WeakCell> weak_cell = factory->NewWeakCell(value);
   5401     CHECK(weak_cell->value()->IsFixedArray());
   5402     IncrementalMarking* marking = heap->incremental_marking();
   5403     if (marking->IsStopped()) {
   5404       heap->StartIncrementalMarking();
   5405     }
   5406     marking->Step(128, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
   5407     heap->CollectGarbage(NEW_SPACE);
   5408     CHECK(weak_cell->value()->IsFixedArray());
   5409     weak_cells[i] = inner_scope.CloseAndEscape(weak_cell);
   5410   }
   5411   heap->CollectAllGarbage();
   5412   CHECK_EQ(*survivor, weak_cells[0]->value());
   5413   for (int i = 1; i < N; i++) {
   5414     CHECK(weak_cells[i]->cleared());
   5415   }
   5416 }
   5417 
   5418 
   5419 #ifdef DEBUG
   5420 TEST(AddInstructionChangesNewSpacePromotion) {
   5421   i::FLAG_allow_natives_syntax = true;
   5422   i::FLAG_expose_gc = true;
   5423   i::FLAG_stress_compaction = true;
   5424   i::FLAG_gc_interval = 1000;
   5425   CcTest::InitializeVM();
   5426   if (!i::FLAG_allocation_site_pretenuring) return;
   5427   v8::HandleScope scope(CcTest::isolate());
   5428   Isolate* isolate = CcTest::i_isolate();
   5429   Heap* heap = isolate->heap();
   5430   LocalContext env;
   5431   CompileRun(
   5432       "function add(a, b) {"
   5433       "  return a + b;"
   5434       "}"
   5435       "add(1, 2);"
   5436       "add(\"a\", \"b\");"
   5437       "var oldSpaceObject;"
   5438       "gc();"
   5439       "function crash(x) {"
   5440       "  var object = {a: null, b: null};"
   5441       "  var result = add(1.5, x | 0);"
   5442       "  object.a = result;"
   5443       "  oldSpaceObject = object;"
   5444       "  return object;"
   5445       "}"
   5446       "crash(1);"
   5447       "crash(1);"
   5448       "%OptimizeFunctionOnNextCall(crash);"
   5449       "crash(1);");
   5450 
   5451   v8::Local<v8::Object> global = CcTest::global();
   5452   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   5453       global->Get(env.local(), v8_str("crash")).ToLocalChecked());
   5454   v8::Local<v8::Value> args1[] = {v8_num(1)};
   5455   heap->DisableInlineAllocation();
   5456   heap->set_allocation_timeout(1);
   5457   g->Call(env.local(), global, 1, args1).ToLocalChecked();
   5458   heap->CollectAllGarbage();
   5459 }
   5460 
   5461 
   5462 void OnFatalErrorExpectOOM(const char* location, const char* message) {
   5463   // Exit with 0 if the location matches our expectation.
   5464   exit(strcmp(location, "CALL_AND_RETRY_LAST"));
   5465 }
   5466 
   5467 
   5468 TEST(CEntryStubOOM) {
   5469   i::FLAG_allow_natives_syntax = true;
   5470   CcTest::InitializeVM();
   5471   v8::HandleScope scope(CcTest::isolate());
   5472   CcTest::isolate()->SetFatalErrorHandler(OnFatalErrorExpectOOM);
   5473 
   5474   v8::Local<v8::Value> result = CompileRun(
   5475       "%SetFlags('--gc-interval=1');"
   5476       "var a = [];"
   5477       "a.__proto__ = [];"
   5478       "a.unshift(1)");
   5479 
   5480   CHECK(result->IsNumber());
   5481 }
   5482 
   5483 #endif  // DEBUG
   5484 
   5485 
   5486 static void InterruptCallback357137(v8::Isolate* isolate, void* data) { }
   5487 
   5488 
   5489 static void RequestInterrupt(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5490   CcTest::isolate()->RequestInterrupt(&InterruptCallback357137, NULL);
   5491 }
   5492 
   5493 
   5494 UNINITIALIZED_TEST(Regress538257) {
   5495   i::FLAG_manual_evacuation_candidates_selection = true;
   5496   v8::Isolate::CreateParams create_params;
   5497   // Set heap limits.
   5498   create_params.constraints.set_max_semi_space_size(1 * Page::kPageSize / MB);
   5499   create_params.constraints.set_max_old_space_size(6 * Page::kPageSize / MB);
   5500   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   5501   v8::Isolate* isolate = v8::Isolate::New(create_params);
   5502   isolate->Enter();
   5503   {
   5504     i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   5505     HandleScope handle_scope(i_isolate);
   5506     PagedSpace* old_space = i_isolate->heap()->old_space();
   5507     const int kMaxObjects = 10000;
   5508     const int kFixedArrayLen = 512;
   5509     Handle<FixedArray> objects[kMaxObjects];
   5510     for (int i = 0; (i < kMaxObjects) && old_space->CanExpand(Page::kPageSize);
   5511          i++) {
   5512       objects[i] = i_isolate->factory()->NewFixedArray(kFixedArrayLen, TENURED);
   5513       Page::FromAddress(objects[i]->address())
   5514           ->SetFlag(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
   5515     }
   5516     SimulateFullSpace(old_space);
   5517     i_isolate->heap()->CollectGarbage(OLD_SPACE);
   5518     // If we get this far, we've successfully aborted compaction. Any further
   5519     // allocations might trigger OOM.
   5520   }
   5521   isolate->Exit();
   5522   isolate->Dispose();
   5523 }
   5524 
   5525 
   5526 TEST(Regress357137) {
   5527   CcTest::InitializeVM();
   5528   v8::Isolate* isolate = CcTest::isolate();
   5529   v8::HandleScope hscope(isolate);
   5530   v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
   5531   global->Set(
   5532       v8::String::NewFromUtf8(isolate, "interrupt", v8::NewStringType::kNormal)
   5533           .ToLocalChecked(),
   5534       v8::FunctionTemplate::New(isolate, RequestInterrupt));
   5535   v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
   5536   CHECK(!context.IsEmpty());
   5537   v8::Context::Scope cscope(context);
   5538 
   5539   v8::Local<v8::Value> result = CompileRun(
   5540       "var locals = '';"
   5541       "for (var i = 0; i < 512; i++) locals += 'var v' + i + '= 42;';"
   5542       "eval('function f() {' + locals + 'return function() { return v0; }; }');"
   5543       "interrupt();"  // This triggers a fake stack overflow in f.
   5544       "f()()");
   5545   CHECK_EQ(42.0, result->ToNumber(context).ToLocalChecked()->Value());
   5546 }
   5547 
   5548 
   5549 TEST(Regress507979) {
   5550   const int kFixedArrayLen = 10;
   5551   CcTest::InitializeVM();
   5552   Isolate* isolate = CcTest::i_isolate();
   5553   Heap* heap = isolate->heap();
   5554   HandleScope handle_scope(isolate);
   5555 
   5556   Handle<FixedArray> o1 = isolate->factory()->NewFixedArray(kFixedArrayLen);
   5557   Handle<FixedArray> o2 = isolate->factory()->NewFixedArray(kFixedArrayLen);
   5558   CHECK(heap->InNewSpace(o1->address()));
   5559   CHECK(heap->InNewSpace(o2->address()));
   5560 
   5561   HeapIterator it(heap, i::HeapIterator::kFilterUnreachable);
   5562 
   5563   // Replace parts of an object placed before a live object with a filler. This
   5564   // way the filler object shares the mark bits with the following live object.
   5565   o1->Shrink(kFixedArrayLen - 1);
   5566 
   5567   for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
   5568     // Let's not optimize the loop away.
   5569     CHECK(obj->address() != nullptr);
   5570   }
   5571 }
   5572 
   5573 
   5574 TEST(ArrayShiftSweeping) {
   5575   i::FLAG_expose_gc = true;
   5576   CcTest::InitializeVM();
   5577   v8::HandleScope scope(CcTest::isolate());
   5578   Isolate* isolate = CcTest::i_isolate();
   5579   Heap* heap = isolate->heap();
   5580 
   5581   v8::Local<v8::Value> result = CompileRun(
   5582       "var array = new Array(400);"
   5583       "var tmp = new Array(1000);"
   5584       "array[0] = 10;"
   5585       "gc();"
   5586       "gc();"
   5587       "array.shift();"
   5588       "array;");
   5589 
   5590   Handle<JSObject> o = Handle<JSObject>::cast(
   5591       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(result)));
   5592   CHECK(heap->InOldSpace(o->elements()));
   5593   CHECK(heap->InOldSpace(*o));
   5594   Page* page = Page::FromAddress(o->elements()->address());
   5595   CHECK(page->parallel_sweeping_state().Value() <=
   5596             MemoryChunk::kSweepingFinalize ||
   5597         Marking::IsBlack(Marking::MarkBitFrom(o->elements())));
   5598 }
   5599 
   5600 
   5601 UNINITIALIZED_TEST(PromotionQueue) {
   5602   i::FLAG_expose_gc = true;
   5603   i::FLAG_max_semi_space_size = 2 * (Page::kPageSize / MB);
   5604   i::FLAG_min_semi_space_size = i::FLAG_max_semi_space_size;
   5605   v8::Isolate::CreateParams create_params;
   5606   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   5607   v8::Isolate* isolate = v8::Isolate::New(create_params);
   5608   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   5609   {
   5610     v8::Isolate::Scope isolate_scope(isolate);
   5611     v8::HandleScope handle_scope(isolate);
   5612     v8::Context::New(isolate)->Enter();
   5613     Heap* heap = i_isolate->heap();
   5614     NewSpace* new_space = heap->new_space();
   5615 
   5616     // In this test we will try to overwrite the promotion queue which is at the
   5617     // end of to-space. To actually make that possible, we need at least two
   5618     // semi-space pages and take advantage of fragmentation.
   5619     // (1) Use a semi-space consisting of two pages.
   5620     // (2) Create a few small long living objects and call the scavenger to
   5621     // move them to the other semi-space.
   5622     // (3) Create a huge object, i.e., remainder of first semi-space page and
   5623     // create another huge object which should be of maximum allocatable memory
   5624     // size of the second semi-space page.
   5625     // (4) Call the scavenger again.
   5626     // What will happen is: the scavenger will promote the objects created in
   5627     // (2) and will create promotion queue entries at the end of the second
   5628     // semi-space page during the next scavenge when it promotes the objects to
   5629     // the old generation. The first allocation of (3) will fill up the first
   5630     // semi-space page. The second allocation in (3) will not fit into the
   5631     // first semi-space page, but it will overwrite the promotion queue which
   5632     // are in the second semi-space page. If the right guards are in place, the
   5633     // promotion queue will be evacuated in that case.
   5634 
   5635 
   5636     CHECK(new_space->IsAtMaximumCapacity());
   5637     CHECK(i::FLAG_min_semi_space_size * MB == new_space->TotalCapacity());
   5638 
   5639     // Call the scavenger two times to get an empty new space
   5640     heap->CollectGarbage(NEW_SPACE);
   5641     heap->CollectGarbage(NEW_SPACE);
   5642 
   5643     // First create a few objects which will survive a scavenge, and will get
   5644     // promoted to the old generation later on. These objects will create
   5645     // promotion queue entries at the end of the second semi-space page.
   5646     const int number_handles = 12;
   5647     Handle<FixedArray> handles[number_handles];
   5648     for (int i = 0; i < number_handles; i++) {
   5649       handles[i] = i_isolate->factory()->NewFixedArray(1, NOT_TENURED);
   5650     }
   5651 
   5652     heap->CollectGarbage(NEW_SPACE);
   5653     CHECK(i::FLAG_min_semi_space_size * MB == new_space->TotalCapacity());
   5654 
   5655     // Fill-up the first semi-space page.
   5656     FillUpOnePage(new_space);
   5657 
   5658     // Create a small object to initialize the bump pointer on the second
   5659     // semi-space page.
   5660     Handle<FixedArray> small =
   5661         i_isolate->factory()->NewFixedArray(1, NOT_TENURED);
   5662     CHECK(heap->InNewSpace(*small));
   5663 
   5664     // Fill-up the second semi-space page.
   5665     FillUpOnePage(new_space);
   5666 
   5667     // This scavenge will corrupt memory if the promotion queue is not
   5668     // evacuated.
   5669     heap->CollectGarbage(NEW_SPACE);
   5670   }
   5671   isolate->Dispose();
   5672 }
   5673 
   5674 
   5675 TEST(Regress388880) {
   5676   i::FLAG_expose_gc = true;
   5677   CcTest::InitializeVM();
   5678   v8::HandleScope scope(CcTest::isolate());
   5679   Isolate* isolate = CcTest::i_isolate();
   5680   Factory* factory = isolate->factory();
   5681   Heap* heap = isolate->heap();
   5682 
   5683   Handle<Map> map1 = Map::Create(isolate, 1);
   5684   Handle<Map> map2 =
   5685       Map::CopyWithField(map1, factory->NewStringFromStaticChars("foo"),
   5686                          HeapType::Any(isolate), NONE, Representation::Tagged(),
   5687                          OMIT_TRANSITION).ToHandleChecked();
   5688 
   5689   int desired_offset = Page::kPageSize - map1->instance_size();
   5690 
   5691   // Allocate padding objects in old pointer space so, that object allocated
   5692   // afterwards would end at the end of the page.
   5693   SimulateFullSpace(heap->old_space());
   5694   int padding_size = desired_offset - Page::kObjectStartOffset;
   5695   CreatePadding(heap, padding_size, TENURED);
   5696 
   5697   Handle<JSObject> o = factory->NewJSObjectFromMap(map1, TENURED);
   5698   o->set_properties(*factory->empty_fixed_array());
   5699 
   5700   // Ensure that the object allocated where we need it.
   5701   Page* page = Page::FromAddress(o->address());
   5702   CHECK_EQ(desired_offset, page->Offset(o->address()));
   5703 
   5704   // Now we have an object right at the end of the page.
   5705 
   5706   // Enable incremental marking to trigger actions in Heap::AdjustLiveBytes()
   5707   // that would cause crash.
   5708   IncrementalMarking* marking = CcTest::heap()->incremental_marking();
   5709   marking->Stop();
   5710   CcTest::heap()->StartIncrementalMarking();
   5711   CHECK(marking->IsMarking());
   5712 
   5713   // Now everything is set up for crashing in JSObject::MigrateFastToFast()
   5714   // when it calls heap->AdjustLiveBytes(...).
   5715   JSObject::MigrateToMap(o, map2);
   5716 }
   5717 
   5718 
   5719 TEST(Regress3631) {
   5720   i::FLAG_expose_gc = true;
   5721   CcTest::InitializeVM();
   5722   v8::HandleScope scope(CcTest::isolate());
   5723   Isolate* isolate = CcTest::i_isolate();
   5724   Heap* heap = isolate->heap();
   5725   IncrementalMarking* marking = CcTest::heap()->incremental_marking();
   5726   v8::Local<v8::Value> result = CompileRun(
   5727       "var weak_map = new WeakMap();"
   5728       "var future_keys = [];"
   5729       "for (var i = 0; i < 50; i++) {"
   5730       "  var key = {'k' : i + 0.1};"
   5731       "  weak_map.set(key, 1);"
   5732       "  future_keys.push({'x' : i + 0.2});"
   5733       "}"
   5734       "weak_map");
   5735   if (marking->IsStopped()) {
   5736     CcTest::heap()->StartIncrementalMarking();
   5737   }
   5738   // Incrementally mark the backing store.
   5739   Handle<JSReceiver> obj =
   5740       v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(result));
   5741   Handle<JSWeakCollection> weak_map(reinterpret_cast<JSWeakCollection*>(*obj));
   5742   while (!Marking::IsBlack(
   5743              Marking::MarkBitFrom(HeapObject::cast(weak_map->table()))) &&
   5744          !marking->IsStopped()) {
   5745     marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
   5746   }
   5747   // Stash the backing store in a handle.
   5748   Handle<Object> save(weak_map->table(), isolate);
   5749   // The following line will update the backing store.
   5750   CompileRun(
   5751       "for (var i = 0; i < 50; i++) {"
   5752       "  weak_map.set(future_keys[i], i);"
   5753       "}");
   5754   heap->incremental_marking()->set_should_hurry(true);
   5755   heap->CollectGarbage(OLD_SPACE);
   5756 }
   5757 
   5758 
   5759 TEST(Regress442710) {
   5760   CcTest::InitializeVM();
   5761   Isolate* isolate = CcTest::i_isolate();
   5762   Heap* heap = isolate->heap();
   5763   Factory* factory = isolate->factory();
   5764 
   5765   HandleScope sc(isolate);
   5766   Handle<JSGlobalObject> global(
   5767       CcTest::i_isolate()->context()->global_object());
   5768   Handle<JSArray> array = factory->NewJSArray(2);
   5769 
   5770   Handle<String> name = factory->InternalizeUtf8String("testArray");
   5771   JSReceiver::SetProperty(global, name, array, SLOPPY).Check();
   5772   CompileRun("testArray[0] = 1; testArray[1] = 2; testArray.shift();");
   5773   heap->CollectGarbage(OLD_SPACE);
   5774 }
   5775 
   5776 
   5777 HEAP_TEST(NumberStringCacheSize) {
   5778   // Test that the number-string cache has not been resized in the snapshot.
   5779   CcTest::InitializeVM();
   5780   Isolate* isolate = CcTest::i_isolate();
   5781   if (!isolate->snapshot_available()) return;
   5782   Heap* heap = isolate->heap();
   5783   CHECK_EQ(Heap::kInitialNumberStringCacheSize * 2,
   5784            heap->number_string_cache()->length());
   5785 }
   5786 
   5787 
   5788 TEST(Regress3877) {
   5789   CcTest::InitializeVM();
   5790   Isolate* isolate = CcTest::i_isolate();
   5791   Heap* heap = isolate->heap();
   5792   Factory* factory = isolate->factory();
   5793   HandleScope scope(isolate);
   5794   CompileRun("function cls() { this.x = 10; }");
   5795   Handle<WeakCell> weak_prototype;
   5796   {
   5797     HandleScope inner_scope(isolate);
   5798     v8::Local<v8::Value> result = CompileRun("cls.prototype");
   5799     Handle<JSReceiver> proto =
   5800         v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(result));
   5801     weak_prototype = inner_scope.CloseAndEscape(factory->NewWeakCell(proto));
   5802   }
   5803   CHECK(!weak_prototype->cleared());
   5804   CompileRun(
   5805       "var a = { };"
   5806       "a.x = new cls();"
   5807       "cls.prototype = null;");
   5808   for (int i = 0; i < 4; i++) {
   5809     heap->CollectAllGarbage();
   5810   }
   5811   // The map of a.x keeps prototype alive
   5812   CHECK(!weak_prototype->cleared());
   5813   // Change the map of a.x and make the previous map garbage collectable.
   5814   CompileRun("a.x.__proto__ = {};");
   5815   for (int i = 0; i < 4; i++) {
   5816     heap->CollectAllGarbage();
   5817   }
   5818   CHECK(weak_prototype->cleared());
   5819 }
   5820 
   5821 
   5822 Handle<WeakCell> AddRetainedMap(Isolate* isolate, Heap* heap) {
   5823     HandleScope inner_scope(isolate);
   5824     Handle<Map> map = Map::Create(isolate, 1);
   5825     v8::Local<v8::Value> result =
   5826         CompileRun("(function () { return {x : 10}; })();");
   5827     Handle<JSReceiver> proto =
   5828         v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(result));
   5829     Map::SetPrototype(map, proto);
   5830     heap->AddRetainedMap(map);
   5831     return inner_scope.CloseAndEscape(Map::WeakCellForMap(map));
   5832 }
   5833 
   5834 
   5835 void CheckMapRetainingFor(int n) {
   5836   FLAG_retain_maps_for_n_gc = n;
   5837   Isolate* isolate = CcTest::i_isolate();
   5838   Heap* heap = isolate->heap();
   5839   Handle<WeakCell> weak_cell = AddRetainedMap(isolate, heap);
   5840   CHECK(!weak_cell->cleared());
   5841   for (int i = 0; i < n; i++) {
   5842     SimulateIncrementalMarking(heap);
   5843     heap->CollectGarbage(OLD_SPACE);
   5844   }
   5845   CHECK(!weak_cell->cleared());
   5846   SimulateIncrementalMarking(heap);
   5847   heap->CollectGarbage(OLD_SPACE);
   5848   CHECK(weak_cell->cleared());
   5849 }
   5850 
   5851 
   5852 TEST(MapRetaining) {
   5853   CcTest::InitializeVM();
   5854   v8::HandleScope scope(CcTest::isolate());
   5855   CheckMapRetainingFor(FLAG_retain_maps_for_n_gc);
   5856   CheckMapRetainingFor(0);
   5857   CheckMapRetainingFor(1);
   5858   CheckMapRetainingFor(7);
   5859 }
   5860 
   5861 
   5862 TEST(RegressArrayListGC) {
   5863   FLAG_retain_maps_for_n_gc = 1;
   5864   FLAG_incremental_marking = 0;
   5865   FLAG_gc_global = true;
   5866   CcTest::InitializeVM();
   5867   v8::HandleScope scope(CcTest::isolate());
   5868   Isolate* isolate = CcTest::i_isolate();
   5869   Heap* heap = isolate->heap();
   5870   AddRetainedMap(isolate, heap);
   5871   Handle<Map> map = Map::Create(isolate, 1);
   5872   heap->CollectGarbage(OLD_SPACE);
   5873   // Force GC in old space on next addition of retained map.
   5874   Map::WeakCellForMap(map);
   5875   SimulateFullSpace(CcTest::heap()->new_space());
   5876   for (int i = 0; i < 10; i++) {
   5877     heap->AddRetainedMap(map);
   5878   }
   5879   heap->CollectGarbage(OLD_SPACE);
   5880 }
   5881 
   5882 
   5883 #ifdef DEBUG
   5884 TEST(PathTracer) {
   5885   CcTest::InitializeVM();
   5886   v8::HandleScope scope(CcTest::isolate());
   5887 
   5888   v8::Local<v8::Value> result = CompileRun("'abc'");
   5889   Handle<Object> o = v8::Utils::OpenHandle(*result);
   5890   CcTest::i_isolate()->heap()->TracePathToObject(*o);
   5891 }
   5892 #endif  // DEBUG
   5893 
   5894 
   5895 TEST(WritableVsImmortalRoots) {
   5896   for (int i = 0; i < Heap::kStrongRootListLength; ++i) {
   5897     Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(i);
   5898     bool writable = Heap::RootCanBeWrittenAfterInitialization(root_index);
   5899     bool immortal = Heap::RootIsImmortalImmovable(root_index);
   5900     // A root value can be writable, immortal, or neither, but not both.
   5901     CHECK(!immortal || !writable);
   5902   }
   5903 }
   5904 
   5905 
   5906 static void TestRightTrimFixedTypedArray(i::ExternalArrayType type,
   5907                                          int initial_length,
   5908                                          int elements_to_trim) {
   5909   v8::HandleScope scope(CcTest::isolate());
   5910   Isolate* isolate = CcTest::i_isolate();
   5911   Factory* factory = isolate->factory();
   5912   Heap* heap = isolate->heap();
   5913 
   5914   Handle<FixedTypedArrayBase> array =
   5915       factory->NewFixedTypedArray(initial_length, type, true);
   5916   int old_size = array->size();
   5917   heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(*array,
   5918                                                          elements_to_trim);
   5919 
   5920   // Check that free space filler is at the right place and did not smash the
   5921   // array header.
   5922   CHECK(array->IsFixedArrayBase());
   5923   CHECK_EQ(initial_length - elements_to_trim, array->length());
   5924   int new_size = array->size();
   5925   if (new_size != old_size) {
   5926     // Free space filler should be created in this case.
   5927     Address next_obj_address = array->address() + array->size();
   5928     CHECK(HeapObject::FromAddress(next_obj_address)->IsFiller());
   5929   }
   5930   heap->CollectAllAvailableGarbage();
   5931 }
   5932 
   5933 
   5934 TEST(Regress472513) {
   5935   CcTest::InitializeVM();
   5936   v8::HandleScope scope(CcTest::isolate());
   5937 
   5938   // The combination of type/initial_length/elements_to_trim triggered
   5939   // typed array header smashing with free space filler (crbug/472513).
   5940 
   5941   // 64-bit cases.
   5942   TestRightTrimFixedTypedArray(i::kExternalUint8Array, 32, 6);
   5943   TestRightTrimFixedTypedArray(i::kExternalUint8Array, 32 - 7, 6);
   5944   TestRightTrimFixedTypedArray(i::kExternalUint16Array, 16, 6);
   5945   TestRightTrimFixedTypedArray(i::kExternalUint16Array, 16 - 3, 6);
   5946   TestRightTrimFixedTypedArray(i::kExternalUint32Array, 8, 6);
   5947   TestRightTrimFixedTypedArray(i::kExternalUint32Array, 8 - 1, 6);
   5948 
   5949   // 32-bit cases.
   5950   TestRightTrimFixedTypedArray(i::kExternalUint8Array, 16, 3);
   5951   TestRightTrimFixedTypedArray(i::kExternalUint8Array, 16 - 3, 3);
   5952   TestRightTrimFixedTypedArray(i::kExternalUint16Array, 8, 3);
   5953   TestRightTrimFixedTypedArray(i::kExternalUint16Array, 8 - 1, 3);
   5954   TestRightTrimFixedTypedArray(i::kExternalUint32Array, 4, 3);
   5955 }
   5956 
   5957 
   5958 TEST(WeakFixedArray) {
   5959   CcTest::InitializeVM();
   5960   v8::HandleScope scope(CcTest::isolate());
   5961 
   5962   Handle<HeapNumber> number = CcTest::i_isolate()->factory()->NewHeapNumber(1);
   5963   Handle<WeakFixedArray> array = WeakFixedArray::Add(Handle<Object>(), number);
   5964   array->Remove(number);
   5965   array->Compact<WeakFixedArray::NullCallback>();
   5966   WeakFixedArray::Add(array, number);
   5967 }
   5968 
   5969 
   5970 TEST(PreprocessStackTrace) {
   5971   // Do not automatically trigger early GC.
   5972   FLAG_gc_interval = -1;
   5973   CcTest::InitializeVM();
   5974   v8::HandleScope scope(CcTest::isolate());
   5975   v8::TryCatch try_catch(CcTest::isolate());
   5976   CompileRun("throw new Error();");
   5977   CHECK(try_catch.HasCaught());
   5978   Isolate* isolate = CcTest::i_isolate();
   5979   Handle<Object> exception = v8::Utils::OpenHandle(*try_catch.Exception());
   5980   Handle<Name> key = isolate->factory()->stack_trace_symbol();
   5981   Handle<Object> stack_trace =
   5982       JSObject::GetProperty(exception, key).ToHandleChecked();
   5983   Handle<Object> code =
   5984       Object::GetElement(isolate, stack_trace, 3).ToHandleChecked();
   5985   CHECK(code->IsCode());
   5986 
   5987   isolate->heap()->CollectAllAvailableGarbage("stack trace preprocessing");
   5988 
   5989   Handle<Object> pos =
   5990       Object::GetElement(isolate, stack_trace, 3).ToHandleChecked();
   5991   CHECK(pos->IsSmi());
   5992 
   5993   Handle<JSArray> stack_trace_array = Handle<JSArray>::cast(stack_trace);
   5994   int array_length = Smi::cast(stack_trace_array->length())->value();
   5995   for (int i = 0; i < array_length; i++) {
   5996     Handle<Object> element =
   5997         Object::GetElement(isolate, stack_trace, i).ToHandleChecked();
   5998     CHECK(!element->IsCode());
   5999   }
   6000 }
   6001 
   6002 
   6003 static bool utils_has_been_collected = false;
   6004 
   6005 static void UtilsHasBeenCollected(
   6006     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   6007   utils_has_been_collected = true;
   6008   data.GetParameter()->Reset();
   6009 }
   6010 
   6011 
   6012 TEST(BootstrappingExports) {
   6013   // Expose utils object and delete it to observe that it is indeed
   6014   // being garbage-collected.
   6015   FLAG_expose_natives_as = "utils";
   6016   CcTest::InitializeVM();
   6017   v8::Isolate* isolate = CcTest::isolate();
   6018   LocalContext env;
   6019 
   6020   if (Snapshot::HaveASnapshotToStartFrom(CcTest::i_isolate())) return;
   6021 
   6022   utils_has_been_collected = false;
   6023 
   6024   v8::Persistent<v8::Object> utils;
   6025 
   6026   {
   6027     v8::HandleScope scope(isolate);
   6028     v8::Local<v8::String> name = v8_str("utils");
   6029     utils.Reset(isolate, CcTest::global()
   6030                              ->Get(env.local(), name)
   6031                              .ToLocalChecked()
   6032                              ->ToObject(env.local())
   6033                              .ToLocalChecked());
   6034     CHECK(CcTest::global()->Delete(env.local(), name).FromJust());
   6035   }
   6036 
   6037   utils.SetWeak(&utils, UtilsHasBeenCollected,
   6038                 v8::WeakCallbackType::kParameter);
   6039 
   6040   CcTest::heap()->CollectAllAvailableGarbage("fire weak callbacks");
   6041 
   6042   CHECK(utils_has_been_collected);
   6043 }
   6044 
   6045 
   6046 TEST(Regress1878) {
   6047   FLAG_allow_natives_syntax = true;
   6048   CcTest::InitializeVM();
   6049   v8::Isolate* isolate = CcTest::isolate();
   6050   v8::HandleScope scope(isolate);
   6051   v8::Local<v8::Function> constructor = v8::Utils::CallableToLocal(
   6052       CcTest::i_isolate()->internal_array_function());
   6053   LocalContext env;
   6054   CHECK(CcTest::global()
   6055             ->Set(env.local(), v8_str("InternalArray"), constructor)
   6056             .FromJust());
   6057 
   6058   v8::TryCatch try_catch(isolate);
   6059 
   6060   CompileRun(
   6061       "var a = Array();"
   6062       "for (var i = 0; i < 1000; i++) {"
   6063       "  var ai = new InternalArray(10000);"
   6064       "  if (%HaveSameMap(ai, a)) throw Error();"
   6065       "  if (!%HasFastObjectElements(ai)) throw Error();"
   6066       "}"
   6067       "for (var i = 0; i < 1000; i++) {"
   6068       "  var ai = new InternalArray(10000);"
   6069       "  if (%HaveSameMap(ai, a)) throw Error();"
   6070       "  if (!%HasFastObjectElements(ai)) throw Error();"
   6071       "}");
   6072 
   6073   CHECK(!try_catch.HasCaught());
   6074 }
   6075 
   6076 
   6077 void AllocateInSpace(Isolate* isolate, size_t bytes, AllocationSpace space) {
   6078   CHECK(bytes >= FixedArray::kHeaderSize);
   6079   CHECK(bytes % kPointerSize == 0);
   6080   Factory* factory = isolate->factory();
   6081   HandleScope scope(isolate);
   6082   AlwaysAllocateScope always_allocate(isolate);
   6083   int elements =
   6084       static_cast<int>((bytes - FixedArray::kHeaderSize) / kPointerSize);
   6085   Handle<FixedArray> array = factory->NewFixedArray(
   6086       elements, space == NEW_SPACE ? NOT_TENURED : TENURED);
   6087   CHECK((space == NEW_SPACE) == isolate->heap()->InNewSpace(*array));
   6088   CHECK_EQ(bytes, static_cast<size_t>(array->Size()));
   6089 }
   6090 
   6091 
   6092 TEST(NewSpaceAllocationCounter) {
   6093   CcTest::InitializeVM();
   6094   v8::HandleScope scope(CcTest::isolate());
   6095   Isolate* isolate = CcTest::i_isolate();
   6096   Heap* heap = isolate->heap();
   6097   size_t counter1 = heap->NewSpaceAllocationCounter();
   6098   heap->CollectGarbage(NEW_SPACE);
   6099   const size_t kSize = 1024;
   6100   AllocateInSpace(isolate, kSize, NEW_SPACE);
   6101   size_t counter2 = heap->NewSpaceAllocationCounter();
   6102   CHECK_EQ(kSize, counter2 - counter1);
   6103   heap->CollectGarbage(NEW_SPACE);
   6104   size_t counter3 = heap->NewSpaceAllocationCounter();
   6105   CHECK_EQ(0U, counter3 - counter2);
   6106   // Test counter overflow.
   6107   size_t max_counter = -1;
   6108   heap->set_new_space_allocation_counter(max_counter - 10 * kSize);
   6109   size_t start = heap->NewSpaceAllocationCounter();
   6110   for (int i = 0; i < 20; i++) {
   6111     AllocateInSpace(isolate, kSize, NEW_SPACE);
   6112     size_t counter = heap->NewSpaceAllocationCounter();
   6113     CHECK_EQ(kSize, counter - start);
   6114     start = counter;
   6115   }
   6116 }
   6117 
   6118 
   6119 TEST(OldSpaceAllocationCounter) {
   6120   CcTest::InitializeVM();
   6121   v8::HandleScope scope(CcTest::isolate());
   6122   Isolate* isolate = CcTest::i_isolate();
   6123   Heap* heap = isolate->heap();
   6124   size_t counter1 = heap->OldGenerationAllocationCounter();
   6125   heap->CollectGarbage(NEW_SPACE);
   6126   heap->CollectGarbage(NEW_SPACE);
   6127   const size_t kSize = 1024;
   6128   AllocateInSpace(isolate, kSize, OLD_SPACE);
   6129   size_t counter2 = heap->OldGenerationAllocationCounter();
   6130   // TODO(ulan): replace all CHECK_LE with CHECK_EQ after v8:4148 is fixed.
   6131   CHECK_LE(kSize, counter2 - counter1);
   6132   heap->CollectGarbage(NEW_SPACE);
   6133   size_t counter3 = heap->OldGenerationAllocationCounter();
   6134   CHECK_EQ(0u, counter3 - counter2);
   6135   AllocateInSpace(isolate, kSize, OLD_SPACE);
   6136   heap->CollectGarbage(OLD_SPACE);
   6137   size_t counter4 = heap->OldGenerationAllocationCounter();
   6138   CHECK_LE(kSize, counter4 - counter3);
   6139   // Test counter overflow.
   6140   size_t max_counter = -1;
   6141   heap->set_old_generation_allocation_counter(max_counter - 10 * kSize);
   6142   size_t start = heap->OldGenerationAllocationCounter();
   6143   for (int i = 0; i < 20; i++) {
   6144     AllocateInSpace(isolate, kSize, OLD_SPACE);
   6145     size_t counter = heap->OldGenerationAllocationCounter();
   6146     CHECK_LE(kSize, counter - start);
   6147     start = counter;
   6148   }
   6149 }
   6150 
   6151 
   6152 TEST(NewSpaceAllocationThroughput) {
   6153   CcTest::InitializeVM();
   6154   v8::HandleScope scope(CcTest::isolate());
   6155   Isolate* isolate = CcTest::i_isolate();
   6156   Heap* heap = isolate->heap();
   6157   GCTracer* tracer = heap->tracer();
   6158   int time1 = 100;
   6159   size_t counter1 = 1000;
   6160   tracer->SampleAllocation(time1, counter1, 0);
   6161   int time2 = 200;
   6162   size_t counter2 = 2000;
   6163   tracer->SampleAllocation(time2, counter2, 0);
   6164   size_t throughput =
   6165       tracer->NewSpaceAllocationThroughputInBytesPerMillisecond();
   6166   CHECK_EQ((counter2 - counter1) / (time2 - time1), throughput);
   6167   int time3 = 1000;
   6168   size_t counter3 = 30000;
   6169   tracer->SampleAllocation(time3, counter3, 0);
   6170   throughput = tracer->NewSpaceAllocationThroughputInBytesPerMillisecond();
   6171   CHECK_EQ((counter3 - counter1) / (time3 - time1), throughput);
   6172 }
   6173 
   6174 
   6175 TEST(NewSpaceAllocationThroughput2) {
   6176   CcTest::InitializeVM();
   6177   v8::HandleScope scope(CcTest::isolate());
   6178   Isolate* isolate = CcTest::i_isolate();
   6179   Heap* heap = isolate->heap();
   6180   GCTracer* tracer = heap->tracer();
   6181   int time1 = 100;
   6182   size_t counter1 = 1000;
   6183   tracer->SampleAllocation(time1, counter1, 0);
   6184   int time2 = 200;
   6185   size_t counter2 = 2000;
   6186   tracer->SampleAllocation(time2, counter2, 0);
   6187   size_t throughput =
   6188       tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(100);
   6189   CHECK_EQ((counter2 - counter1) / (time2 - time1), throughput);
   6190   int time3 = 1000;
   6191   size_t counter3 = 30000;
   6192   tracer->SampleAllocation(time3, counter3, 0);
   6193   throughput = tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(100);
   6194   CHECK_EQ((counter3 - counter1) / (time3 - time1), throughput);
   6195 }
   6196 
   6197 
   6198 static void CheckLeak(const v8::FunctionCallbackInfo<v8::Value>& args) {
   6199   Isolate* isolate = CcTest::i_isolate();
   6200   Object* message =
   6201       *reinterpret_cast<Object**>(isolate->pending_message_obj_address());
   6202   CHECK(message->IsTheHole());
   6203 }
   6204 
   6205 
   6206 TEST(MessageObjectLeak) {
   6207   CcTest::InitializeVM();
   6208   v8::Isolate* isolate = CcTest::isolate();
   6209   v8::HandleScope scope(isolate);
   6210   v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
   6211   global->Set(
   6212       v8::String::NewFromUtf8(isolate, "check", v8::NewStringType::kNormal)
   6213           .ToLocalChecked(),
   6214       v8::FunctionTemplate::New(isolate, CheckLeak));
   6215   v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
   6216   v8::Context::Scope cscope(context);
   6217 
   6218   const char* test =
   6219       "try {"
   6220       "  throw 'message 1';"
   6221       "} catch (e) {"
   6222       "}"
   6223       "check();"
   6224       "L: try {"
   6225       "  throw 'message 2';"
   6226       "} finally {"
   6227       "  break L;"
   6228       "}"
   6229       "check();";
   6230   CompileRun(test);
   6231 
   6232   const char* flag = "--turbo-filter=*";
   6233   FlagList::SetFlagsFromString(flag, StrLength(flag));
   6234   FLAG_always_opt = true;
   6235   FLAG_turbo_try_finally = true;
   6236 
   6237   CompileRun(test);
   6238 }
   6239 
   6240 
   6241 static void CheckEqualSharedFunctionInfos(
   6242     const v8::FunctionCallbackInfo<v8::Value>& args) {
   6243   Handle<Object> obj1 = v8::Utils::OpenHandle(*args[0]);
   6244   Handle<Object> obj2 = v8::Utils::OpenHandle(*args[1]);
   6245   Handle<JSFunction> fun1 = Handle<JSFunction>::cast(obj1);
   6246   Handle<JSFunction> fun2 = Handle<JSFunction>::cast(obj2);
   6247   CHECK(fun1->shared() == fun2->shared());
   6248 }
   6249 
   6250 
   6251 static void RemoveCodeAndGC(const v8::FunctionCallbackInfo<v8::Value>& args) {
   6252   Isolate* isolate = CcTest::i_isolate();
   6253   Handle<Object> obj = v8::Utils::OpenHandle(*args[0]);
   6254   Handle<JSFunction> fun = Handle<JSFunction>::cast(obj);
   6255   fun->ReplaceCode(*isolate->builtins()->CompileLazy());
   6256   fun->shared()->ReplaceCode(*isolate->builtins()->CompileLazy());
   6257   isolate->heap()->CollectAllAvailableGarbage("remove code and gc");
   6258 }
   6259 
   6260 
   6261 TEST(CanonicalSharedFunctionInfo) {
   6262   CcTest::InitializeVM();
   6263   v8::Isolate* isolate = CcTest::isolate();
   6264   v8::HandleScope scope(isolate);
   6265   v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
   6266   global->Set(isolate, "check", v8::FunctionTemplate::New(
   6267                                     isolate, CheckEqualSharedFunctionInfos));
   6268   global->Set(isolate, "remove",
   6269               v8::FunctionTemplate::New(isolate, RemoveCodeAndGC));
   6270   v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
   6271   v8::Context::Scope cscope(context);
   6272   CompileRun(
   6273       "function f() { return function g() {}; }"
   6274       "var g1 = f();"
   6275       "remove(f);"
   6276       "var g2 = f();"
   6277       "check(g1, g2);");
   6278 
   6279   CompileRun(
   6280       "function f() { return (function() { return function g() {}; })(); }"
   6281       "var g1 = f();"
   6282       "remove(f);"
   6283       "var g2 = f();"
   6284       "check(g1, g2);");
   6285 }
   6286 
   6287 
   6288 TEST(OldGenerationAllocationThroughput) {
   6289   CcTest::InitializeVM();
   6290   v8::HandleScope scope(CcTest::isolate());
   6291   Isolate* isolate = CcTest::i_isolate();
   6292   Heap* heap = isolate->heap();
   6293   GCTracer* tracer = heap->tracer();
   6294   int time1 = 100;
   6295   size_t counter1 = 1000;
   6296   tracer->SampleAllocation(time1, 0, counter1);
   6297   int time2 = 200;
   6298   size_t counter2 = 2000;
   6299   tracer->SampleAllocation(time2, 0, counter2);
   6300   size_t throughput =
   6301       tracer->OldGenerationAllocationThroughputInBytesPerMillisecond(100);
   6302   CHECK_EQ((counter2 - counter1) / (time2 - time1), throughput);
   6303   int time3 = 1000;
   6304   size_t counter3 = 30000;
   6305   tracer->SampleAllocation(time3, 0, counter3);
   6306   throughput =
   6307       tracer->OldGenerationAllocationThroughputInBytesPerMillisecond(100);
   6308   CHECK_EQ((counter3 - counter1) / (time3 - time1), throughput);
   6309 }
   6310 
   6311 
   6312 TEST(AllocationThroughput) {
   6313   CcTest::InitializeVM();
   6314   v8::HandleScope scope(CcTest::isolate());
   6315   Isolate* isolate = CcTest::i_isolate();
   6316   Heap* heap = isolate->heap();
   6317   GCTracer* tracer = heap->tracer();
   6318   int time1 = 100;
   6319   size_t counter1 = 1000;
   6320   tracer->SampleAllocation(time1, counter1, counter1);
   6321   int time2 = 200;
   6322   size_t counter2 = 2000;
   6323   tracer->SampleAllocation(time2, counter2, counter2);
   6324   size_t throughput = tracer->AllocationThroughputInBytesPerMillisecond(100);
   6325   CHECK_EQ(2 * (counter2 - counter1) / (time2 - time1), throughput);
   6326   int time3 = 1000;
   6327   size_t counter3 = 30000;
   6328   tracer->SampleAllocation(time3, counter3, counter3);
   6329   throughput = tracer->AllocationThroughputInBytesPerMillisecond(100);
   6330   CHECK_EQ(2 * (counter3 - counter1) / (time3 - time1), throughput);
   6331 }
   6332 
   6333 
   6334 TEST(ContextMeasure) {
   6335   CcTest::InitializeVM();
   6336   v8::HandleScope scope(CcTest::isolate());
   6337   Isolate* isolate = CcTest::i_isolate();
   6338   LocalContext context;
   6339 
   6340   int size_upper_limit = 0;
   6341   int count_upper_limit = 0;
   6342   HeapIterator it(CcTest::heap());
   6343   for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
   6344     size_upper_limit += obj->Size();
   6345     count_upper_limit++;
   6346   }
   6347 
   6348   ContextMeasure measure(*isolate->native_context());
   6349 
   6350   PrintF("Context size        : %d bytes\n", measure.Size());
   6351   PrintF("Context object count: %d\n", measure.Count());
   6352 
   6353   CHECK_LE(1000, measure.Count());
   6354   CHECK_LE(50000, measure.Size());
   6355 
   6356   CHECK_LE(measure.Count(), count_upper_limit);
   6357   CHECK_LE(measure.Size(), size_upper_limit);
   6358 }
   6359 
   6360 
   6361 TEST(ScriptIterator) {
   6362   CcTest::InitializeVM();
   6363   v8::HandleScope scope(CcTest::isolate());
   6364   Isolate* isolate = CcTest::i_isolate();
   6365   Heap* heap = CcTest::heap();
   6366   LocalContext context;
   6367 
   6368   heap->CollectAllGarbage();
   6369 
   6370   int script_count = 0;
   6371   {
   6372     HeapIterator it(heap);
   6373     for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
   6374       if (obj->IsScript()) script_count++;
   6375     }
   6376   }
   6377 
   6378   {
   6379     Script::Iterator iterator(isolate);
   6380     while (iterator.Next()) script_count--;
   6381   }
   6382 
   6383   CHECK_EQ(0, script_count);
   6384 }
   6385 
   6386 
   6387 TEST(SharedFunctionInfoIterator) {
   6388   CcTest::InitializeVM();
   6389   v8::HandleScope scope(CcTest::isolate());
   6390   Isolate* isolate = CcTest::i_isolate();
   6391   Heap* heap = CcTest::heap();
   6392   LocalContext context;
   6393 
   6394   heap->CollectAllGarbage();
   6395   heap->CollectAllGarbage();
   6396 
   6397   int sfi_count = 0;
   6398   {
   6399     HeapIterator it(heap);
   6400     for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
   6401       if (!obj->IsSharedFunctionInfo()) continue;
   6402       sfi_count++;
   6403     }
   6404   }
   6405 
   6406   {
   6407     SharedFunctionInfo::Iterator iterator(isolate);
   6408     while (iterator.Next()) sfi_count--;
   6409   }
   6410 
   6411   CHECK_EQ(0, sfi_count);
   6412 }
   6413 
   6414 
   6415 template <typename T>
   6416 static UniqueId MakeUniqueId(const Persistent<T>& p) {
   6417   return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
   6418 }
   6419 
   6420 
   6421 TEST(Regress519319) {
   6422   CcTest::InitializeVM();
   6423   v8::Isolate* isolate = CcTest::isolate();
   6424   v8::HandleScope scope(isolate);
   6425   Heap* heap = CcTest::heap();
   6426   LocalContext context;
   6427 
   6428   v8::Persistent<Value> parent;
   6429   v8::Persistent<Value> child;
   6430 
   6431   parent.Reset(isolate, v8::Object::New(isolate));
   6432   child.Reset(isolate, v8::Object::New(isolate));
   6433 
   6434   SimulateFullSpace(heap->old_space());
   6435   heap->CollectGarbage(OLD_SPACE);
   6436   {
   6437     UniqueId id = MakeUniqueId(parent);
   6438     isolate->SetObjectGroupId(parent, id);
   6439     isolate->SetReferenceFromGroup(id, child);
   6440   }
   6441   // The CollectGarbage call above starts sweeper threads.
   6442   // The crash will happen if the following two functions
   6443   // are called before sweeping finishes.
   6444   heap->StartIncrementalMarking();
   6445   heap->FinalizeIncrementalMarkingIfComplete("test");
   6446 }
   6447 
   6448 
   6449 HEAP_TEST(TestMemoryReducerSampleJsCalls) {
   6450   CcTest::InitializeVM();
   6451   v8::HandleScope scope(CcTest::isolate());
   6452   Heap* heap = CcTest::heap();
   6453   Isolate* isolate = CcTest::i_isolate();
   6454   MemoryReducer* memory_reducer = heap->memory_reducer_;
   6455   memory_reducer->SampleAndGetJsCallsPerMs(0);
   6456   isolate->IncrementJsCallsFromApiCounter();
   6457   isolate->IncrementJsCallsFromApiCounter();
   6458   isolate->IncrementJsCallsFromApiCounter();
   6459   double calls_per_ms = memory_reducer->SampleAndGetJsCallsPerMs(1);
   6460   CheckDoubleEquals(3, calls_per_ms);
   6461 
   6462   calls_per_ms = memory_reducer->SampleAndGetJsCallsPerMs(2);
   6463   CheckDoubleEquals(0, calls_per_ms);
   6464 
   6465   isolate->IncrementJsCallsFromApiCounter();
   6466   isolate->IncrementJsCallsFromApiCounter();
   6467   isolate->IncrementJsCallsFromApiCounter();
   6468   isolate->IncrementJsCallsFromApiCounter();
   6469   calls_per_ms = memory_reducer->SampleAndGetJsCallsPerMs(4);
   6470   CheckDoubleEquals(2, calls_per_ms);
   6471 }
   6472 
   6473 
   6474 }  // namespace internal
   6475 }  // namespace v8
   6476