1 // Copyright 2016 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 <limits> 6 7 #include "src/globals.h" 8 #include "src/heap/slot-set.h" 9 #include "src/heap/spaces.h" 10 #include "testing/gtest/include/gtest/gtest.h" 11 12 namespace v8 { 13 namespace internal { 14 15 TEST(SlotSet, InsertAndLookup1) { 16 SlotSet set; 17 set.SetPageStart(0); 18 for (int i = 0; i < Page::kPageSize; i += kPointerSize) { 19 EXPECT_FALSE(set.Lookup(i)); 20 } 21 for (int i = 0; i < Page::kPageSize; i += kPointerSize) { 22 set.Insert(i); 23 } 24 for (int i = 0; i < Page::kPageSize; i += kPointerSize) { 25 EXPECT_TRUE(set.Lookup(i)); 26 } 27 } 28 29 TEST(SlotSet, InsertAndLookup2) { 30 SlotSet set; 31 set.SetPageStart(0); 32 for (int i = 0; i < Page::kPageSize; i += kPointerSize) { 33 if (i % 7 == 0) { 34 set.Insert(i); 35 } 36 } 37 for (int i = 0; i < Page::kPageSize; i += kPointerSize) { 38 if (i % 7 == 0) { 39 EXPECT_TRUE(set.Lookup(i)); 40 } else { 41 EXPECT_FALSE(set.Lookup(i)); 42 } 43 } 44 } 45 46 TEST(SlotSet, Iterate) { 47 SlotSet set; 48 set.SetPageStart(0); 49 for (int i = 0; i < Page::kPageSize; i += kPointerSize) { 50 if (i % 7 == 0) { 51 set.Insert(i); 52 } 53 } 54 55 set.Iterate([](Address slot_address) { 56 uintptr_t intaddr = reinterpret_cast<uintptr_t>(slot_address); 57 if (intaddr % 3 == 0) { 58 return KEEP_SLOT; 59 } else { 60 return REMOVE_SLOT; 61 } 62 }); 63 64 for (int i = 0; i < Page::kPageSize; i += kPointerSize) { 65 if (i % 21 == 0) { 66 EXPECT_TRUE(set.Lookup(i)); 67 } else { 68 EXPECT_FALSE(set.Lookup(i)); 69 } 70 } 71 } 72 73 TEST(SlotSet, Remove) { 74 SlotSet set; 75 set.SetPageStart(0); 76 for (int i = 0; i < Page::kPageSize; i += kPointerSize) { 77 if (i % 7 == 0) { 78 set.Insert(i); 79 } 80 } 81 82 for (int i = 0; i < Page::kPageSize; i += kPointerSize) { 83 if (i % 3 != 0) { 84 set.Remove(i); 85 } 86 } 87 88 for (int i = 0; i < Page::kPageSize; i += kPointerSize) { 89 if (i % 21 == 0) { 90 EXPECT_TRUE(set.Lookup(i)); 91 } else { 92 EXPECT_FALSE(set.Lookup(i)); 93 } 94 } 95 } 96 97 void CheckRemoveRangeOn(uint32_t start, uint32_t end) { 98 SlotSet set; 99 set.SetPageStart(0); 100 uint32_t first = start == 0 ? 0 : start - kPointerSize; 101 uint32_t last = end == Page::kPageSize ? end - kPointerSize : end; 102 for (uint32_t i = first; i <= last; i += kPointerSize) { 103 set.Insert(i); 104 } 105 set.RemoveRange(start, end); 106 if (first != start) { 107 EXPECT_TRUE(set.Lookup(first)); 108 } 109 if (last == end) { 110 EXPECT_TRUE(set.Lookup(last)); 111 } 112 for (uint32_t i = start; i < end; i += kPointerSize) { 113 EXPECT_FALSE(set.Lookup(i)); 114 } 115 } 116 117 TEST(SlotSet, RemoveRange) { 118 CheckRemoveRangeOn(0, Page::kPageSize); 119 CheckRemoveRangeOn(1 * kPointerSize, 1023 * kPointerSize); 120 for (uint32_t start = 0; start <= 32; start++) { 121 CheckRemoveRangeOn(start * kPointerSize, (start + 1) * kPointerSize); 122 CheckRemoveRangeOn(start * kPointerSize, (start + 2) * kPointerSize); 123 const uint32_t kEnds[] = {32, 64, 100, 128, 1024, 1500, 2048}; 124 for (int i = 0; i < sizeof(kEnds) / sizeof(uint32_t); i++) { 125 for (int k = -3; k <= 3; k++) { 126 uint32_t end = (kEnds[i] + k); 127 if (start < end) { 128 CheckRemoveRangeOn(start * kPointerSize, end * kPointerSize); 129 } 130 } 131 } 132 } 133 SlotSet set; 134 set.SetPageStart(0); 135 set.Insert(Page::kPageSize / 2); 136 set.RemoveRange(0, Page::kPageSize); 137 for (uint32_t i = 0; i < Page::kPageSize; i += kPointerSize) { 138 EXPECT_FALSE(set.Lookup(i)); 139 } 140 } 141 142 TEST(TypedSlotSet, Iterate) { 143 TypedSlotSet set(0); 144 const int kDelta = 10000001; 145 const int kHostDelta = 50001; 146 int added = 0; 147 uint32_t j = 0; 148 for (uint32_t i = 0; i < TypedSlotSet::kMaxOffset; 149 i += kDelta, j += kHostDelta) { 150 SlotType type = static_cast<SlotType>(i % NUMBER_OF_SLOT_TYPES); 151 set.Insert(type, j, i); 152 ++added; 153 } 154 int iterated = 0; 155 set.Iterate([&iterated, kDelta, kHostDelta](SlotType type, Address host_addr, 156 Address addr) { 157 uint32_t i = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(addr)); 158 uint32_t j = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(host_addr)); 159 EXPECT_EQ(i % NUMBER_OF_SLOT_TYPES, static_cast<uint32_t>(type)); 160 EXPECT_EQ(0, i % kDelta); 161 EXPECT_EQ(0, j % kHostDelta); 162 ++iterated; 163 return i % 2 == 0 ? KEEP_SLOT : REMOVE_SLOT; 164 }); 165 EXPECT_EQ(added, iterated); 166 iterated = 0; 167 set.Iterate([&iterated](SlotType type, Address host_addr, Address addr) { 168 uint32_t i = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(addr)); 169 EXPECT_EQ(0, i % 2); 170 ++iterated; 171 return KEEP_SLOT; 172 }); 173 EXPECT_EQ(added / 2, iterated); 174 } 175 176 } // namespace internal 177 } // namespace v8 178