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