Home | History | Annotate | Download | only in heap
      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 
     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:
     26   inline CellType* cell() { return cell_; }
     27   inline CellType mask() { return mask_; }
     28 
     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 
     38   inline void Set() { *cell_ |= mask_; }
     39   inline bool Get() { return (*cell_ & mask_) != 0; }
     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 
     63   static int CellsForLength(int length) {
     64     return (length + kBitsPerCell - 1) >> kBitsPerCellLog2;
     65   }
     66 
     67   int CellsCount() { return CellsForLength(kLength); }
     68 
     69   static int SizeFor(int cells_count) {
     70     return sizeof(MarkBit::CellType) * cells_count;
     71   }
     72 
     73   INLINE(static uint32_t IndexToCell(uint32_t index)) {
     74     return index >> kBitsPerCellLog2;
     75   }
     76 
     77   V8_INLINE static uint32_t IndexInCell(uint32_t index) {
     78     return index & kBitIndexMask;
     79   }
     80 
     81   INLINE(static uint32_t CellToIndex(uint32_t index)) {
     82     return index << kBitsPerCellLog2;
     83   }
     84 
     85   INLINE(static uint32_t CellAlignIndex(uint32_t index)) {
     86     return (index + kBitIndexMask) & ~kBitIndexMask;
     87   }
     88 
     89   INLINE(MarkBit::CellType* cells()) {
     90     return reinterpret_cast<MarkBit::CellType*>(this);
     91   }
     92 
     93   INLINE(Address address()) { return reinterpret_cast<Address>(this); }
     94 
     95   INLINE(static Bitmap* FromAddress(Address addr)) {
     96     return reinterpret_cast<Bitmap*>(addr);
     97   }
     98 
     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 
    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).
    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).
    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.
    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.
    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:
    213     CellPrinter() : seq_start(0), seq_type(0), seq_length(0) {}
    214 
    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 
    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 
    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 
    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 
    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;
    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;
    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;
    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;
    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.
    299   INLINE(static bool IsBlackOrGrey(MarkBit mark_bit)) { return mark_bit.Get(); }
    300 
    301   INLINE(static void MarkBlack(MarkBit mark_bit)) {
    302     mark_bit.Set();
    303     mark_bit.Next().Set();
    304   }
    305 
    306   INLINE(static void MarkWhite(MarkBit mark_bit)) {
    307     mark_bit.Clear();
    308     mark_bit.Next().Clear();
    309   }
    310 
    311   INLINE(static void BlackToWhite(MarkBit markbit)) {
    312     DCHECK(IsBlack(markbit));
    313     markbit.Clear();
    314     markbit.Next().Clear();
    315   }
    316 
    317   INLINE(static void GreyToWhite(MarkBit markbit)) {
    318     DCHECK(IsGrey(markbit));
    319     markbit.Clear();
    320     markbit.Next().Clear();
    321   }
    322 
    323   INLINE(static void BlackToGrey(MarkBit markbit)) {
    324     DCHECK(IsBlack(markbit));
    325     markbit.Next().Clear();
    326   }
    327 
    328   INLINE(static void WhiteToGrey(MarkBit markbit)) {
    329     DCHECK(IsWhite(markbit));
    330     markbit.Set();
    331   }
    332 
    333   INLINE(static void WhiteToBlack(MarkBit markbit)) {
    334     DCHECK(IsWhite(markbit));
    335     markbit.Set();
    336     markbit.Next().Set();
    337   }
    338 
    339   INLINE(static void GreyToBlack(MarkBit markbit)) {
    340     DCHECK(IsGrey(markbit));
    341     markbit.Next().Set();
    342   }
    343 
    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 
    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 
    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