LCOV - code coverage report
Current view: top level - src/heap - marking.h (source / functions) Hit Total Coverage
Test: app.info Lines: 41 46 89.1 %
Date: 2019-02-19 Functions: 23 26 88.5 %

          Line data    Source code
       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_HEAP_MARKING_H_
       6             : #define V8_HEAP_MARKING_H_
       7             : 
       8             : #include "src/base/atomic-utils.h"
       9             : #include "src/utils.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : 
      14             : class MarkBit {
      15             :  public:
      16             :   typedef uint32_t CellType;
      17             :   STATIC_ASSERT(sizeof(CellType) == sizeof(base::Atomic32));
      18             : 
      19             :   inline MarkBit(CellType* cell, CellType mask) : cell_(cell), mask_(mask) {}
      20             : 
      21             : #ifdef DEBUG
      22             :   bool operator==(const MarkBit& other) {
      23             :     return cell_ == other.cell_ && mask_ == other.mask_;
      24             :   }
      25             : #endif
      26             : 
      27             :  private:
      28   775212497 :   inline MarkBit Next() {
      29   775232634 :     CellType new_mask = mask_ << 1;
      30   775232634 :     if (new_mask == 0) {
      31    24808881 :       return MarkBit(cell_ + 1, 1);
      32             :     } else {
      33   750404245 :       return MarkBit(cell_, new_mask);
      34             :     }
      35             :   }
      36             : 
      37             :   // The function returns true if it succeeded to
      38             :   // transition the bit from 0 to 1.
      39             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
      40             :   inline bool Set();
      41             : 
      42             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
      43             :   inline bool Get();
      44             : 
      45             :   // The function returns true if it succeeded to
      46             :   // transition the bit from 1 to 0.
      47             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
      48             :   inline bool Clear();
      49             : 
      50             :   CellType* cell_;
      51             :   CellType mask_;
      52             : 
      53             :   friend class IncrementalMarking;
      54             :   friend class ConcurrentMarkingMarkbits;
      55             :   friend class Marking;
      56             : };
      57             : 
      58             : template <>
      59      379236 : inline bool MarkBit::Set<AccessMode::NON_ATOMIC>() {
      60      379236 :   CellType old_value = *cell_;
      61      379236 :   *cell_ = old_value | mask_;
      62      379236 :   return (old_value & mask_) == 0;
      63             : }
      64             : 
      65             : template <>
      66  7740986723 : inline bool MarkBit::Set<AccessMode::ATOMIC>() {
      67  7741006860 :   return base::AsAtomic32::SetBits(cell_, mask_, mask_);
      68             : }
      69             : 
      70             : template <>
      71   245622931 : inline bool MarkBit::Get<AccessMode::NON_ATOMIC>() {
      72   245622931 :   return (*cell_ & mask_) != 0;
      73             : }
      74             : 
      75             : template <>
      76   948554224 : inline bool MarkBit::Get<AccessMode::ATOMIC>() {
      77  1897108448 :   return (base::AsAtomic32::Acquire_Load(cell_) & mask_) != 0;
      78             : }
      79             : 
      80             : template <>
      81      162316 : inline bool MarkBit::Clear<AccessMode::NON_ATOMIC>() {
      82      162316 :   CellType old_value = *cell_;
      83      162316 :   *cell_ = old_value & ~mask_;
      84      162316 :   return (old_value & mask_) == mask_;
      85             : }
      86             : 
      87             : template <>
      88             : inline bool MarkBit::Clear<AccessMode::ATOMIC>() {
      89             :   return base::AsAtomic32::SetBits(cell_, 0u, mask_);
      90             : }
      91             : 
      92             : // Bitmap is a sequence of cells each containing fixed number of bits.
      93             : class V8_EXPORT_PRIVATE Bitmap {
      94             :  public:
      95             :   static const uint32_t kBitsPerCell = 32;
      96             :   static const uint32_t kBitsPerCellLog2 = 5;
      97             :   static const uint32_t kBitIndexMask = kBitsPerCell - 1;
      98             :   static const uint32_t kBytesPerCell = kBitsPerCell / kBitsPerByte;
      99             :   static const uint32_t kBytesPerCellLog2 = kBitsPerCellLog2 - kBitsPerByteLog2;
     100             : 
     101             :   static const size_t kLength = (1 << kPageSizeBits) >> (kTaggedSizeLog2);
     102             : 
     103             :   static const size_t kSize = (1 << kPageSizeBits) >>
     104             :                               (kTaggedSizeLog2 + kBitsPerByteLog2);
     105             : 
     106             :   static int CellsForLength(int length) {
     107             :     return (length + kBitsPerCell - 1) >> kBitsPerCellLog2;
     108             :   }
     109             : 
     110             :   int CellsCount() { return CellsForLength(kLength); }
     111             : 
     112             :   V8_INLINE static uint32_t IndexToCell(uint32_t index) {
     113     2240292 :     return index >> kBitsPerCellLog2;
     114             :   }
     115             : 
     116             :   V8_INLINE static uint32_t IndexInCell(uint32_t index) {
     117  8821640741 :     return index & kBitIndexMask;
     118             :   }
     119             : 
     120             :   // Retrieves the cell containing the provided markbit index.
     121             :   V8_INLINE static uint32_t CellAlignIndex(uint32_t index) {
     122     1120146 :     return index & ~kBitIndexMask;
     123             :   }
     124             : 
     125             :   V8_INLINE MarkBit::CellType* cells() {
     126             :     return reinterpret_cast<MarkBit::CellType*>(this);
     127             :   }
     128             : 
     129             :   V8_INLINE static Bitmap* FromAddress(Address addr) {
     130             :     return reinterpret_cast<Bitmap*>(addr);
     131             :   }
     132             : 
     133  8156438476 :   inline MarkBit MarkBitFromIndex(uint32_t index) {
     134  8156438482 :     MarkBit::CellType mask = 1u << IndexInCell(index);
     135  8156438482 :     MarkBit::CellType* cell = this->cells() + (index >> kBitsPerCellLog2);
     136  8156438476 :     return MarkBit(cell, mask);
     137             :   }
     138             : 
     139             :   void Clear();
     140             : 
     141             :   void MarkAllBits();
     142             : 
     143             :   // Clears bits in the given cell. The mask specifies bits to clear: if a
     144             :   // bit is set in the mask then the corresponding bit is cleared in the cell.
     145             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     146             :   void ClearBitsInCell(uint32_t cell_index, uint32_t mask);
     147             : 
     148             :   // Sets bits in the given cell. The mask specifies bits to set: if a
     149             :   // bit is set in the mask then the corresponding bit is set in the cell.
     150             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     151             :   void SetBitsInCell(uint32_t cell_index, uint32_t mask);
     152             : 
     153             :   // Sets all bits in the range [start_index, end_index). The cells at the
     154             :   // boundary of the range are updated with atomic compare and swap operation.
     155             :   // The inner cells are updated with relaxed write.
     156             :   void SetRange(uint32_t start_index, uint32_t end_index);
     157             : 
     158             :   // Clears all bits in the range [start_index, end_index). The cells at the
     159             :   // boundary of the range are updated with atomic compare and swap operation.
     160             :   // The inner cells are updated with relaxed write.
     161             :   void ClearRange(uint32_t start_index, uint32_t end_index);
     162             : 
     163             :   // Returns true if all bits in the range [start_index, end_index) are set.
     164             :   bool AllBitsSetInRange(uint32_t start_index, uint32_t end_index);
     165             : 
     166             :   // Returns true if all bits in the range [start_index, end_index) are cleared.
     167             :   bool AllBitsClearInRange(uint32_t start_index, uint32_t end_index);
     168             : 
     169             :   void Print();
     170             : 
     171             :   bool IsClean();
     172             : };
     173             : 
     174             : template <>
     175             : inline void Bitmap::SetBitsInCell<AccessMode::NON_ATOMIC>(uint32_t cell_index,
     176             :                                                           uint32_t mask) {
     177             :   cells()[cell_index] |= mask;
     178             : }
     179             : 
     180             : template <>
     181             : inline void Bitmap::SetBitsInCell<AccessMode::ATOMIC>(uint32_t cell_index,
     182             :                                                       uint32_t mask) {
     183      322586 :   base::AsAtomic32::SetBits(cells() + cell_index, mask, mask);
     184             : }
     185             : 
     186             : template <>
     187             : inline void Bitmap::ClearBitsInCell<AccessMode::NON_ATOMIC>(uint32_t cell_index,
     188             :                                                             uint32_t mask) {
     189             :   cells()[cell_index] &= ~mask;
     190             : }
     191             : 
     192             : template <>
     193             : inline void Bitmap::ClearBitsInCell<AccessMode::ATOMIC>(uint32_t cell_index,
     194             :                                                         uint32_t mask) {
     195      191540 :   base::AsAtomic32::SetBits(cells() + cell_index, 0u, mask);
     196             : }
     197             : 
     198             : class Marking : public AllStatic {
     199             :  public:
     200             :   // TODO(hpayer): The current mark bit operations use as default NON_ATOMIC
     201             :   // mode for access. We should remove the default value or switch it with
     202             :   // ATOMIC as soon we add concurrency.
     203             : 
     204             :   // Impossible markbits: 01
     205             :   static const char* kImpossibleBitPattern;
     206             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     207             :   V8_INLINE static bool IsImpossible(MarkBit mark_bit) {
     208             :     if (mode == AccessMode::NON_ATOMIC) {
     209          21 :       return !mark_bit.Get<mode>() && mark_bit.Next().Get<mode>();
     210             :     }
     211             :     // If we are in concurrent mode we can only tell if an object has the
     212             :     // impossible bit pattern if we read the first bit again after reading
     213             :     // the first and the second bit. If the first bit is till zero and the
     214             :     // second bit is one then the object has the impossible bit pattern.
     215           5 :     bool is_impossible = !mark_bit.Get<mode>() && mark_bit.Next().Get<mode>();
     216           5 :     if (is_impossible) {
     217           5 :       return !mark_bit.Get<mode>();
     218             :     }
     219             :     return false;
     220             :   }
     221             : 
     222             :   // Black markbits: 11
     223             :   static const char* kBlackBitPattern;
     224             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     225             :   V8_INLINE static bool IsBlack(MarkBit mark_bit) {
     226    55294553 :     return mark_bit.Get<mode>() && mark_bit.Next().Get<mode>();
     227             :   }
     228             : 
     229             :   // White markbits: 00 - this is required by the mark bit clearer.
     230             :   static const char* kWhiteBitPattern;
     231             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     232             :   V8_INLINE static bool IsWhite(MarkBit mark_bit) {
     233             :     DCHECK(!IsImpossible<mode>(mark_bit));
     234   205544489 :     return !mark_bit.Get<mode>();
     235             :   }
     236             : 
     237             :   // Grey markbits: 10
     238             :   static const char* kGreyBitPattern;
     239             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     240             :   V8_INLINE static bool IsGrey(MarkBit mark_bit) {
     241     8110420 :     return mark_bit.Get<mode>() && !mark_bit.Next().Get<mode>();
     242             :   }
     243             : 
     244             :   // IsBlackOrGrey assumes that the first bit is set for black or grey
     245             :   // objects.
     246             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     247             :   V8_INLINE static bool IsBlackOrGrey(MarkBit mark_bit) {
     248   153734867 :     return mark_bit.Get<mode>();
     249             :   }
     250             : 
     251             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     252             :   V8_INLINE static void MarkWhite(MarkBit markbit) {
     253             :     STATIC_ASSERT(mode == AccessMode::NON_ATOMIC);
     254       81158 :     markbit.Clear<mode>();
     255       81158 :     markbit.Next().Clear<mode>();
     256             :   }
     257             : 
     258             :   // Warning: this method is not safe in general in concurrent scenarios.
     259             :   // If you know that nobody else will change the bits on the given location
     260             :   // then you may use it.
     261             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     262             :   V8_INLINE static void MarkBlack(MarkBit markbit) {
     263             :     markbit.Set<mode>();
     264             :     markbit.Next().Set<mode>();
     265             :   }
     266             : 
     267             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     268             :   V8_INLINE static bool WhiteToGrey(MarkBit markbit) {
     269  7067426232 :     return markbit.Set<mode>();
     270             :   }
     271             : 
     272             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     273             :   V8_INLINE static bool WhiteToBlack(MarkBit markbit) {
     274           8 :     return markbit.Set<mode>() && markbit.Next().Set<mode>();
     275             :   }
     276             : 
     277             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     278             :   V8_INLINE static bool GreyToBlack(MarkBit markbit) {
     279   725288338 :     return markbit.Get<mode>() && markbit.Next().Set<mode>();
     280             :   }
     281             : 
     282             :   enum ObjectColor {
     283             :     BLACK_OBJECT,
     284             :     WHITE_OBJECT,
     285             :     GREY_OBJECT,
     286             :     IMPOSSIBLE_COLOR
     287             :   };
     288             : 
     289             :   static const char* ColorName(ObjectColor color) {
     290             :     switch (color) {
     291             :       case BLACK_OBJECT:
     292             :         return "black";
     293             :       case WHITE_OBJECT:
     294             :         return "white";
     295             :       case GREY_OBJECT:
     296             :         return "grey";
     297             :       case IMPOSSIBLE_COLOR:
     298             :         return "impossible";
     299             :     }
     300             :     return "error";
     301             :   }
     302             : 
     303           0 :   static ObjectColor Color(MarkBit mark_bit) {
     304           0 :     if (IsBlack(mark_bit)) return BLACK_OBJECT;
     305           0 :     if (IsWhite(mark_bit)) return WHITE_OBJECT;
     306           0 :     if (IsGrey(mark_bit)) return GREY_OBJECT;
     307           0 :     UNREACHABLE();
     308             :   }
     309             : 
     310             :  private:
     311             :   DISALLOW_IMPLICIT_CONSTRUCTORS(Marking);
     312             : };
     313             : 
     314             : }  // namespace internal
     315             : }  // namespace v8
     316             : 
     317             : #endif  // V8_HEAP_MARKING_H_

Generated by: LCOV version 1.10