summaryrefslogtreecommitdiff
path: root/deps/v8/src/utils/pointer-with-payload.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/utils/pointer-with-payload.h')
-rw-r--r--deps/v8/src/utils/pointer-with-payload.h104
1 files changed, 104 insertions, 0 deletions
diff --git a/deps/v8/src/utils/pointer-with-payload.h b/deps/v8/src/utils/pointer-with-payload.h
new file mode 100644
index 0000000000..1c140ff684
--- /dev/null
+++ b/deps/v8/src/utils/pointer-with-payload.h
@@ -0,0 +1,104 @@
+// Copyright 2018 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_UTILS_POINTER_WITH_PAYLOAD_H_
+#define V8_UTILS_POINTER_WITH_PAYLOAD_H_
+
+#include <cstdint>
+#include <type_traits>
+
+#include "include/v8config.h"
+#include "src/base/logging.h"
+
+namespace v8 {
+namespace internal {
+
+template <typename PointerType>
+struct PointerWithPayloadTraits {
+ static constexpr int value =
+ alignof(PointerType) >= 8 ? 3 : alignof(PointerType) >= 4 ? 2 : 1;
+};
+
+// PointerWithPayload combines a PointerType* an a small PayloadType into
+// one. The bits of the storage type get packed into the lower bits of the
+// pointer that are free due to alignment. The user needs to specify how many
+// bits are needed to store the PayloadType, allowing Types that by default are
+// larger to be stored.
+//
+// Example:
+// PointerWithPayload<int *, bool, 1> data_and_flag;
+//
+// Here we store a bool that needs 1 bit of storage state into the lower bits
+// of int *, which points to some int data;
+
+template <typename PointerType, typename PayloadType, int NumPayloadBits>
+class PointerWithPayload {
+ // We have log2(ptr alignment) kAvailBits free to use
+ static constexpr int kAvailBits = PointerWithPayloadTraits<
+ typename std::remove_const<PointerType>::type>::value;
+ static_assert(
+ kAvailBits >= NumPayloadBits,
+ "Ptr does not have sufficient alignment for the selected amount of "
+ "storage bits.");
+
+ static constexpr uintptr_t kPayloadMask = (uintptr_t{1} << kAvailBits) - 1;
+ static constexpr uintptr_t kPointerMask = ~kPayloadMask;
+
+ public:
+ PointerWithPayload() {}
+
+ explicit PointerWithPayload(PointerType* pointer)
+ : pointer_(reinterpret_cast<uintptr_t>(pointer)) {
+ DCHECK_EQ(GetPointer(), pointer);
+ DCHECK_EQ(GetPayload(), static_cast<PayloadType>(0));
+ }
+
+ explicit PointerWithPayload(PayloadType payload)
+ : pointer_(static_cast<uintptr_t>(payload)) {
+ DCHECK_EQ(GetPointer(), nullptr);
+ DCHECK_EQ(GetPayload(), payload);
+ }
+
+ PointerWithPayload(PointerType* pointer, PayloadType payload) {
+ update(pointer, payload);
+ }
+
+ V8_INLINE PointerType* GetPointer() const {
+ return reinterpret_cast<PointerType*>(pointer_ & kPointerMask);
+ }
+
+ V8_INLINE PointerType* operator->() const { return GetPointer(); }
+
+ V8_INLINE void update(PointerType* new_pointer, PayloadType new_payload) {
+ pointer_ = reinterpret_cast<uintptr_t>(new_pointer) |
+ static_cast<uintptr_t>(new_payload);
+ DCHECK_EQ(GetPayload(), new_payload);
+ DCHECK_EQ(GetPointer(), new_pointer);
+ }
+
+ V8_INLINE void SetPointer(PointerType* newptr) {
+ DCHECK_EQ(reinterpret_cast<uintptr_t>(newptr) & kPayloadMask, 0);
+ pointer_ = reinterpret_cast<uintptr_t>(newptr) | (pointer_ & kPayloadMask);
+ DCHECK_EQ(GetPointer(), newptr);
+ }
+
+ V8_INLINE PayloadType GetPayload() const {
+ return static_cast<PayloadType>(pointer_ & kPayloadMask);
+ }
+
+ V8_INLINE void SetPayload(PayloadType new_payload) {
+ uintptr_t new_payload_ptr = static_cast<uintptr_t>(new_payload);
+ DCHECK_EQ(new_payload_ptr & kPayloadMask, new_payload_ptr);
+ pointer_ = (pointer_ & kPointerMask) | new_payload_ptr;
+ DCHECK_EQ(GetPayload(), new_payload);
+ }
+
+ private:
+ uintptr_t pointer_ = 0;
+};
+
+} // namespace internal
+} // namespace v8
+
+#endif // V8_UTILS_POINTER_WITH_PAYLOAD_H_