Loading...
Searching...
No Matches
tagged-member.h
Go to the documentation of this file.
1// Copyright 2025 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 INCLUDE_CPPGC_TAGGED_MEMBER_H_
6#define INCLUDE_CPPGC_TAGGED_MEMBER_H_
7
8#include <atomic>
9#include <concepts>
10#include <cstddef>
11#include <type_traits>
12
14#include "cppgc/macros.h"
15#include "cppgc/member.h"
16#include "cppgc/visitor.h"
17
18namespace cppgc::subtle {
19
20// The class allows to store a Member along with a single bit tag. It uses
21// distinct tag types, Tag1 and Tag2, to represent the two states of the tag.
22// The tag is stored in the least significant bit of the pointer.
23//
24// Example usage:
25// struct ParentTag {};
26// struct ShadowHostTag {};
27//
28// /* Constructs a member with the pointer to parent tag: */
29// TaggedUncompressedMember<Node, ParentTag, ShadowHostTag>
30// m(ParentTag{}, parent);
31template <typename Pointee, typename Tag1, typename Tag2>
34 static constexpr uintptr_t kTagBit = 0b1;
36 "The tag must live in the alignment bits of the pointer.");
37
38 public:
39 TaggedUncompressedMember(Tag1, Pointee* ptr) : ptr_(ptr) {}
40 TaggedUncompressedMember(Tag2, Pointee* ptr)
41 : ptr_(reinterpret_cast<Pointee*>(reinterpret_cast<uintptr_t>(ptr) |
42 kTagBit)) {}
43
44 template <typename Tag>
45 Pointee* GetAs() const {
46 auto* raw = ptr_.Get();
47 if constexpr (std::same_as<Tag, Tag1>) {
48 CPPGC_DCHECK(Is<Tag1>());
49 return raw;
50 } else {
51 static_assert(std::same_as<Tag, Tag2>);
52 CPPGC_DCHECK(Is<Tag2>());
53 return GetUntagged();
54 }
55 }
56
57 template <typename Tag>
58 Pointee* TryGetAs() const {
59 auto* raw = ptr_.Get();
60 if constexpr (std::same_as<Tag, Tag1>) {
61 return (reinterpret_cast<uintptr_t>(raw) & kTagBit) ? nullptr : raw;
62 } else {
63 static_assert(std::same_as<Tag, Tag2>);
64 return (reinterpret_cast<uintptr_t>(raw) & kTagBit)
65 ? reinterpret_cast<Pointee*>(reinterpret_cast<uintptr_t>(raw) &
66 ~kTagBit)
67 : nullptr;
68 }
69 }
70
71 Pointee* GetUntagged() const {
72 return reinterpret_cast<Pointee*>(reinterpret_cast<uintptr_t>(ptr_.Get()) &
73 ~kTagBit);
74 }
75
76 template <typename Tag>
77 void SetAs(Pointee* pointee) {
78 if constexpr (std::same_as<Tag, Tag1>) {
79 ptr_ = pointee;
80 } else {
81 static_assert(std::same_as<Tag, Tag2>);
82 ptr_ = reinterpret_cast<Pointee*>(reinterpret_cast<uintptr_t>(pointee) |
83 kTagBit);
84 }
85 }
86
87 template <typename Tag>
88 bool Is() const {
89 const bool tag_set = reinterpret_cast<uintptr_t>(ptr_.Get()) & kTagBit;
90 if constexpr (std::same_as<Tag, Tag1>) {
91 return !tag_set;
92 } else {
93 static_assert(std::same_as<Tag, Tag2>);
94 return tag_set;
95 }
96 }
97
98 void Trace(Visitor* v) const {
99 // Construct an untagged pointer and pass it to Visitor::Trace(). The plugin
100 // would warn that ptr_ is untraced, which is why CPPGC_PLUGIN_IGNORE is
101 // used.
102 auto* untagged = reinterpret_cast<Pointee*>(
103 reinterpret_cast<uintptr_t>(ptr_.GetRawAtomic()) & ~kTagBit);
104 UncompressedMember<Pointee> temp(untagged);
105 v->Trace(temp);
106 }
107
108 private:
109 CPPGC_PLUGIN_IGNORE("See Trace()") UncompressedMember<Pointee> ptr_;
110};
111
112} // namespace cppgc::subtle
113
114#endif // INCLUDE_CPPGC_TAGGED_MEMBER_H_
Definition: visitor.h:75
void Trace(const Member< T > &member)
Definition: visitor.h:93
Definition: member.h:79
Definition: tagged-member.h:32
Pointee * GetUntagged() const
Definition: tagged-member.h:71
Pointee * GetAs() const
Definition: tagged-member.h:45
void Trace(Visitor *v) const
Definition: tagged-member.h:98
TaggedUncompressedMember(Tag2, Pointee *ptr)
Definition: tagged-member.h:40
bool Is() const
Definition: tagged-member.h:88
void SetAs(Pointee *pointee)
Definition: tagged-member.h:77
static constexpr uintptr_t kTagBit
Definition: tagged-member.h:34
TaggedUncompressedMember(Tag1, Pointee *ptr)
Definition: tagged-member.h:39
Pointee * TryGetAs() const
Definition: tagged-member.h:58
#define CPPGC_DCHECK(condition)
Definition: logging.h:36
#define CPPGC_PLUGIN_IGNORE(bug_or_reason)
Definition: macros.h:46
#define CPPGC_DISALLOW_NEW()
Definition: macros.h:14
constexpr size_t kAllocationGranularity
Definition: api-constants.h:65
Definition: cross-thread-persistent.h:431