V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
pointer-with-payload.h
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>
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>
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:
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  PointerWithPayload(PointerType* pointer, PayloadType payload) {
64  update(pointer, payload);
65  }
66 
67  V8_INLINE PointerType* GetPointer() const {
68  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  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  pointer_ = reinterpret_cast<uintptr_t>(newptr) | (pointer_ & kPayloadMask);
83  DCHECK_EQ(GetPointer(), newptr);
84  }
85 
86  V8_INLINE PayloadType GetPayload() const {
87  return static_cast<PayloadType>(pointer_ & kPayloadMask);
88  }
89 
90  V8_INLINE void SetPayload(PayloadType new_payload) {
91  uintptr_t new_payload_ptr = static_cast<uintptr_t>(new_payload);
92  DCHECK_EQ(new_payload_ptr & kPayloadMask, new_payload_ptr);
93  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_
Definition: libplatform.h:13