v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
pointer-with-payload.h
Go to the documentation of this file.
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_BASE_POINTER_WITH_PAYLOAD_H_
6#define V8_BASE_POINTER_WITH_PAYLOAD_H_
7
8#include <cstdint>
9#include <type_traits>
10
11#include "src/base/logging.h"
12
13namespace v8 {
14namespace base {
15
16template <typename PointerType>
18 static constexpr int kAvailableBits =
19 alignof(PointerType) >= 8 ? 3 : alignof(PointerType) >= 4 ? 2 : 1;
20};
21
22// Assume void* has the same payloads as void**, under the assumption that it's
23// used for classes that contain at least one pointer.
24template <>
26};
27
28// PointerWithPayload combines a PointerType* an a small PayloadType into
29// one. The bits of the storage type get packed into the lower bits of the
30// pointer that are free due to alignment. The user needs to specify how many
31// bits are needed to store the PayloadType, allowing Types that by default are
32// larger to be stored.
33//
34// Example:
35// PointerWithPayload<int *, bool, 1> data_and_flag;
36//
37// Here we store a bool that needs 1 bit of storage state into the lower bits
38// of int *, which points to some int data;
39template <typename PointerType, typename PayloadType, int NumPayloadBits>
41 public:
42 PointerWithPayload() = default;
43
44 explicit PointerWithPayload(PointerType* pointer)
45 : pointer_with_payload_(reinterpret_cast<uintptr_t>(pointer)) {
46 DCHECK_EQ(GetPointer(), pointer);
47 DCHECK_EQ(GetPayload(), static_cast<PayloadType>(0));
48 }
49
50 explicit PointerWithPayload(PayloadType payload)
51 : pointer_with_payload_(static_cast<uintptr_t>(payload)) {
52 DCHECK_EQ(GetPointer(), nullptr);
53 DCHECK_EQ(GetPayload(), payload);
54 }
55
56 PointerWithPayload(PointerType* pointer, PayloadType payload) {
57 Update(pointer, payload);
58 }
59
60 V8_INLINE PointerType* GetPointer() const {
61 return reinterpret_cast<PointerType*>(pointer_with_payload_ & kPointerMask);
62 }
63
64 // An optimized version of GetPointer for when we know the payload value.
65 V8_INLINE PointerType* GetPointerWithKnownPayload(PayloadType payload) const {
66 DCHECK_EQ(GetPayload(), payload);
67 return reinterpret_cast<PointerType*>(pointer_with_payload_ -
68 static_cast<uintptr_t>(payload));
69 }
70
71 V8_INLINE PointerType* operator->() const { return GetPointer(); }
72
73 V8_INLINE void Update(PointerType* new_pointer, PayloadType new_payload) {
74 pointer_with_payload_ = 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_with_payload_ = reinterpret_cast<uintptr_t>(newptr) |
84 DCHECK_EQ(GetPointer(), newptr);
85 }
86
87 V8_INLINE PayloadType GetPayload() const {
88 return static_cast<PayloadType>(pointer_with_payload_ & kPayloadMask);
89 }
90
91 V8_INLINE void SetPayload(PayloadType new_payload) {
92 uintptr_t new_payload_ptr = static_cast<uintptr_t>(new_payload);
93 DCHECK_EQ(new_payload_ptr & kPayloadMask, new_payload_ptr);
95 (pointer_with_payload_ & kPointerMask) | new_payload_ptr;
96 DCHECK_EQ(GetPayload(), new_payload);
97 }
98
99 uintptr_t raw() const { return pointer_with_payload_; }
100
101 private:
103 typename std::remove_const<PointerType>::type>::kAvailableBits;
104 static_assert(
105 kAvailableBits >= NumPayloadBits,
106 "Ptr does not have sufficient alignment for the selected amount of "
107 "storage bits. Override PointerWithPayloadTraits to guarantee available "
108 "bits manually.");
109
110 static constexpr uintptr_t kPayloadMask =
111 (uintptr_t{1} << NumPayloadBits) - 1;
112 static constexpr uintptr_t kPointerMask = ~kPayloadMask;
113
115};
116
117template <typename PointerType, typename PayloadType, int NumPayloadBits>
123
124} // namespace base
125} // namespace v8
126
127#endif // V8_BASE_POINTER_WITH_PAYLOAD_H_
V8_INLINE PointerType * operator->() const
PointerWithPayload(PayloadType payload)
V8_INLINE void Update(PointerType *new_pointer, PayloadType new_payload)
V8_INLINE PointerType * GetPointer() const
static constexpr uintptr_t kPayloadMask
V8_INLINE void SetPayload(PayloadType new_payload)
V8_INLINE PointerType * GetPointerWithKnownPayload(PayloadType payload) const
V8_INLINE PayloadType GetPayload() const
PointerWithPayload(PointerType *pointer, PayloadType payload)
static constexpr uintptr_t kPointerMask
V8_INLINE void SetPointer(PointerType *newptr)
PointerWithPayload(PointerType *pointer)
bool operator==(PointerWithPayload< PointerType, PayloadType, NumPayloadBits > lhs, PointerWithPayload< PointerType, PayloadType, NumPayloadBits > rhs)
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_INLINE
Definition v8config.h:500