Home | History | Annotate | Download | only in heap
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <vector>
      6 
      7 #include "src/globals.h"
      8 #include "src/heap/heap.h"
      9 #include "src/heap/spaces.h"
     10 #include "src/heap/spaces-inl.h"
     11 #include "test/cctest/cctest.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 static Address AllocateLabBackingStore(Heap* heap, intptr_t size_in_bytes) {
     17   AllocationResult result = heap->old_space()->AllocateRaw(
     18       static_cast<int>(size_in_bytes), kDoubleAligned);
     19   Object* obj = result.ToObjectChecked();
     20   Address adr = HeapObject::cast(obj)->address();
     21   return adr;
     22 }
     23 
     24 
     25 static void VerifyIterable(v8::internal::Address base,
     26                            v8::internal::Address limit,
     27                            std::vector<intptr_t> expected_size) {
     28   CHECK_LE(reinterpret_cast<intptr_t>(base), reinterpret_cast<intptr_t>(limit));
     29   HeapObject* object = nullptr;
     30   size_t counter = 0;
     31   while (base < limit) {
     32     object = HeapObject::FromAddress(base);
     33     CHECK(object->IsFiller());
     34     CHECK_LT(counter, expected_size.size());
     35     CHECK_EQ(expected_size[counter], object->Size());
     36     base += object->Size();
     37     counter++;
     38   }
     39 }
     40 
     41 
     42 static bool AllocateFromLab(Heap* heap, LocalAllocationBuffer* lab,
     43                             intptr_t size_in_bytes,
     44                             AllocationAlignment alignment = kWordAligned) {
     45   HeapObject* obj;
     46   AllocationResult result =
     47       lab->AllocateRawAligned(static_cast<int>(size_in_bytes), alignment);
     48   if (result.To(&obj)) {
     49     heap->CreateFillerObjectAt(obj->address(), static_cast<int>(size_in_bytes));
     50     return true;
     51   }
     52   return false;
     53 }
     54 
     55 
     56 TEST(InvalidLab) {
     57   LocalAllocationBuffer lab = LocalAllocationBuffer::InvalidBuffer();
     58   CHECK(!lab.IsValid());
     59 }
     60 
     61 
     62 TEST(UnusedLabImplicitClose) {
     63   CcTest::InitializeVM();
     64   Heap* heap = CcTest::heap();
     65   heap->root(Heap::kOnePointerFillerMapRootIndex);
     66   const int kLabSize = 4 * KB;
     67   Address base = AllocateLabBackingStore(heap, kLabSize);
     68   Address limit = base + kLabSize;
     69   intptr_t expected_sizes_raw[1] = {kLabSize};
     70   std::vector<intptr_t> expected_sizes(expected_sizes_raw,
     71                                        expected_sizes_raw + 1);
     72   {
     73     AllocationResult lab_backing_store(HeapObject::FromAddress(base));
     74     LocalAllocationBuffer lab =
     75         LocalAllocationBuffer::FromResult(heap, lab_backing_store, kLabSize);
     76     CHECK(lab.IsValid());
     77   }
     78   VerifyIterable(base, limit, expected_sizes);
     79 }
     80 
     81 
     82 TEST(SimpleAllocate) {
     83   CcTest::InitializeVM();
     84   Heap* heap = CcTest::heap();
     85   const int kLabSize = 4 * KB;
     86   Address base = AllocateLabBackingStore(heap, kLabSize);
     87   Address limit = base + kLabSize;
     88   intptr_t sizes_raw[1] = {128};
     89   intptr_t expected_sizes_raw[2] = {128, kLabSize - 128};
     90   std::vector<intptr_t> sizes(sizes_raw, sizes_raw + 1);
     91   std::vector<intptr_t> expected_sizes(expected_sizes_raw,
     92                                        expected_sizes_raw + 2);
     93   {
     94     AllocationResult lab_backing_store(HeapObject::FromAddress(base));
     95     LocalAllocationBuffer lab =
     96         LocalAllocationBuffer::FromResult(heap, lab_backing_store, kLabSize);
     97     CHECK(lab.IsValid());
     98     intptr_t sum = 0;
     99     for (auto size : sizes) {
    100       if (AllocateFromLab(heap, &lab, size)) {
    101         sum += size;
    102       }
    103     }
    104   }
    105   VerifyIterable(base, limit, expected_sizes);
    106 }
    107 
    108 
    109 TEST(AllocateUntilLabOOM) {
    110   CcTest::InitializeVM();
    111   Heap* heap = CcTest::heap();
    112   const int kLabSize = 2 * KB;
    113   Address base = AllocateLabBackingStore(heap, kLabSize);
    114   Address limit = base + kLabSize;
    115   // The following objects won't fit in {kLabSize}.
    116   intptr_t sizes_raw[5] = {512, 512, 128, 512, 512};
    117   intptr_t expected_sizes_raw[5] = {512, 512, 128, 512, 384 /* left over */};
    118   std::vector<intptr_t> sizes(sizes_raw, sizes_raw + 5);
    119   std::vector<intptr_t> expected_sizes(expected_sizes_raw,
    120                                        expected_sizes_raw + 5);
    121   intptr_t sum = 0;
    122   {
    123     AllocationResult lab_backing_store(HeapObject::FromAddress(base));
    124     LocalAllocationBuffer lab =
    125         LocalAllocationBuffer::FromResult(heap, lab_backing_store, kLabSize);
    126     CHECK(lab.IsValid());
    127     for (auto size : sizes) {
    128       if (AllocateFromLab(heap, &lab, size)) {
    129         sum += size;
    130       }
    131     }
    132     CHECK_EQ(kLabSize - sum, 384);
    133   }
    134   VerifyIterable(base, limit, expected_sizes);
    135 }
    136 
    137 
    138 TEST(AllocateExactlyUntilLimit) {
    139   CcTest::InitializeVM();
    140   Heap* heap = CcTest::heap();
    141   const int kLabSize = 2 * KB;
    142   Address base = AllocateLabBackingStore(heap, kLabSize);
    143   Address limit = base + kLabSize;
    144   intptr_t sizes_raw[4] = {512, 512, 512, 512};
    145   intptr_t expected_sizes_raw[5] = {512, 512, 512, 512, 0};
    146   std::vector<intptr_t> sizes(sizes_raw, sizes_raw + 4);
    147   std::vector<intptr_t> expected_sizes(expected_sizes_raw,
    148                                        expected_sizes_raw + 5);
    149   {
    150     AllocationResult lab_backing_store(HeapObject::FromAddress(base));
    151     LocalAllocationBuffer lab =
    152         LocalAllocationBuffer::FromResult(heap, lab_backing_store, kLabSize);
    153     CHECK(lab.IsValid());
    154     intptr_t sum = 0;
    155     for (auto size : sizes) {
    156       if (AllocateFromLab(heap, &lab, size)) {
    157         sum += size;
    158       } else {
    159         break;
    160       }
    161     }
    162     CHECK_EQ(kLabSize - sum, 0);
    163   }
    164   VerifyIterable(base, limit, expected_sizes);
    165 }
    166 
    167 
    168 TEST(MergeSuccessful) {
    169   CcTest::InitializeVM();
    170   Heap* heap = CcTest::heap();
    171   const int kLabSize = 2 * KB;
    172   Address base1 = AllocateLabBackingStore(heap, kLabSize);
    173   Address limit1 = base1 + kLabSize;
    174   Address base2 = limit1;
    175   Address limit2 = base2 + kLabSize;
    176 
    177   intptr_t sizes1_raw[4] = {512, 512, 512, 256};
    178   intptr_t expected_sizes1_raw[5] = {512, 512, 512, 256, 256};
    179   std::vector<intptr_t> sizes1(sizes1_raw, sizes1_raw + 4);
    180   std::vector<intptr_t> expected_sizes1(expected_sizes1_raw,
    181                                         expected_sizes1_raw + 5);
    182 
    183   intptr_t sizes2_raw[5] = {256, 512, 512, 512, 512};
    184   intptr_t expected_sizes2_raw[10] = {512, 512, 512, 256, 256,
    185                                       512, 512, 512, 512, 0};
    186   std::vector<intptr_t> sizes2(sizes2_raw, sizes2_raw + 5);
    187   std::vector<intptr_t> expected_sizes2(expected_sizes2_raw,
    188                                         expected_sizes2_raw + 10);
    189 
    190   {
    191     AllocationResult lab_backing_store1(HeapObject::FromAddress(base1));
    192     LocalAllocationBuffer lab1 =
    193         LocalAllocationBuffer::FromResult(heap, lab_backing_store1, kLabSize);
    194     CHECK(lab1.IsValid());
    195     intptr_t sum = 0;
    196     for (auto size : sizes1) {
    197       if (AllocateFromLab(heap, &lab1, size)) {
    198         sum += size;
    199       } else {
    200         break;
    201       }
    202     }
    203 
    204     AllocationResult lab_backing_store2(HeapObject::FromAddress(base2));
    205     LocalAllocationBuffer lab2 =
    206         LocalAllocationBuffer::FromResult(heap, lab_backing_store2, kLabSize);
    207     CHECK(lab2.IsValid());
    208     CHECK(lab2.TryMerge(&lab1));
    209     CHECK(!lab1.IsValid());
    210     for (auto size : sizes2) {
    211       if (AllocateFromLab(heap, &lab2, size)) {
    212         sum += size;
    213       } else {
    214         break;
    215       }
    216     }
    217     CHECK_EQ(2 * kLabSize - sum, 0);
    218   }
    219   VerifyIterable(base1, limit1, expected_sizes1);
    220   VerifyIterable(base1, limit2, expected_sizes2);
    221 }
    222 
    223 
    224 TEST(MergeFailed) {
    225   CcTest::InitializeVM();
    226   Heap* heap = CcTest::heap();
    227   const int kLabSize = 2 * KB;
    228   Address base1 = AllocateLabBackingStore(heap, kLabSize);
    229   Address base2 = base1 + kLabSize;
    230   Address base3 = base2 + kLabSize;
    231 
    232   {
    233     AllocationResult lab_backing_store1(HeapObject::FromAddress(base1));
    234     LocalAllocationBuffer lab1 =
    235         LocalAllocationBuffer::FromResult(heap, lab_backing_store1, kLabSize);
    236     CHECK(lab1.IsValid());
    237 
    238     AllocationResult lab_backing_store2(HeapObject::FromAddress(base2));
    239     LocalAllocationBuffer lab2 =
    240         LocalAllocationBuffer::FromResult(heap, lab_backing_store2, kLabSize);
    241     CHECK(lab2.IsValid());
    242 
    243     AllocationResult lab_backing_store3(HeapObject::FromAddress(base3));
    244     LocalAllocationBuffer lab3 =
    245         LocalAllocationBuffer::FromResult(heap, lab_backing_store3, kLabSize);
    246     CHECK(lab3.IsValid());
    247 
    248     CHECK(!lab3.TryMerge(&lab1));
    249   }
    250 }
    251 
    252 
    253 #ifdef V8_HOST_ARCH_32_BIT
    254 TEST(AllocateAligned) {
    255   CcTest::InitializeVM();
    256   Heap* heap = CcTest::heap();
    257   const int kLabSize = 2 * KB;
    258   Address base = AllocateLabBackingStore(heap, kLabSize);
    259   Address limit = base + kLabSize;
    260   std::pair<intptr_t, AllocationAlignment> sizes_raw[2] = {
    261       std::make_pair(116, kWordAligned), std::make_pair(64, kDoubleAligned)};
    262   std::vector<std::pair<intptr_t, AllocationAlignment>> sizes(sizes_raw,
    263                                                               sizes_raw + 2);
    264   intptr_t expected_sizes_raw[4] = {116, 4, 64, 1864};
    265   std::vector<intptr_t> expected_sizes(expected_sizes_raw,
    266                                        expected_sizes_raw + 4);
    267 
    268   {
    269     AllocationResult lab_backing_store(HeapObject::FromAddress(base));
    270     LocalAllocationBuffer lab =
    271         LocalAllocationBuffer::FromResult(heap, lab_backing_store, kLabSize);
    272     CHECK(lab.IsValid());
    273     for (auto pair : sizes) {
    274       if (!AllocateFromLab(heap, &lab, pair.first, pair.second)) {
    275         break;
    276       }
    277     }
    278   }
    279   VerifyIterable(base, limit, expected_sizes);
    280 }
    281 #endif  // V8_HOST_ARCH_32_BIT
    282 
    283 }  // namespace internal
    284 }  // namespace v8
    285