LCOV - code coverage report
Current view: top level - src - pointer-with-payload.h (source / functions) Hit Total Coverage
Test: app.info Lines: 5 8 62.5 %
Date: 2019-02-19 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright 2018 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_POINTER_WITH_PAYLOAD_H_
       6             : #define V8_POINTER_WITH_PAYLOAD_H_
       7             : 
       8             : #include <cstdint>
       9             : #include <type_traits>
      10             : 
      11             : #include "include/v8config.h"
      12             : #include "src/base/logging.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17             : template <typename PointerType>
      18             : struct PointerWithPayloadTraits {
      19             :   static constexpr int value =
      20             :       alignof(PointerType) >= 8 ? 3 : alignof(PointerType) >= 4 ? 2 : 1;
      21             : };
      22             : 
      23             : // PointerWithPayload combines a PointerType* an a small PayloadType into
      24             : // one. The bits of the storage type get packed into the lower bits of the
      25             : // pointer that are free due to alignment. The user needs to specify how many
      26             : // bits are needed to store the PayloadType, allowing Types that by default are
      27             : // larger to be stored.
      28             : //
      29             : // Example:
      30             : //   PointerWithPayload<int *, bool, 1> data_and_flag;
      31             : //
      32             : //   Here we store a bool that needs 1 bit of storage state into the lower bits
      33             : //   of int *, which points to some int data;
      34             : 
      35             : template <typename PointerType, typename PayloadType, int NumPayloadBits>
      36             : class PointerWithPayload {
      37             :   // We have log2(ptr alignment) kAvailBits free to use
      38             :   static constexpr int kAvailBits = PointerWithPayloadTraits<
      39             :       typename std::remove_const<PointerType>::type>::value;
      40             :   static_assert(
      41             :       kAvailBits >= NumPayloadBits,
      42             :       "Ptr does not have sufficient alignment for the selected amount of "
      43             :       "storage bits.");
      44             : 
      45             :   static constexpr uintptr_t kPayloadMask = (uintptr_t{1} << kAvailBits) - 1;
      46             :   static constexpr uintptr_t kPointerMask = ~kPayloadMask;
      47             : 
      48             :  public:
      49           0 :   PointerWithPayload() {}
      50             : 
      51             :   explicit PointerWithPayload(PointerType* pointer)
      52             :       : pointer_(reinterpret_cast<uintptr_t>(pointer)) {
      53             :     DCHECK_EQ(GetPointer(), pointer);
      54             :     DCHECK_EQ(GetPayload(), static_cast<PayloadType>(0));
      55             :   }
      56             : 
      57             :   explicit PointerWithPayload(PayloadType payload)
      58             :       : pointer_(static_cast<uintptr_t>(payload)) {
      59             :     DCHECK_EQ(GetPointer(), nullptr);
      60             :     DCHECK_EQ(GetPayload(), payload);
      61             :   }
      62             : 
      63    51578267 :   PointerWithPayload(PointerType* pointer, PayloadType payload) {
      64             :     update(pointer, payload);
      65             :   }
      66             : 
      67             :   V8_INLINE PointerType* GetPointer() const {
      68    20140588 :     return reinterpret_cast<PointerType*>(pointer_ & kPointerMask);
      69             :   }
      70             : 
      71             :   V8_INLINE PointerType* operator->() const { return GetPointer(); }
      72             : 
      73             :   V8_INLINE void update(PointerType* new_pointer, PayloadType new_payload) {
      74    51828686 :     pointer_ = reinterpret_cast<uintptr_t>(new_pointer) |
      75             :                static_cast<uintptr_t>(new_payload);
      76             :     DCHECK_EQ(GetPayload(), new_payload);
      77             :     DCHECK_EQ(GetPointer(), new_pointer);
      78             :   }
      79             : 
      80             :   V8_INLINE void SetPointer(PointerType* newptr) {
      81             :     DCHECK_EQ(reinterpret_cast<uintptr_t>(newptr) & kPayloadMask, 0);
      82      132572 :     pointer_ = reinterpret_cast<uintptr_t>(newptr) | (pointer_ & kPayloadMask);
      83             :     DCHECK_EQ(GetPointer(), newptr);
      84             :   }
      85             : 
      86             :   V8_INLINE PayloadType GetPayload() const {
      87    17761406 :     return static_cast<PayloadType>(pointer_ & kPayloadMask);
      88             :   }
      89             : 
      90             :   V8_INLINE void SetPayload(PayloadType new_payload) {
      91           0 :     uintptr_t new_payload_ptr = static_cast<uintptr_t>(new_payload);
      92             :     DCHECK_EQ(new_payload_ptr & kPayloadMask, new_payload_ptr);
      93           0 :     pointer_ = (pointer_ & kPointerMask) | new_payload_ptr;
      94             :     DCHECK_EQ(GetPayload(), new_payload);
      95             :   }
      96             : 
      97             :  private:
      98             :   uintptr_t pointer_ = 0;
      99             : };
     100             : 
     101             : }  // namespace internal
     102             : }  // namespace v8
     103             : 
     104             : #endif  // V8_POINTER_WITH_PAYLOAD_H_

Generated by: LCOV version 1.10