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 #ifndef V8_MARKING_H 6 #define V8_MARKING_H 7 8 #include "src/utils.h" 9 10 namespace v8 { 11 namespace internal { 12 13 class MarkBit { 14 public: 15 typedef uint32_t CellType; 16 MarkBit(CellType * cell,CellType mask)17 inline MarkBit(CellType* cell, CellType mask) : cell_(cell), mask_(mask) {} 18 19 #ifdef DEBUG 20 bool operator==(const MarkBit& other) { 21 return cell_ == other.cell_ && mask_ == other.mask_; 22 } 23 #endif 24 25 private: cell()26 inline CellType* cell() { return cell_; } mask()27 inline CellType mask() { return mask_; } 28 Next()29 inline MarkBit Next() { 30 CellType new_mask = mask_ << 1; 31 if (new_mask == 0) { 32 return MarkBit(cell_ + 1, 1); 33 } else { 34 return MarkBit(cell_, new_mask); 35 } 36 } 37 Set()38 inline void Set() { *cell_ |= mask_; } Get()39 inline bool Get() { return (*cell_ & mask_) != 0; } Clear()40 inline void Clear() { *cell_ &= ~mask_; } 41 42 CellType* cell_; 43 CellType mask_; 44 45 friend class IncrementalMarking; 46 friend class Marking; 47 }; 48 49 // Bitmap is a sequence of cells each containing fixed number of bits. 50 class Bitmap { 51 public: 52 static const uint32_t kBitsPerCell = 32; 53 static const uint32_t kBitsPerCellLog2 = 5; 54 static const uint32_t kBitIndexMask = kBitsPerCell - 1; 55 static const uint32_t kBytesPerCell = kBitsPerCell / kBitsPerByte; 56 static const uint32_t kBytesPerCellLog2 = kBitsPerCellLog2 - kBitsPerByteLog2; 57 58 static const size_t kLength = (1 << kPageSizeBits) >> (kPointerSizeLog2); 59 60 static const size_t kSize = (1 << kPageSizeBits) >> 61 (kPointerSizeLog2 + kBitsPerByteLog2); 62 CellsForLength(int length)63 static int CellsForLength(int length) { 64 return (length + kBitsPerCell - 1) >> kBitsPerCellLog2; 65 } 66 CellsCount()67 int CellsCount() { return CellsForLength(kLength); } 68 SizeFor(int cells_count)69 static int SizeFor(int cells_count) { 70 return sizeof(MarkBit::CellType) * cells_count; 71 } 72 INLINE(static uint32_t IndexToCell (uint32_t index))73 INLINE(static uint32_t IndexToCell(uint32_t index)) { 74 return index >> kBitsPerCellLog2; 75 } 76 IndexInCell(uint32_t index)77 V8_INLINE static uint32_t IndexInCell(uint32_t index) { 78 return index & kBitIndexMask; 79 } 80 INLINE(static uint32_t CellToIndex (uint32_t index))81 INLINE(static uint32_t CellToIndex(uint32_t index)) { 82 return index << kBitsPerCellLog2; 83 } 84 INLINE(static uint32_t CellAlignIndex (uint32_t index))85 INLINE(static uint32_t CellAlignIndex(uint32_t index)) { 86 return (index + kBitIndexMask) & ~kBitIndexMask; 87 } 88 INLINE(MarkBit::CellType * cells ())89 INLINE(MarkBit::CellType* cells()) { 90 return reinterpret_cast<MarkBit::CellType*>(this); 91 } 92 INLINE(Address address ())93 INLINE(Address address()) { return reinterpret_cast<Address>(this); } 94 INLINE(static Bitmap * FromAddress (Address addr))95 INLINE(static Bitmap* FromAddress(Address addr)) { 96 return reinterpret_cast<Bitmap*>(addr); 97 } 98 MarkBitFromIndex(uint32_t index)99 inline MarkBit MarkBitFromIndex(uint32_t index) { 100 MarkBit::CellType mask = 1u << IndexInCell(index); 101 MarkBit::CellType* cell = this->cells() + (index >> kBitsPerCellLog2); 102 return MarkBit(cell, mask); 103 } 104 Clear()105 void Clear() { 106 for (int i = 0; i < CellsCount(); i++) cells()[i] = 0; 107 } 108 109 // Sets all bits in the range [start_index, end_index). SetRange(uint32_t start_index,uint32_t end_index)110 void SetRange(uint32_t start_index, uint32_t end_index) { 111 unsigned int start_cell_index = start_index >> Bitmap::kBitsPerCellLog2; 112 MarkBit::CellType start_index_mask = 1u << Bitmap::IndexInCell(start_index); 113 114 unsigned int end_cell_index = end_index >> Bitmap::kBitsPerCellLog2; 115 MarkBit::CellType end_index_mask = 1u << Bitmap::IndexInCell(end_index); 116 117 if (start_cell_index != end_cell_index) { 118 // Firstly, fill all bits from the start address to the end of the first 119 // cell with 1s. 120 cells()[start_cell_index] |= ~(start_index_mask - 1); 121 // Then fill all in between cells with 1s. 122 for (unsigned int i = start_cell_index + 1; i < end_cell_index; i++) { 123 cells()[i] = ~0u; 124 } 125 // Finally, fill all bits until the end address in the last cell with 1s. 126 cells()[end_cell_index] |= (end_index_mask - 1); 127 } else { 128 cells()[start_cell_index] |= end_index_mask - start_index_mask; 129 } 130 } 131 132 // Clears all bits in the range [start_index, end_index). ClearRange(uint32_t start_index,uint32_t end_index)133 void ClearRange(uint32_t start_index, uint32_t end_index) { 134 unsigned int start_cell_index = start_index >> Bitmap::kBitsPerCellLog2; 135 MarkBit::CellType start_index_mask = 1u << Bitmap::IndexInCell(start_index); 136 137 unsigned int end_cell_index = end_index >> Bitmap::kBitsPerCellLog2; 138 MarkBit::CellType end_index_mask = 1u << Bitmap::IndexInCell(end_index); 139 140 if (start_cell_index != end_cell_index) { 141 // Firstly, fill all bits from the start address to the end of the first 142 // cell with 0s. 143 cells()[start_cell_index] &= (start_index_mask - 1); 144 // Then fill all in between cells with 0s. 145 for (unsigned int i = start_cell_index + 1; i < end_cell_index; i++) { 146 cells()[i] = 0; 147 } 148 // Finally, set all bits until the end address in the last cell with 0s. 149 cells()[end_cell_index] &= ~(end_index_mask - 1); 150 } else { 151 cells()[start_cell_index] &= ~(end_index_mask - start_index_mask); 152 } 153 } 154 155 // Returns true if all bits in the range [start_index, end_index) are set. AllBitsSetInRange(uint32_t start_index,uint32_t end_index)156 bool AllBitsSetInRange(uint32_t start_index, uint32_t end_index) { 157 unsigned int start_cell_index = start_index >> Bitmap::kBitsPerCellLog2; 158 MarkBit::CellType start_index_mask = 1u << Bitmap::IndexInCell(start_index); 159 160 unsigned int end_cell_index = end_index >> Bitmap::kBitsPerCellLog2; 161 MarkBit::CellType end_index_mask = 1u << Bitmap::IndexInCell(end_index); 162 163 MarkBit::CellType matching_mask; 164 if (start_cell_index != end_cell_index) { 165 matching_mask = ~(start_index_mask - 1); 166 if ((cells()[start_cell_index] & matching_mask) != matching_mask) { 167 return false; 168 } 169 for (unsigned int i = start_cell_index + 1; i < end_cell_index; i++) { 170 if (cells()[i] != ~0u) return false; 171 } 172 matching_mask = (end_index_mask - 1); 173 return ((cells()[end_cell_index] & matching_mask) == matching_mask); 174 } else { 175 matching_mask = end_index_mask - start_index_mask; 176 return (cells()[end_cell_index] & matching_mask) == matching_mask; 177 } 178 } 179 180 // Returns true if all bits in the range [start_index, end_index) are cleared. AllBitsClearInRange(uint32_t start_index,uint32_t end_index)181 bool AllBitsClearInRange(uint32_t start_index, uint32_t end_index) { 182 unsigned int start_cell_index = start_index >> Bitmap::kBitsPerCellLog2; 183 MarkBit::CellType start_index_mask = 1u << Bitmap::IndexInCell(start_index); 184 185 unsigned int end_cell_index = end_index >> Bitmap::kBitsPerCellLog2; 186 MarkBit::CellType end_index_mask = 1u << Bitmap::IndexInCell(end_index); 187 188 MarkBit::CellType matching_mask; 189 if (start_cell_index != end_cell_index) { 190 matching_mask = ~(start_index_mask - 1); 191 if ((cells()[start_cell_index] & matching_mask)) return false; 192 for (unsigned int i = start_cell_index + 1; i < end_cell_index; i++) { 193 if (cells()[i]) return false; 194 } 195 matching_mask = (end_index_mask - 1); 196 return !(cells()[end_cell_index] & matching_mask); 197 } else { 198 matching_mask = end_index_mask - start_index_mask; 199 return !(cells()[end_cell_index] & matching_mask); 200 } 201 } 202 203 static void PrintWord(uint32_t word, uint32_t himask = 0) { 204 for (uint32_t mask = 1; mask != 0; mask <<= 1) { 205 if ((mask & himask) != 0) PrintF("["); 206 PrintF((mask & word) ? "1" : "0"); 207 if ((mask & himask) != 0) PrintF("]"); 208 } 209 } 210 211 class CellPrinter { 212 public: CellPrinter()213 CellPrinter() : seq_start(0), seq_type(0), seq_length(0) {} 214 Print(uint32_t pos,uint32_t cell)215 void Print(uint32_t pos, uint32_t cell) { 216 if (cell == seq_type) { 217 seq_length++; 218 return; 219 } 220 221 Flush(); 222 223 if (IsSeq(cell)) { 224 seq_start = pos; 225 seq_length = 0; 226 seq_type = cell; 227 return; 228 } 229 230 PrintF("%d: ", pos); 231 PrintWord(cell); 232 PrintF("\n"); 233 } 234 Flush()235 void Flush() { 236 if (seq_length > 0) { 237 PrintF("%d: %dx%d\n", seq_start, seq_type == 0 ? 0 : 1, 238 seq_length * kBitsPerCell); 239 seq_length = 0; 240 } 241 } 242 IsSeq(uint32_t cell)243 static bool IsSeq(uint32_t cell) { return cell == 0 || cell == 0xFFFFFFFF; } 244 245 private: 246 uint32_t seq_start; 247 uint32_t seq_type; 248 uint32_t seq_length; 249 }; 250 Print()251 void Print() { 252 CellPrinter printer; 253 for (int i = 0; i < CellsCount(); i++) { 254 printer.Print(i, cells()[i]); 255 } 256 printer.Flush(); 257 PrintF("\n"); 258 } 259 IsClean()260 bool IsClean() { 261 for (int i = 0; i < CellsCount(); i++) { 262 if (cells()[i] != 0) { 263 return false; 264 } 265 } 266 return true; 267 } 268 }; 269 270 class Marking : public AllStatic { 271 public: 272 // Impossible markbits: 01 273 static const char* kImpossibleBitPattern; INLINE(static bool IsImpossible (MarkBit mark_bit))274 INLINE(static bool IsImpossible(MarkBit mark_bit)) { 275 return !mark_bit.Get() && mark_bit.Next().Get(); 276 } 277 278 // Black markbits: 11 279 static const char* kBlackBitPattern; INLINE(static bool IsBlack (MarkBit mark_bit))280 INLINE(static bool IsBlack(MarkBit mark_bit)) { 281 return mark_bit.Get() && mark_bit.Next().Get(); 282 } 283 284 // White markbits: 00 - this is required by the mark bit clearer. 285 static const char* kWhiteBitPattern; INLINE(static bool IsWhite (MarkBit mark_bit))286 INLINE(static bool IsWhite(MarkBit mark_bit)) { 287 DCHECK(!IsImpossible(mark_bit)); 288 return !mark_bit.Get(); 289 } 290 291 // Grey markbits: 10 292 static const char* kGreyBitPattern; INLINE(static bool IsGrey (MarkBit mark_bit))293 INLINE(static bool IsGrey(MarkBit mark_bit)) { 294 return mark_bit.Get() && !mark_bit.Next().Get(); 295 } 296 297 // IsBlackOrGrey assumes that the first bit is set for black or grey 298 // objects. INLINE(static bool IsBlackOrGrey (MarkBit mark_bit))299 INLINE(static bool IsBlackOrGrey(MarkBit mark_bit)) { return mark_bit.Get(); } 300 INLINE(static void MarkBlack (MarkBit mark_bit))301 INLINE(static void MarkBlack(MarkBit mark_bit)) { 302 mark_bit.Set(); 303 mark_bit.Next().Set(); 304 } 305 INLINE(static void MarkWhite (MarkBit mark_bit))306 INLINE(static void MarkWhite(MarkBit mark_bit)) { 307 mark_bit.Clear(); 308 mark_bit.Next().Clear(); 309 } 310 INLINE(static void BlackToWhite (MarkBit markbit))311 INLINE(static void BlackToWhite(MarkBit markbit)) { 312 DCHECK(IsBlack(markbit)); 313 markbit.Clear(); 314 markbit.Next().Clear(); 315 } 316 INLINE(static void GreyToWhite (MarkBit markbit))317 INLINE(static void GreyToWhite(MarkBit markbit)) { 318 DCHECK(IsGrey(markbit)); 319 markbit.Clear(); 320 markbit.Next().Clear(); 321 } 322 INLINE(static void BlackToGrey (MarkBit markbit))323 INLINE(static void BlackToGrey(MarkBit markbit)) { 324 DCHECK(IsBlack(markbit)); 325 markbit.Next().Clear(); 326 } 327 INLINE(static void WhiteToGrey (MarkBit markbit))328 INLINE(static void WhiteToGrey(MarkBit markbit)) { 329 DCHECK(IsWhite(markbit)); 330 markbit.Set(); 331 } 332 INLINE(static void WhiteToBlack (MarkBit markbit))333 INLINE(static void WhiteToBlack(MarkBit markbit)) { 334 DCHECK(IsWhite(markbit)); 335 markbit.Set(); 336 markbit.Next().Set(); 337 } 338 INLINE(static void GreyToBlack (MarkBit markbit))339 INLINE(static void GreyToBlack(MarkBit markbit)) { 340 DCHECK(IsGrey(markbit)); 341 markbit.Next().Set(); 342 } 343 INLINE(static void AnyToGrey (MarkBit markbit))344 INLINE(static void AnyToGrey(MarkBit markbit)) { 345 markbit.Set(); 346 markbit.Next().Clear(); 347 } 348 349 enum ObjectColor { 350 BLACK_OBJECT, 351 WHITE_OBJECT, 352 GREY_OBJECT, 353 IMPOSSIBLE_COLOR 354 }; 355 ColorName(ObjectColor color)356 static const char* ColorName(ObjectColor color) { 357 switch (color) { 358 case BLACK_OBJECT: 359 return "black"; 360 case WHITE_OBJECT: 361 return "white"; 362 case GREY_OBJECT: 363 return "grey"; 364 case IMPOSSIBLE_COLOR: 365 return "impossible"; 366 } 367 return "error"; 368 } 369 Color(MarkBit mark_bit)370 static ObjectColor Color(MarkBit mark_bit) { 371 if (IsBlack(mark_bit)) return BLACK_OBJECT; 372 if (IsWhite(mark_bit)) return WHITE_OBJECT; 373 if (IsGrey(mark_bit)) return GREY_OBJECT; 374 UNREACHABLE(); 375 return IMPOSSIBLE_COLOR; 376 } 377 378 private: 379 DISALLOW_IMPLICIT_CONSTRUCTORS(Marking); 380 }; 381 382 } // namespace internal 383 } // namespace v8 384 385 #endif // V8_MARKING_H_ 386