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: 2017-10-20 Functions: 21 26 80.8 %

          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_MARKING_H
       6             : #define V8_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   698079165 :   inline MarkBit Next() {
      29   698079165 :     CellType new_mask = mask_ << 1;
      30   698079165 :     if (new_mask == 0) {
      31    16983823 :       return MarkBit(cell_ + 1, 1);
      32             :     } else {
      33   681095342 :       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      186538 : inline bool MarkBit::Set<AccessMode::NON_ATOMIC>() {
      60      186538 :   CellType old_value = *cell_;
      61      186538 :   *cell_ = old_value | mask_;
      62      186538 :   return (old_value & mask_) == 0;
      63             : }
      64             : 
      65             : template <>
      66  5356652151 : inline bool MarkBit::Set<AccessMode::ATOMIC>() {
      67  5356652151 :   return base::AsAtomic32::SetBits(cell_, mask_, mask_);
      68             : }
      69             : 
      70             : template <>
      71   258260685 : inline bool MarkBit::Get<AccessMode::NON_ATOMIC>() {
      72   258260685 :   return (*cell_ & mask_) != 0;
      73             : }
      74             : 
      75             : template <>
      76   876551133 : inline bool MarkBit::Get<AccessMode::ATOMIC>() {
      77  1753102266 :   return (base::AsAtomic32::Acquire_Load(cell_) & mask_) != 0;
      78             : }
      79             : 
      80             : template <>
      81        8090 : inline bool MarkBit::Clear<AccessMode::NON_ATOMIC>() {
      82        8090 :   CellType old_value = *cell_;
      83        8090 :   *cell_ = old_value & ~mask_;
      84        8090 :   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) >> (kPointerSizeLog2);
     102             : 
     103             :   static const size_t kSize = (1 << kPageSizeBits) >>
     104             :                               (kPointerSizeLog2 + 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     2897364 :     return index >> kBitsPerCellLog2;
     114             :   }
     115             : 
     116             :   V8_INLINE static uint32_t IndexInCell(uint32_t index) {
     117  6395389395 :     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      965788 :     return index & ~kBitIndexMask;
     123             :   }
     124             : 
     125             :   V8_INLINE static bool IsCellAligned(uint32_t index) {
     126             :     return (index & kBitIndexMask) == 0;
     127             :   }
     128             : 
     129             :   V8_INLINE MarkBit::CellType* cells() {
     130             :     return reinterpret_cast<MarkBit::CellType*>(this);
     131             :   }
     132             : 
     133             :   V8_INLINE static Bitmap* FromAddress(Address addr) {
     134             :     return reinterpret_cast<Bitmap*>(addr);
     135             :   }
     136             : 
     137  5785293664 :   inline MarkBit MarkBitFromIndex(uint32_t index) {
     138  5785293670 :     MarkBit::CellType mask = 1u << IndexInCell(index);
     139  5785293670 :     MarkBit::CellType* cell = this->cells() + (index >> kBitsPerCellLog2);
     140  5785293664 :     return MarkBit(cell, mask);
     141             :   }
     142             : 
     143             :   void Clear();
     144             : 
     145             :   // Clears bits in the given cell. The mask specifies bits to clear: if a
     146             :   // bit is set in the mask then the corresponding bit is cleared in the cell.
     147             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     148             :   void ClearBitsInCell(uint32_t cell_index, uint32_t mask);
     149             : 
     150             :   // Sets bits in the given cell. The mask specifies bits to set: if a
     151             :   // bit is set in the mask then the corresponding bit is set in the cell.
     152             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     153             :   void SetBitsInCell(uint32_t cell_index, uint32_t mask);
     154             : 
     155             :   // Sets all bits in the range [start_index, end_index). The cells at the
     156             :   // boundary of the range are updated with atomic compare and swap operation.
     157             :   // The inner cells are updated with relaxed write.
     158             :   void SetRange(uint32_t start_index, uint32_t end_index);
     159             : 
     160             :   // Clears all bits in the range [start_index, end_index). The cells at the
     161             :   // boundary of the range are updated with atomic compare and swap operation.
     162             :   // The inner cells are updated with relaxed write.
     163             :   void ClearRange(uint32_t start_index, uint32_t end_index);
     164             : 
     165             :   // Returns true if all bits in the range [start_index, end_index) are set.
     166             :   bool AllBitsSetInRange(uint32_t start_index, uint32_t end_index);
     167             : 
     168             :   // Returns true if all bits in the range [start_index, end_index) are cleared.
     169             :   bool AllBitsClearInRange(uint32_t start_index, uint32_t end_index);
     170             : 
     171             :   void Print();
     172             : 
     173             :   bool IsClean();
     174             : };
     175             : 
     176             : template <>
     177             : inline void Bitmap::SetBitsInCell<AccessMode::NON_ATOMIC>(uint32_t cell_index,
     178             :                                                           uint32_t mask) {
     179             :   cells()[cell_index] |= mask;
     180             : }
     181             : 
     182             : template <>
     183             : inline void Bitmap::SetBitsInCell<AccessMode::ATOMIC>(uint32_t cell_index,
     184             :                                                       uint32_t mask) {
     185      287347 :   base::AsAtomic32::SetBits(cells() + cell_index, mask, mask);
     186             : }
     187             : 
     188             : template <>
     189             : inline void Bitmap::ClearBitsInCell<AccessMode::NON_ATOMIC>(uint32_t cell_index,
     190             :                                                             uint32_t mask) {
     191             :   cells()[cell_index] &= ~mask;
     192             : }
     193             : 
     194             : template <>
     195             : inline void Bitmap::ClearBitsInCell<AccessMode::ATOMIC>(uint32_t cell_index,
     196             :                                                         uint32_t mask) {
     197      170730 :   base::AsAtomic32::SetBits(cells() + cell_index, 0u, mask);
     198             : }
     199             : 
     200             : class Marking : public AllStatic {
     201             :  public:
     202             :   // TODO(hpayer): The current mark bit operations use as default NON_ATOMIC
     203             :   // mode for access. We should remove the default value or switch it with
     204             :   // ATOMIC as soon we add concurrency.
     205             : 
     206             :   // Impossible markbits: 01
     207             :   static const char* kImpossibleBitPattern;
     208             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     209             :   INLINE(static bool IsImpossible(MarkBit mark_bit)) {
     210             :     if (mode == AccessMode::NON_ATOMIC) {
     211          21 :       return !mark_bit.Get<mode>() && mark_bit.Next().Get<mode>();
     212             :     }
     213             :     // If we are in concurrent mode we can only tell if an object has the
     214             :     // impossible bit pattern if we read the first bit again after reading
     215             :     // the first and the second bit. If the first bit is till zero and the
     216             :     // second bit is one then the object has the impossible bit pattern.
     217           5 :     bool is_impossible = !mark_bit.Get<mode>() && mark_bit.Next().Get<mode>();
     218           5 :     if (is_impossible) {
     219           5 :       return !mark_bit.Get<mode>();
     220             :     }
     221             :     return false;
     222             :   }
     223             : 
     224             :   // Black markbits: 11
     225             :   static const char* kBlackBitPattern;
     226             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     227             :   INLINE(static bool IsBlack(MarkBit mark_bit)) {
     228    76799553 :     return mark_bit.Get<mode>() && mark_bit.Next().Get<mode>();
     229             :   }
     230             : 
     231             :   // White markbits: 00 - this is required by the mark bit clearer.
     232             :   static const char* kWhiteBitPattern;
     233             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     234             :   INLINE(static bool IsWhite(MarkBit mark_bit)) {
     235             :     DCHECK(!IsImpossible<mode>(mark_bit));
     236   244597930 :     return !mark_bit.Get<mode>();
     237             :   }
     238             : 
     239             :   // Grey markbits: 10
     240             :   static const char* kGreyBitPattern;
     241             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     242             :   INLINE(static bool IsGrey(MarkBit mark_bit)) {
     243    33440960 :     return mark_bit.Get<mode>() && !mark_bit.Next().Get<mode>();
     244             :   }
     245             : 
     246             :   // IsBlackOrGrey assumes that the first bit is set for black or grey
     247             :   // objects.
     248             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     249             :   INLINE(static bool IsBlackOrGrey(MarkBit mark_bit)) {
     250    85087810 :     return mark_bit.Get<mode>();
     251             :   }
     252             : 
     253             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     254             :   INLINE(static void MarkWhite(MarkBit markbit)) {
     255             :     STATIC_ASSERT(mode == AccessMode::NON_ATOMIC);
     256        4045 :     markbit.Clear<mode>();
     257        4045 :     markbit.Next().Clear<mode>();
     258             :   }
     259             : 
     260             :   // Warning: this method is not safe in general in concurrent scenarios.
     261             :   // If you know that nobody else will change the bits on the given location
     262             :   // then you may use it.
     263             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     264             :   INLINE(static void MarkBlack(MarkBit markbit)) {
     265             :     markbit.Set<mode>();
     266             :     markbit.Next().Set<mode>();
     267             :   }
     268             : 
     269             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     270             :   INLINE(static bool WhiteToGrey(MarkBit markbit)) {
     271  4722004226 :     return markbit.Set<mode>();
     272             :   }
     273             : 
     274             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     275             :   INLINE(static bool WhiteToBlack(MarkBit markbit)) {
     276           3 :     return markbit.Set<mode>() && markbit.Next().Set<mode>();
     277             :   }
     278             : 
     279             :   template <AccessMode mode = AccessMode::NON_ATOMIC>
     280             :   INLINE(static bool GreyToBlack(MarkBit markbit)) {
     281   621589586 :     return markbit.Get<mode>() && markbit.Next().Set<mode>();
     282             :   }
     283             : 
     284             :   enum ObjectColor {
     285             :     BLACK_OBJECT,
     286             :     WHITE_OBJECT,
     287             :     GREY_OBJECT,
     288             :     IMPOSSIBLE_COLOR
     289             :   };
     290             : 
     291             :   static const char* ColorName(ObjectColor color) {
     292             :     switch (color) {
     293             :       case BLACK_OBJECT:
     294             :         return "black";
     295             :       case WHITE_OBJECT:
     296             :         return "white";
     297             :       case GREY_OBJECT:
     298             :         return "grey";
     299             :       case IMPOSSIBLE_COLOR:
     300             :         return "impossible";
     301             :     }
     302             :     return "error";
     303             :   }
     304             : 
     305           0 :   static ObjectColor Color(MarkBit mark_bit) {
     306           0 :     if (IsBlack(mark_bit)) return BLACK_OBJECT;
     307           0 :     if (IsWhite(mark_bit)) return WHITE_OBJECT;
     308           0 :     if (IsGrey(mark_bit)) return GREY_OBJECT;
     309           0 :     UNREACHABLE();
     310             :   }
     311             : 
     312             :  private:
     313             :   DISALLOW_IMPLICIT_CONSTRUCTORS(Marking);
     314             : };
     315             : 
     316             : }  // namespace internal
     317             : }  // namespace v8
     318             : 
     319             : #endif  // V8_MARKING_H_

Generated by: LCOV version 1.10