v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
tagged-field.h
Go to the documentation of this file.
1// Copyright 2019 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_OBJECTS_TAGGED_FIELD_H_
6#define V8_OBJECTS_TAGGED_FIELD_H_
7
9#include "src/base/macros.h"
11#include "src/common/globals.h"
14
15namespace v8::internal {
16
17// TaggedMember<T> represents an potentially compressed V8 tagged pointer, which
18// is intended to be used as a member of a V8 object class.
19//
20// TODO(leszeks): Merge with TaggedField.
21template <typename T, typename CompressionScheme = V8HeapCompressionScheme>
22class TaggedMember;
23
24// Base class for all TaggedMember<T> classes.
25// TODO(leszeks): Merge with TaggedImpl.
26// TODO(leszeks): Maybe split STRONG and WEAK bases.
28
29template <typename T, typename CompressionScheme>
31 public:
32 constexpr TaggedMember() = default;
33
34 inline Tagged<T> load() const;
35 inline void store(HeapObjectLayout* host, Tagged<T> value,
37 inline void store_no_write_barrier(Tagged<T> value);
38
39 inline Tagged<T> Relaxed_Load() const;
40 inline void Relaxed_Store(HeapObjectLayout* host, Tagged<T> value,
43
44 inline Tagged<T> Acquire_Load() const;
45 inline void Release_Store(HeapObjectLayout* host, Tagged<T> value,
48
49 inline Tagged<T> SeqCst_Load() const;
50 inline void SeqCst_Store(HeapObjectLayout* host, Tagged<T> value,
53
57 HeapObjectLayout* host, Tagged<T> expected_value, Tagged<T> value,
59
60 private:
61 inline void WriteBarrier(HeapObjectLayout* host, Tagged<T> value,
62 WriteBarrierMode mode);
63 static inline Address tagged_to_full(Tagged_t tagged_value);
64 static inline Tagged_t full_to_tagged(Address value);
65};
66
67static_assert(alignof(TaggedMember<Object>) == alignof(Tagged_t));
68static_assert(sizeof(TaggedMember<Object>) == sizeof(Tagged_t));
69
70template <typename T>
72 public:
74
76 void set_value(T value) { base::WriteUnalignedValue(storage_, value); }
77
78 protected:
79 alignas(alignof(Tagged_t)) char storage_[sizeof(T)];
80};
81
83 public:
85
86 uint64_t value_as_bits() const {
88 }
89 void set_value_as_bits(uint64_t value) {
91 }
92};
93static_assert(alignof(UnalignedDoubleMember) == alignof(Tagged_t));
94static_assert(sizeof(UnalignedDoubleMember) == sizeof(double));
95
96// FLEXIBLE_ARRAY_MEMBER(T, name) represents a marker for a variable-sized
97// suffix of members for a type.
98//
99// It behaves as if it were the last member of a class, and creates an accessor
100// for `T* name()`.
101//
102// This macro is used instead of the C99 flexible array member syntax, because
103//
104// a) That syntax is only in C++ as an extension,
105// b) On all our major compilers, it doesn't allow the class to have
106// subclasses (which means it doesn't work for e.g. TaggedArrayBase or
107// BigIntBase),
108// c) The similar zero-length array extension _also_ doesn't allow subclasses
109// on some compilers (specifically, MSVC).
110//
111// On compilers that do support zero length arrays (i.e. not MSVC), we use one
112// of these instead of `this` pointer fiddling. This gives LLVM better
113// information for optimization, and gives us the warnings we'd want to have
114// (e.g. only allowing one FAM in a class, ensuring that OFFSET_OF_DATA_START is
115// only used on classes with a FAM) on clang -- the MSVC version then doesn't
116// check the same constraints, and relies on the code being equivalent enough.
117#if V8_CC_MSVC && !defined(__clang__)
118// MSVC doesn't support zero length arrays in base classes. Cast the
119// one-past-this value to a zero length array reference, so that the return
120// values match that in GCC/clang.
121#define FLEXIBLE_ARRAY_MEMBER(Type, name) \
122 using FlexibleDataReturnType = Type[0]; \
123 FlexibleDataReturnType& name() { \
124 static_assert(alignof(Type) <= alignof(decltype(*this))); \
125 using ReturnType = Type[0]; \
126 return reinterpret_cast<ReturnType&>(*(this + 1)); \
127 } \
128 const FlexibleDataReturnType& name() const { \
129 static_assert(alignof(Type) <= alignof(decltype(*this))); \
130 using ReturnType = Type[0]; \
131 return reinterpret_cast<const ReturnType&>(*(this + 1)); \
132 } \
133 using FlexibleDataType = Type
134#else
135// GCC and clang allow zero length arrays in base classes. Return the zero
136// length array by reference, to avoid array-to-pointer decay which can lose
137// aliasing information.
138#define FLEXIBLE_ARRAY_MEMBER(Type, name) \
139 using FlexibleDataReturnType = Type[0]; \
140 FlexibleDataReturnType& name() { return flexible_array_member_data_; } \
141 const FlexibleDataReturnType& name() const { \
142 return flexible_array_member_data_; \
143 } \
144 Type flexible_array_member_data_[0]; \
145 \
146 public: \
147 template <typename Class> \
148 static constexpr auto OffsetOfDataStart() { \
149 /* Produce a compiler error if {Class} is not this class */ \
150 static_assert(base::tmp::lazy_true< \
151 decltype(std::declval<Class>() \
152 .flexible_array_member_data_)>::value); \
153 return static_cast<int>(offsetof(Class, flexible_array_member_data_)); \
154 } \
155 \
156 private: \
157 using FlexibleDataType = Type
158#endif
159
160// OFFSET_OF_DATA_START(T) returns the offset of the FLEXIBLE_ARRAY_MEMBER of
161// the class T.
162#if V8_CC_MSVC && !defined(__clang__)
163#define OFFSET_OF_DATA_START(Type) sizeof(Type)
164#else
165#define OFFSET_OF_DATA_START(Type) Type::template OffsetOfDataStart<Type>()
166#endif
167
168// This helper static class represents a tagged field of type T at offset
169// kFieldOffset inside some host HeapObject.
170// For full-pointer mode this type adds no overhead but when pointer
171// compression is enabled such class allows us to use proper decompression
172// function depending on the field type.
173template <typename T, int kFieldOffset = 0,
174 typename CompressionScheme = V8HeapCompressionScheme>
175class TaggedField : public AllStatic {
176 public:
177 static_assert(is_taggable_v<T> || std::is_same<MapWord, T>::value,
178 "T must be strong or weak tagged type or MapWord");
179
180 // True for Smi fields.
181 static constexpr bool kIsSmi = std::is_same<Smi, T>::value;
182
183 // True for HeapObject and MapWord fields. The latter may look like a Smi
184 // if it contains forwarding pointer but still requires tagged pointer
185 // decompression.
186 static constexpr bool kIsHeapObject =
187 is_subtype<T, HeapObject>::value || std::is_same_v<MapWord, T>;
188
189 // Types should be wrapped in Tagged<>, except for MapWord which is used
190 // directly.
191 // TODO(leszeks): Clean this up to be more uniform.
192 using PtrType =
193 std::conditional_t<std::is_same_v<MapWord, T>, MapWord, Tagged<T>>;
194
195 static inline Address address(Tagged<HeapObject> host, int offset = 0);
196
197 static inline PtrType load(Tagged<HeapObject> host, int offset = 0);
198 static inline PtrType load(PtrComprCageBase cage_base,
199 Tagged<HeapObject> host, int offset = 0);
200
201 static inline void store(Tagged<HeapObject> host, PtrType value);
202 static inline void store(Tagged<HeapObject> host, int offset, PtrType value);
203
204 static inline PtrType Relaxed_Load(Tagged<HeapObject> host, int offset = 0);
205 static inline PtrType Relaxed_Load(PtrComprCageBase cage_base,
206 Tagged<HeapObject> host, int offset = 0);
207
208 static inline void Relaxed_Store(Tagged<HeapObject> host, PtrType value);
209 static inline void Relaxed_Store(Tagged<HeapObject> host, int offset,
210 PtrType value);
211
212 static inline PtrType Acquire_Load(Tagged<HeapObject> host, int offset = 0);
213 static inline PtrType Acquire_Load_No_Unpack(PtrComprCageBase cage_base,
215 int offset = 0);
216 static inline PtrType Acquire_Load(PtrComprCageBase cage_base,
217 Tagged<HeapObject> host, int offset = 0);
218
219 static inline PtrType SeqCst_Load(Tagged<HeapObject> host, int offset = 0);
220 static inline PtrType SeqCst_Load(PtrComprCageBase cage_base,
221 Tagged<HeapObject> host, int offset = 0);
222
223 static inline void Release_Store(Tagged<HeapObject> host, PtrType value);
224 static inline void Release_Store(Tagged<HeapObject> host, int offset,
225 PtrType value);
226
227 static inline void SeqCst_Store(Tagged<HeapObject> host, PtrType value);
228 static inline void SeqCst_Store(Tagged<HeapObject> host, int offset,
229 PtrType value);
230
231 static inline PtrType SeqCst_Swap(Tagged<HeapObject> host, int offset,
232 PtrType value);
233 static inline PtrType SeqCst_Swap(PtrComprCageBase cage_base,
234 Tagged<HeapObject> host, int offset,
235 PtrType value);
236
238 PtrType old, PtrType value);
240 PtrType old, PtrType value);
242 int offset, PtrType old,
243 PtrType value);
244
245 // Note: Use these *_Map_Word methods only when loading a MapWord from a
246 // MapField.
247 static inline PtrType Relaxed_Load_Map_Word(PtrComprCageBase cage_base,
248 Tagged<HeapObject> host);
249 static inline void Relaxed_Store_Map_Word(Tagged<HeapObject> host,
250 PtrType value);
251 static inline void Release_Store_Map_Word(Tagged<HeapObject> host,
252 PtrType value);
253
254 private:
255 static inline Tagged_t* location(Tagged<HeapObject> host, int offset = 0);
256
257 template <typename TOnHeapAddress>
258 static inline Address tagged_to_full(TOnHeapAddress on_heap_addr,
259 Tagged_t tagged_value);
260
261 static inline Tagged_t full_to_tagged(Address value);
262};
263
264template <typename T>
265class TaggedField<Tagged<T>> : public TaggedField<T> {};
266
267template <typename T, int kFieldOffset>
268class TaggedField<Tagged<T>, kFieldOffset>
269 : public TaggedField<T, kFieldOffset> {};
270
271template <typename T, int kFieldOffset, typename CompressionScheme>
272class TaggedField<Tagged<T>, kFieldOffset, CompressionScheme>
273 : public TaggedField<T, kFieldOffset, CompressionScheme> {};
274
275} // namespace v8::internal
276
277#endif // V8_OBJECTS_TAGGED_FIELD_H_
#define T
static void SeqCst_Store(Tagged< HeapObject > host, PtrType value)
static Tagged_t Relaxed_CompareAndSwap(Tagged< HeapObject > host, PtrType old, PtrType value)
static void Release_Store(Tagged< HeapObject > host, PtrType value)
std::conditional_t< std::is_same_v< MapWord, T >, MapWord, Tagged< T > > PtrType
static PtrType load(Tagged< HeapObject > host, int offset=0)
static void Relaxed_Store(Tagged< HeapObject > host, PtrType value)
static void Relaxed_Store_Map_Word(Tagged< HeapObject > host, PtrType value)
static PtrType Relaxed_Load(Tagged< HeapObject > host, int offset=0)
static Address address(Tagged< HeapObject > host, int offset=0)
static constexpr bool kIsHeapObject
static Tagged_t full_to_tagged(Address value)
static PtrType Acquire_Load_No_Unpack(PtrComprCageBase cage_base, Tagged< HeapObject > host, int offset=0)
static PtrType SeqCst_CompareAndSwap(Tagged< HeapObject > host, int offset, PtrType old, PtrType value)
static void store(Tagged< HeapObject > host, PtrType value)
static Tagged_t Release_CompareAndSwap(Tagged< HeapObject > host, PtrType old, PtrType value)
static Tagged_t * location(Tagged< HeapObject > host, int offset=0)
static PtrType Acquire_Load(Tagged< HeapObject > host, int offset=0)
static PtrType SeqCst_Load(Tagged< HeapObject > host, int offset=0)
static Address tagged_to_full(TOnHeapAddress on_heap_addr, Tagged_t tagged_value)
static PtrType SeqCst_Swap(Tagged< HeapObject > host, int offset, PtrType value)
static constexpr bool kIsSmi
static void Release_Store_Map_Word(Tagged< HeapObject > host, PtrType value)
static PtrType Relaxed_Load_Map_Word(PtrComprCageBase cage_base, Tagged< HeapObject > host)
Tagged< T > SeqCst_Load() const
Tagged< T > Relaxed_Load() const
void store(HeapObjectLayout *host, Tagged< T > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
Tagged< T > SeqCst_Swap(HeapObjectLayout *host, Tagged< T > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
void SeqCst_Store_no_write_barrier(Tagged< T > value)
void Relaxed_Store_no_write_barrier(Tagged< T > value)
Tagged< T > SeqCst_CompareAndSwap(HeapObjectLayout *host, Tagged< T > expected_value, Tagged< T > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
void store_no_write_barrier(Tagged< T > value)
void Release_Store_no_write_barrier(Tagged< T > value)
static Address tagged_to_full(Tagged_t tagged_value)
void SeqCst_Store(HeapObjectLayout *host, Tagged< T > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
void Release_Store(HeapObjectLayout *host, Tagged< T > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
void WriteBarrier(HeapObjectLayout *host, Tagged< T > value, WriteBarrierMode mode)
Tagged< T > Acquire_Load() const
void Relaxed_Store(HeapObjectLayout *host, Tagged< T > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
constexpr TaggedMember()=default
static Tagged_t full_to_tagged(Address value)
void set_value_as_bits(uint64_t value)
int32_t offset
static V ReadUnalignedValue(Address p)
Definition memory.h:28
static void WriteUnalignedValue(Address p, V value)
Definition memory.h:41
@ UPDATE_WRITE_BARRIER
Definition objects.h:55
Address Tagged_t
Definition globals.h:547
static constexpr bool is_taggable_v
Definition tagged.h:316
V8HeapCompressionSchemeImpl< MainCage > V8HeapCompressionScheme
Definition globals.h:1137