1 // Copyright 2016 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.
5 // Note 1: Any file that includes this one should include object-macros-undef.h
8 // Note 2: This file is deliberately missing the include guards (the undeffing
9 // approach wouldn't work otherwise).
11 // PRESUBMIT_INTENTIONALLY_MISSING_INCLUDE_GUARD
13 // The accessors with RELAXED_, ACQUIRE_, and RELEASE_ prefixes should be used
14 // for fields that can be written to and read from multiple threads at the same
15 // time. See comments in src/base/atomicops.h for the memory ordering sematics.
17 #include "src/base/memory.h"
19 // V8 objects are defined as:
21 // V8_OBJECT class Foo : class Base {
25 // These macros are to enable warnings which ensure that there is no unwanted
26 // within-object padding.
29 _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic error \"-Wpadded\"")
31 // GCC wants this pragma to be a new statement, but we prefer to have
32 // V8_OBJECT_END look like part of the definition. Insert a semicolon before the
33 // pragma to make gcc happy, and use static_assert(true) to swallow the next
35 #define V8_OBJECT_END \
37 _Pragma("GCC diagnostic pop") static_assert(true)
39 #define V8_OBJECT __pragma(warning(push)) __pragma(warning(default : 4820))
40 #define V8_OBJECT_END __pragma(warning(pop))
46 // Since this changes visibility, it should always be last in a class
48 #define OBJECT_CONSTRUCTORS(Type, ...) \
50 constexpr Type() : __VA_ARGS__() {} \
52 /* For every object, add a `->` operator which returns a pointer to this \
53 object. This will allow smoother transition between T and Tagged<T>. */ \
54 Type* operator->() { return this; } \
55 const Type* operator->() const { return this; } \
58 friend class Tagged<Type>; \
60 /* Special constructor for constexpr construction which allows skipping type \
62 explicit constexpr V8_INLINE Type(Address ptr, HeapObject::SkipTypeCheckTag) \
63 : __VA_ARGS__(ptr, HeapObject::SkipTypeCheckTag()) {} \
65 explicit inline Type(Address ptr)
67 #define OBJECT_CONSTRUCTORS_IMPL(Type, Super) \
68 inline Type::Type(Address ptr) : Super(ptr) { SLOW_DCHECK(Is##Type(*this)); }
70 #define NEVER_READ_ONLY_SPACE \
71 inline Heap* GetHeap() const; \
72 inline Isolate* GetIsolate() const;
74 // TODO(leszeks): Add checks in the factory that we never allocate these
75 // objects in RO space.
76 #define NEVER_READ_ONLY_SPACE_IMPL(Type) \
77 Heap* Type::GetHeap() const { return GetHeapFromWritableObject(*this); } \
78 Isolate* Type::GetIsolate() const { \
79 return GetIsolateFromWritableObject(*this); \
82 #define DECL_PRIMITIVE_GETTER(name, type) inline type name() const;
84 #define DECL_PRIMITIVE_SETTER(name, type) inline void set_##name(type value);
86 #define DECL_PRIMITIVE_ACCESSORS(name, type) \
87 DECL_PRIMITIVE_GETTER(name, type) \
88 DECL_PRIMITIVE_SETTER(name, type)
90 #define DECL_BOOLEAN_ACCESSORS(name) DECL_PRIMITIVE_ACCESSORS(name, bool)
92 #define DECL_INT_ACCESSORS(name) DECL_PRIMITIVE_ACCESSORS(name, int)
94 #define DECL_INT32_ACCESSORS(name) DECL_PRIMITIVE_ACCESSORS(name, int32_t)
96 #define DECL_SANDBOXED_POINTER_ACCESSORS(name, type) \
97 DECL_PRIMITIVE_GETTER(name, type) \
98 DECL_PRIMITIVE_SETTER(name, type)
100 #define DECL_UINT16_ACCESSORS(name) DECL_PRIMITIVE_ACCESSORS(name, uint16_t)
102 #define DECL_INT16_ACCESSORS(name) DECL_PRIMITIVE_ACCESSORS(name, int16_t)
104 #define DECL_UINT8_ACCESSORS(name) DECL_PRIMITIVE_ACCESSORS(name, uint8_t)
106 #define DECL_RELAXED_PRIMITIVE_ACCESSORS(name, type) \
107 inline type name(RelaxedLoadTag) const; \
108 inline void set_##name(type value, RelaxedStoreTag);
110 #define DECL_RELAXED_INT32_ACCESSORS(name) \
111 DECL_RELAXED_PRIMITIVE_ACCESSORS(name, int32_t)
113 #define DECL_RELAXED_UINT32_ACCESSORS(name) \
114 DECL_RELAXED_PRIMITIVE_ACCESSORS(name, uint32_t)
116 #define DECL_RELAXED_UINT16_ACCESSORS(name) \
117 DECL_RELAXED_PRIMITIVE_ACCESSORS(name, uint16_t)
119 #define DECL_GETTER(name, type) \
120 inline type name() const; \
121 inline type name(PtrComprCageBase cage_base) const;
123 #define DEF_GETTER(holder, name, type) \
124 type holder::name() const { \
125 PtrComprCageBase cage_base = GetPtrComprCageBase(*this); \
126 return holder::name(cage_base); \
128 type holder::name(PtrComprCageBase cage_base) const
130 #define DEF_RELAXED_GETTER(holder, name, type) \
131 type holder::name(RelaxedLoadTag tag) const { \
132 PtrComprCageBase cage_base = GetPtrComprCageBase(*this); \
133 return holder::name(cage_base, tag); \
135 type holder::name(PtrComprCageBase cage_base, RelaxedLoadTag) const
137 #define DEF_ACQUIRE_GETTER(holder, name, type) \
138 type holder::name(AcquireLoadTag tag) const { \
139 PtrComprCageBase cage_base = GetPtrComprCageBase(*this); \
140 return holder::name(cage_base, tag); \
142 type holder::name(PtrComprCageBase cage_base, AcquireLoadTag) const
144 #define DEF_HEAP_OBJECT_PREDICATE(holder, name) \
145 bool name(Tagged<holder> obj) { \
146 PtrComprCageBase cage_base = GetPtrComprCageBase(obj); \
147 return name(obj, cage_base); \
149 bool name(Tagged<holder> obj, PtrComprCageBase cage_base)
151 #define TQ_FIELD_TYPE(name, tq_type) \
152 static constexpr const char* k##name##TqFieldType = tq_type;
154 #define DECL_FIELD_OFFSET_TQ(name, value, tq_type) \
155 static const int k##name##Offset = value; \
156 TQ_FIELD_TYPE(name, tq_type)
158 #define DECL_SETTER(name, type) \
159 inline void set_##name(type value, \
160 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
162 #define DECL_ACCESSORS(name, type) \
163 DECL_GETTER(name, type) \
164 DECL_SETTER(name, type)
166 #define DECL_ACCESSORS_LOAD_TAG(name, type, tag_type) \
167 inline type name(tag_type tag) const; \
168 inline type name(PtrComprCageBase cage_base, tag_type) const;
170 #define DECL_ACCESSORS_STORE_TAG(name, type, tag_type) \
171 inline void set_##name(type value, tag_type, \
172 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
174 #define DECL_RELAXED_GETTER(name, type) \
175 DECL_ACCESSORS_LOAD_TAG(name, type, RelaxedLoadTag)
177 #define DECL_RELAXED_SETTER(name, type) \
178 DECL_ACCESSORS_STORE_TAG(name, type, RelaxedStoreTag)
180 #define DECL_RELAXED_ACCESSORS(name, type) \
181 DECL_RELAXED_GETTER(name, type) \
182 DECL_RELAXED_SETTER(name, type)
184 #define DECL_ACQUIRE_GETTER(name, type) \
185 DECL_ACCESSORS_LOAD_TAG(name, type, AcquireLoadTag)
187 #define DECL_RELEASE_SETTER(name, type) \
188 DECL_ACCESSORS_STORE_TAG(name, type, ReleaseStoreTag)
190 #define DECL_RELEASE_ACQUIRE_ACCESSORS(name, type) \
191 DECL_ACQUIRE_GETTER(name, type) \
192 DECL_RELEASE_SETTER(name, type)
194 #define DECL_RELEASE_ACQUIRE_WEAK_ACCESSORS(name) \
195 DECL_ACQUIRE_GETTER(name, MaybeObject) \
196 DECL_RELEASE_SETTER(name, MaybeObject)
198 #define DECL_CAST(Type) \
199 V8_INLINE static Tagged<Type> cast(Tagged<Object> object); \
200 V8_INLINE static constexpr Tagged<Type> unchecked_cast( \
201 Tagged<Object> object) { \
202 return Tagged<Type>::unchecked_cast(object); \
205 #define CAST_ACCESSOR(Type) \
206 Tagged<Type> Type::cast(Tagged<Object> object) { \
207 return Tagged<Type>(Type(object.ptr())); \
210 #define DEF_PRIMITIVE_ACCESSORS(holder, name, offset, type) \
211 type holder::name() const { return ReadField<type>(offset); } \
212 void holder::set_##name(type value) { WriteField<type>(offset, value); }
214 #define INT_ACCESSORS(holder, name, offset) \
215 DEF_PRIMITIVE_ACCESSORS(holder, name, offset, int)
217 #define INT32_ACCESSORS(holder, name, offset) \
218 DEF_PRIMITIVE_ACCESSORS(holder, name, offset, int32_t)
220 #define UINT16_ACCESSORS(holder, name, offset) \
221 DEF_PRIMITIVE_ACCESSORS(holder, name, offset, uint16_t)
223 #define UINT8_ACCESSORS(holder, name, offset) \
224 DEF_PRIMITIVE_ACCESSORS(holder, name, offset, uint8_t)
226 #define RELAXED_INT32_ACCESSORS(holder, name, offset) \
227 int32_t holder::name(RelaxedLoadTag) const { \
228 return RELAXED_READ_INT32_FIELD(*this, offset); \
230 void holder::set_##name(int32_t value, RelaxedStoreTag) { \
231 RELAXED_WRITE_INT32_FIELD(*this, offset, value); \
234 #define RELAXED_UINT32_ACCESSORS(holder, name, offset) \
235 uint32_t holder::name(RelaxedLoadTag) const { \
236 return RELAXED_READ_UINT32_FIELD(*this, offset); \
238 void holder::set_##name(uint32_t value, RelaxedStoreTag) { \
239 RELAXED_WRITE_UINT32_FIELD(*this, offset, value); \
242 #define RELAXED_UINT16_ACCESSORS(holder, name, offset) \
243 uint16_t holder::name(RelaxedLoadTag) const { \
244 return RELAXED_READ_UINT16_FIELD(*this, offset); \
246 void holder::set_##name(uint16_t value, RelaxedStoreTag) { \
247 RELAXED_WRITE_UINT16_FIELD(*this, offset, value); \
250 #define ACCESSORS_CHECKED2(holder, name, type, offset, get_condition, \
252 DEF_GETTER(holder, name, type) { \
253 type value = TaggedField<type, offset>::load(cage_base, *this); \
254 DCHECK(get_condition); \
257 void holder::set_##name(type value, WriteBarrierMode mode) { \
258 DCHECK(set_condition); \
259 TaggedField<type, offset>::store(*this, value); \
260 CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode); \
263 #define ACCESSORS_CHECKED(holder, name, type, offset, condition) \
264 ACCESSORS_CHECKED2(holder, name, type, offset, condition, condition)
266 #define ACCESSORS(holder, name, type, offset) \
267 ACCESSORS_CHECKED(holder, name, type, offset, true)
269 // TODO(jgruber): Eventually, all accessors should be ported to the NOCAGE
270 // variant (which doesn't define a PtrComprCageBase overload). Once that's
271 // done, remove the cage-ful macros (e.g. ACCESSORS) and rename the cage-less
272 // macros (e.g. ACCESSORS_NOCAGE).
273 #define ACCESSORS_NOCAGE(holder, name, type, offset) \
274 type holder::name() const { \
275 PtrComprCageBase cage_base = GetPtrComprCageBase(*this); \
276 return TaggedField<type, offset>::load(cage_base, *this); \
278 void holder::set_##name(type value, WriteBarrierMode mode) { \
279 TaggedField<type, offset>::store(*this, value); \
280 CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode); \
283 #define RENAME_TORQUE_ACCESSORS(holder, name, torque_name, type) \
284 inline type holder::name() const { \
285 return TorqueGeneratedClass::torque_name(); \
287 inline type holder::name(PtrComprCageBase cage_base) const { \
288 return TorqueGeneratedClass::torque_name(cage_base); \
290 inline void holder::set_##name(type value, WriteBarrierMode mode) { \
291 TorqueGeneratedClass::set_##torque_name(value, mode); \
294 #define RENAME_PRIMITIVE_TORQUE_ACCESSORS(holder, name, torque_name, type) \
295 type holder::name() const { return TorqueGeneratedClass::torque_name(); } \
296 void holder::set_##name(type value) { \
297 TorqueGeneratedClass::set_##torque_name(value); \
300 #define ACCESSORS_RELAXED_CHECKED2(holder, name, type, offset, get_condition, \
302 type holder::name() const { \
303 PtrComprCageBase cage_base = GetPtrComprCageBase(*this); \
304 return holder::name(cage_base); \
306 type holder::name(PtrComprCageBase cage_base) const { \
307 type value = TaggedField<type, offset>::Relaxed_Load(cage_base, *this); \
308 DCHECK(get_condition); \
311 void holder::set_##name(type value, WriteBarrierMode mode) { \
312 DCHECK(set_condition); \
313 TaggedField<type, offset>::Relaxed_Store(*this, value); \
314 CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode); \
317 #define ACCESSORS_RELAXED_CHECKED(holder, name, type, offset, condition) \
318 ACCESSORS_RELAXED_CHECKED2(holder, name, type, offset, condition, condition)
320 #define ACCESSORS_RELAXED(holder, name, type, offset) \
321 ACCESSORS_RELAXED_CHECKED(holder, name, type, offset, true)
323 // Similar to ACCESSORS_RELAXED above but with respective relaxed tags.
324 #define RELAXED_ACCESSORS_CHECKED2(holder, name, type, offset, get_condition, \
326 DEF_RELAXED_GETTER(holder, name, type) { \
327 type value = TaggedField<type, offset>::Relaxed_Load(cage_base, *this); \
328 DCHECK(get_condition); \
331 void holder::set_##name(type value, RelaxedStoreTag, \
332 WriteBarrierMode mode) { \
333 DCHECK(set_condition); \
334 TaggedField<type, offset>::Relaxed_Store(*this, value); \
335 CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode); \
338 #define RELAXED_ACCESSORS_CHECKED(holder, name, type, offset, condition) \
339 RELAXED_ACCESSORS_CHECKED2(holder, name, type, offset, condition, condition)
341 #define RELAXED_ACCESSORS(holder, name, type, offset) \
342 RELAXED_ACCESSORS_CHECKED(holder, name, type, offset, true)
344 #define RELEASE_ACQUIRE_GETTER_CHECKED(holder, name, type, offset, \
346 DEF_ACQUIRE_GETTER(holder, name, type) { \
347 type value = TaggedField<type, offset>::Acquire_Load(cage_base, *this); \
348 DCHECK(get_condition); \
352 #define RELEASE_ACQUIRE_SETTER_CHECKED(holder, name, type, offset, \
354 void holder::set_##name(type value, ReleaseStoreTag, \
355 WriteBarrierMode mode) { \
356 DCHECK(set_condition); \
357 TaggedField<type, offset>::Release_Store(*this, value); \
358 CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode); \
361 #define RELEASE_ACQUIRE_ACCESSORS_CHECKED2(holder, name, type, offset, \
362 get_condition, set_condition) \
363 RELEASE_ACQUIRE_GETTER_CHECKED(holder, name, type, offset, get_condition) \
364 RELEASE_ACQUIRE_SETTER_CHECKED(holder, name, type, offset, set_condition)
366 #define RELEASE_ACQUIRE_ACCESSORS_CHECKED(holder, name, type, offset, \
368 RELEASE_ACQUIRE_ACCESSORS_CHECKED2(holder, name, type, offset, condition, \
371 #define RELEASE_ACQUIRE_ACCESSORS(holder, name, type, offset) \
372 RELEASE_ACQUIRE_ACCESSORS_CHECKED(holder, name, type, offset, true)
374 #define WEAK_ACCESSORS_CHECKED2(holder, name, offset, get_condition, \
376 DEF_GETTER(holder, name, MaybeObject) { \
377 MaybeObject value = \
378 TaggedField<MaybeObject, offset>::load(cage_base, *this); \
379 DCHECK(get_condition); \
382 void holder::set_##name(MaybeObject value, WriteBarrierMode mode) { \
383 DCHECK(set_condition); \
384 TaggedField<MaybeObject, offset>::store(*this, value); \
385 CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode); \
388 #define WEAK_ACCESSORS_CHECKED(holder, name, offset, condition) \
389 WEAK_ACCESSORS_CHECKED2(holder, name, offset, condition, condition)
391 #define WEAK_ACCESSORS(holder, name, offset) \
392 WEAK_ACCESSORS_CHECKED(holder, name, offset, true)
394 #define RELEASE_ACQUIRE_WEAK_ACCESSORS_CHECKED2(holder, name, offset, \
395 get_condition, set_condition) \
396 DEF_ACQUIRE_GETTER(holder, name, MaybeObject) { \
397 MaybeObject value = \
398 TaggedField<MaybeObject, offset>::Acquire_Load(cage_base, *this); \
399 DCHECK(get_condition); \
402 void holder::set_##name(MaybeObject value, ReleaseStoreTag, \
403 WriteBarrierMode mode) { \
404 DCHECK(set_condition); \
405 TaggedField<MaybeObject, offset>::Release_Store(*this, value); \
406 CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode); \
409 #define RELEASE_ACQUIRE_WEAK_ACCESSORS_CHECKED(holder, name, offset, \
411 RELEASE_ACQUIRE_WEAK_ACCESSORS_CHECKED2(holder, name, offset, condition, \
414 #define RELEASE_ACQUIRE_WEAK_ACCESSORS(holder, name, offset) \
415 RELEASE_ACQUIRE_WEAK_ACCESSORS_CHECKED(holder, name, offset, true)
417 // Getter that returns a Smi as an int and writes an int as a Smi.
418 #define SMI_ACCESSORS_CHECKED(holder, name, offset, condition) \
419 int holder::name() const { \
421 Tagged<Smi> value = TaggedField<Smi, offset>::load(*this); \
422 return value.value(); \
424 void holder::set_##name(int value) { \
426 TaggedField<Smi, offset>::store(*this, Smi::FromInt(value)); \
429 #define SMI_ACCESSORS(holder, name, offset) \
430 SMI_ACCESSORS_CHECKED(holder, name, offset, true)
432 #define DECL_RELEASE_ACQUIRE_INT_ACCESSORS(name) \
433 inline int name(AcquireLoadTag) const; \
434 inline void set_##name(int value, ReleaseStoreTag);
436 #define RELEASE_ACQUIRE_SMI_ACCESSORS(holder, name, offset) \
437 int holder::name(AcquireLoadTag) const { \
438 Tagged<Smi> value = TaggedField<Smi, offset>::Acquire_Load(*this); \
439 return value.value(); \
441 void holder::set_##name(int value, ReleaseStoreTag) { \
442 TaggedField<Smi, offset>::Release_Store(*this, Smi::FromInt(value)); \
445 #define DECL_RELAXED_INT_ACCESSORS(name) \
446 inline int name(RelaxedLoadTag) const; \
447 inline void set_##name(int value, RelaxedStoreTag);
449 #define RELAXED_SMI_ACCESSORS(holder, name, offset) \
450 int holder::name(RelaxedLoadTag) const { \
451 Tagged<Smi> value = TaggedField<Smi, offset>::Relaxed_Load(*this); \
452 return value.value(); \
454 void holder::set_##name(int value, RelaxedStoreTag) { \
455 TaggedField<Smi, offset>::Relaxed_Store(*this, Smi::FromInt(value)); \
458 #define BOOL_GETTER(holder, field, name, offset) \
459 bool holder::name() const { return BooleanBit::get(field(), offset); }
461 #define BOOL_ACCESSORS(holder, field, name, offset) \
462 bool holder::name() const { return BooleanBit::get(field(), offset); } \
463 void holder::set_##name(bool value) { \
464 set_##field(BooleanBit::set(field(), offset, value)); \
467 #define DECL_RELAXED_BOOL_ACCESSORS(name) \
468 inline bool name(RelaxedLoadTag) const; \
469 inline void set_##name(bool value, RelaxedStoreTag);
471 #define RELAXED_BOOL_ACCESSORS(holder, field, name, offset) \
472 bool holder::name(RelaxedLoadTag) const { \
473 return BooleanBit::get(field(kRelaxedLoad), offset); \
475 void holder::set_##name(bool value, RelaxedStoreTag) { \
476 set_##field(BooleanBit::set(field(kRelaxedLoad), offset, value), \
480 // Host objects in ReadOnlySpace can't define the isolate-less accessor.
481 #define DECL_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST(name, type) \
482 inline type name(i::Isolate* isolate_for_sandbox) const; \
483 inline void init_##name(i::Isolate* isolate, const type initial_value); \
484 inline void set_##name(i::Isolate* isolate, const type value);
486 // Host objects in ReadOnlySpace can't define the isolate-less accessor.
487 #define EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST(holder, name, type, \
489 type holder::name(i::Isolate* isolate_for_sandbox) const { \
490 /* This is a workaround for MSVC error C2440 not allowing */ \
491 /* reinterpret casts to the same type. */ \
493 Address result = HeapObject::ReadExternalPointerField<tag>( \
494 offset, isolate_for_sandbox); \
495 return reinterpret_cast<type>(reinterpret_cast<C2440*>(result)); \
497 void holder::init_##name(i::Isolate* isolate, const type initial_value) { \
498 /* This is a workaround for MSVC error C2440 not allowing */ \
499 /* reinterpret casts to the same type. */ \
501 Address the_value = reinterpret_cast<Address>( \
502 reinterpret_cast<const C2440*>(initial_value)); \
503 HeapObject::InitExternalPointerField<tag>(offset, isolate, the_value); \
505 void holder::set_##name(i::Isolate* isolate, const type value) { \
506 /* This is a workaround for MSVC error C2440 not allowing */ \
507 /* reinterpret casts to the same type. */ \
509 Address the_value = \
510 reinterpret_cast<Address>(reinterpret_cast<const C2440*>(value)); \
511 HeapObject::WriteExternalPointerField<tag>(offset, isolate, the_value); \
514 #define DECL_EXTERNAL_POINTER_ACCESSORS(name, type) \
515 inline type name() const; \
516 DECL_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST(name, type)
518 #define EXTERNAL_POINTER_ACCESSORS(holder, name, type, offset, tag) \
519 type holder::name() const { \
520 i::Isolate* isolate_for_sandbox = GetIsolateForSandbox(*this); \
521 return holder::name(isolate_for_sandbox); \
523 EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST(holder, name, type, offset, \
525 #define DECL_TRUSTED_POINTER_ACCESSORS(name, type) \
526 inline Tagged<type> name(const Isolate* isolate, AcquireLoadTag) const; \
527 inline void set_##name(Tagged<type> value, ReleaseStoreTag, \
528 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \
529 inline bool has_##name(AcquireLoadTag) const; \
530 inline void clear_##name(ReleaseStoreTag);
532 #define TRUSTED_POINTER_ACCESSORS(holder, name, type, offset, tag) \
533 inline Tagged<type> holder::name(const Isolate* isolate, AcquireLoadTag) \
535 DCHECK(has_##name(kAcquireLoad)); \
536 return type::cast(ReadTrustedPointerField<tag>(offset, isolate)); \
538 inline void holder::set_##name(Tagged<type> value, ReleaseStoreTag, \
539 WriteBarrierMode mode) { \
540 WriteTrustedPointerField<tag>(offset, value); \
541 CONDITIONAL_TRUSTED_POINTER_WRITE_BARRIER(*this, offset, tag, value, \
544 inline bool holder::has_##name(AcquireLoadTag) const { \
545 return !IsTrustedPointerFieldCleared(offset); \
547 inline void holder::clear_##name(ReleaseStoreTag) { \
548 ClearTrustedPointerField(offset); \
551 #define BIT_FIELD_ACCESSORS2(holder, get_field, set_field, name, BitField) \
552 typename BitField::FieldType holder::name() const { \
553 return BitField::decode(get_field()); \
555 void holder::set_##name(typename BitField::FieldType value) { \
556 set_##set_field(BitField::update(set_field(), value)); \
559 #define BIT_FIELD_ACCESSORS(holder, field, name, BitField) \
560 BIT_FIELD_ACCESSORS2(holder, field, field, name, BitField)
562 #define RELAXED_INT16_ACCESSORS(holder, name, offset) \
563 int16_t holder::name() const { \
564 return RELAXED_READ_INT16_FIELD(*this, offset); \
566 void holder::set_##name(int16_t value) { \
567 RELAXED_WRITE_INT16_FIELD(*this, offset, value); \
570 #define FIELD_ADDR(p, offset) ((p).ptr() + offset - kHeapObjectTag)
572 #define SEQ_CST_READ_FIELD(p, offset) \
573 TaggedField<Object>::SeqCst_Load(p, offset)
575 #define ACQUIRE_READ_FIELD(p, offset) \
576 TaggedField<Object>::Acquire_Load(p, offset)
578 #define RELAXED_READ_FIELD(p, offset) \
579 TaggedField<Object>::Relaxed_Load(p, offset)
581 #define RELAXED_READ_WEAK_FIELD(p, offset) \
582 TaggedField<MaybeObject>::Relaxed_Load(p, offset)
584 #define WRITE_FIELD(p, offset, value) \
585 TaggedField<Object>::store(p, offset, value)
587 #define SEQ_CST_WRITE_FIELD(p, offset, value) \
588 TaggedField<Object>::SeqCst_Store(p, offset, value)
590 #define RELEASE_WRITE_FIELD(p, offset, value) \
591 TaggedField<Object>::Release_Store(p, offset, value)
593 #define RELAXED_WRITE_FIELD(p, offset, value) \
594 TaggedField<Object>::Relaxed_Store(p, offset, value)
596 #define RELAXED_WRITE_WEAK_FIELD(p, offset, value) \
597 TaggedField<MaybeObject>::Relaxed_Store(p, offset, value)
599 #define SEQ_CST_SWAP_FIELD(p, offset, value) \
600 TaggedField<Object>::SeqCst_Swap(p, offset, value)
602 #define SEQ_CST_COMPARE_AND_SWAP_FIELD(p, offset, expected, value) \
603 TaggedField<Object>::SeqCst_CompareAndSwap(p, offset, expected, value)
605 #ifdef V8_DISABLE_WRITE_BARRIERS
606 #define WRITE_BARRIER(object, offset, value)
608 #define WRITE_BARRIER(object, offset, value) \
610 DCHECK_NOT_NULL(GetHeapFromWritableObject(object)); \
611 static_assert(kTaggedCanConvertToRawObjects); \
612 CombinedWriteBarrier(object, Tagged(object)->RawField(offset), value, \
613 UPDATE_WRITE_BARRIER); \
617 #ifdef V8_DISABLE_WRITE_BARRIERS
618 #define WEAK_WRITE_BARRIER(object, offset, value)
620 #define WEAK_WRITE_BARRIER(object, offset, value) \
622 DCHECK_NOT_NULL(GetHeapFromWritableObject(object)); \
623 static_assert(kTaggedCanConvertToRawObjects); \
624 CombinedWriteBarrier(object, Tagged(object)->RawMaybeWeakField(offset), \
625 value, UPDATE_WRITE_BARRIER); \
629 #ifdef V8_DISABLE_WRITE_BARRIERS
630 #define EPHEMERON_KEY_WRITE_BARRIER(object, offset, value)
631 #elif V8_ENABLE_UNCONDITIONAL_WRITE_BARRIERS
632 #define EPHEMERON_KEY_WRITE_BARRIER(object, offset, value) \
633 WRITE_BARRIER(object, offset, value)
635 #define EPHEMERON_KEY_WRITE_BARRIER(object, offset, value) \
637 DCHECK_NOT_NULL(GetHeapFromWritableObject(object)); \
638 CombinedEphemeronWriteBarrier(EphemeronHashTable::cast(object), \
639 (object)->RawField(offset), value, \
640 UPDATE_WRITE_BARRIER); \
644 #ifdef V8_DISABLE_WRITE_BARRIERS
645 #define INDIRECT_POINTER_WRITE_BARRIER(object, offset, tag, value)
647 #define INDIRECT_POINTER_WRITE_BARRIER(object, offset, tag, value) \
649 DCHECK_NOT_NULL(GetHeapFromWritableObject(object)); \
650 IndirectPointerWriteBarrier( \
651 object, Tagged(object)->RawIndirectPointerField(offset, tag), value, \
652 UPDATE_WRITE_BARRIER); \
656 #ifdef V8_DISABLE_WRITE_BARRIERS
657 #define CONDITIONAL_WRITE_BARRIER(object, offset, value, mode)
658 #elif V8_ENABLE_UNCONDITIONAL_WRITE_BARRIERS
659 #define CONDITIONAL_WRITE_BARRIER(object, offset, value, mode) \
660 WRITE_BARRIER(object, offset, value)
662 #define CONDITIONAL_WRITE_BARRIER(object, offset, value, mode) \
664 DCHECK_NOT_NULL(GetHeapFromWritableObject(object)); \
665 CombinedWriteBarrier(object, (object)->RawField(offset), value, mode); \
669 #ifdef V8_DISABLE_WRITE_BARRIERS
670 #define CONDITIONAL_WEAK_WRITE_BARRIER(object, offset, value, mode)
671 #elif V8_ENABLE_UNCONDITIONAL_WRITE_BARRIERS
672 #define CONDITIONAL_WEAK_WRITE_BARRIER(object, offset, value, mode) \
673 WRITE_BARRIER(object, offset, value)
675 #define CONDITIONAL_WEAK_WRITE_BARRIER(object, offset, value, mode) \
677 DCHECK_NOT_NULL(GetHeapFromWritableObject(object)); \
678 CombinedWriteBarrier(object, (object)->RawMaybeWeakField(offset), value, \
683 #ifdef V8_DISABLE_WRITE_BARRIERS
684 #define CONDITIONAL_EPHEMERON_KEY_WRITE_BARRIER(object, offset, value, mode)
686 #define CONDITIONAL_EPHEMERON_KEY_WRITE_BARRIER(object, offset, value, mode) \
688 DCHECK_NOT_NULL(GetHeapFromWritableObject(object)); \
689 CombinedEphemeronWriteBarrier(EphemeronHashTable::cast(object), \
690 (object)->RawField(offset), value, mode); \
694 #ifdef V8_DISABLE_WRITE_BARRIERS
695 #define CONDITIONAL_INDIRECT_POINTER_WRITE_BARRIER(object, offset, tag, value, \
698 #define CONDITIONAL_INDIRECT_POINTER_WRITE_BARRIER(object, offset, tag, value, \
701 DCHECK_NOT_NULL(GetHeapFromWritableObject(object)); \
702 IndirectPointerWriteBarrier( \
703 object, (object).RawIndirectPointerField(offset, tag), value, mode); \
707 #ifdef V8_ENABLE_SANDBOX
708 #define CONDITIONAL_TRUSTED_POINTER_WRITE_BARRIER(object, offset, tag, value, \
710 CONDITIONAL_INDIRECT_POINTER_WRITE_BARRIER(object, offset, tag, value, mode)
712 #define CONDITIONAL_TRUSTED_POINTER_WRITE_BARRIER(object, offset, tag, value, \
714 CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
716 #define CONDITIONAL_CODE_POINTER_WRITE_BARRIER(object, offset, value, mode) \
717 CONDITIONAL_TRUSTED_POINTER_WRITE_BARRIER( \
718 object, offset, kCodeIndirectPointerTag, value, mode)
720 #define ACQUIRE_READ_INT8_FIELD(p, offset) \
721 static_cast<int8_t>(base::Acquire_Load( \
722 reinterpret_cast<const base::Atomic8*>(FIELD_ADDR(p, offset))))
724 #define ACQUIRE_READ_INT32_FIELD(p, offset) \
725 static_cast<int32_t>(base::Acquire_Load( \
726 reinterpret_cast<const base::Atomic32*>(FIELD_ADDR(p, offset))))
728 #define RELAXED_WRITE_INT8_FIELD(p, offset, value) \
729 base::Relaxed_Store(reinterpret_cast<base::Atomic8*>(FIELD_ADDR(p, offset)), \
730 static_cast<base::Atomic8>(value));
731 #define RELAXED_READ_INT8_FIELD(p, offset) \
732 static_cast<int8_t>(base::Relaxed_Load( \
733 reinterpret_cast<const base::Atomic8*>(FIELD_ADDR(p, offset))))
735 #define RELAXED_READ_UINT16_FIELD(p, offset) \
736 static_cast<uint16_t>(base::Relaxed_Load( \
737 reinterpret_cast<const base::Atomic16*>(FIELD_ADDR(p, offset))))
739 #define RELAXED_WRITE_UINT16_FIELD(p, offset, value) \
740 base::Relaxed_Store( \
741 reinterpret_cast<base::Atomic16*>(FIELD_ADDR(p, offset)), \
742 static_cast<base::Atomic16>(value));
744 #define RELAXED_READ_INT16_FIELD(p, offset) \
745 static_cast<int16_t>(base::Relaxed_Load( \
746 reinterpret_cast<const base::Atomic16*>(FIELD_ADDR(p, offset))))
748 #define RELAXED_WRITE_INT16_FIELD(p, offset, value) \
749 base::Relaxed_Store( \
750 reinterpret_cast<base::Atomic16*>(FIELD_ADDR(p, offset)), \
751 static_cast<base::Atomic16>(value));
753 #define RELAXED_READ_UINT32_FIELD(p, offset) \
754 static_cast<uint32_t>(base::Relaxed_Load( \
755 reinterpret_cast<const base::Atomic32*>(FIELD_ADDR(p, offset))))
757 #define ACQUIRE_READ_UINT32_FIELD(p, offset) \
758 static_cast<uint32_t>(base::Acquire_Load( \
759 reinterpret_cast<const base::Atomic32*>(FIELD_ADDR(p, offset))))
761 #define RELAXED_WRITE_UINT32_FIELD(p, offset, value) \
762 base::Relaxed_Store( \
763 reinterpret_cast<base::Atomic32*>(FIELD_ADDR(p, offset)), \
764 static_cast<base::Atomic32>(value));
766 #define RELEASE_WRITE_INT8_FIELD(p, offset, value) \
767 base::Release_Store(reinterpret_cast<base::Atomic8*>(FIELD_ADDR(p, offset)), \
768 static_cast<base::Atomic8>(value));
770 #define RELEASE_WRITE_UINT32_FIELD(p, offset, value) \
771 base::Release_Store( \
772 reinterpret_cast<base::Atomic32*>(FIELD_ADDR(p, offset)), \
773 static_cast<base::Atomic32>(value));
775 #define RELAXED_READ_INT32_FIELD(p, offset) \
776 static_cast<int32_t>(base::Relaxed_Load( \
777 reinterpret_cast<const base::Atomic32*>(FIELD_ADDR(p, offset))))
779 #if defined(V8_HOST_ARCH_64_BIT)
780 #define RELAXED_READ_INT64_FIELD(p, offset) \
781 static_cast<int64_t>(base::Relaxed_Load( \
782 reinterpret_cast<const base::Atomic64*>(FIELD_ADDR(p, offset))))
785 #define RELEASE_WRITE_INT32_FIELD(p, offset, value) \
786 base::Release_Store( \
787 reinterpret_cast<base::Atomic32*>(FIELD_ADDR(p, offset)), \
788 static_cast<base::Atomic32>(value))
790 #define RELAXED_WRITE_INT32_FIELD(p, offset, value) \
791 base::Relaxed_Store( \
792 reinterpret_cast<base::Atomic32*>(FIELD_ADDR(p, offset)), \
793 static_cast<base::Atomic32>(value))
795 static_assert(sizeof(int) == sizeof(int32_t),
796 "sizeof int must match sizeof int32_t");
798 #define RELAXED_READ_INT_FIELD(p, offset) RELAXED_READ_INT32_FIELD(p, offset)
800 #define RELAXED_WRITE_INT_FIELD(p, offset, value) \
801 RELAXED_WRITE_INT32_FIELD(p, offset, value)
803 static_assert(sizeof(unsigned) == sizeof(uint32_t),
804 "sizeof unsigned must match sizeof uint32_t");
806 #define RELAXED_READ_UINT_FIELD(p, offset) RELAXED_READ_UINT32_FIELD(p, offset)
808 #define RELAXED_WRITE_UINT_FIELD(p, offset, value) \
809 RELAXED_WRITE_UINT32_FIELD(p, offset, value)
811 #define RELAXED_READ_BYTE_FIELD(p, offset) \
812 static_cast<uint8_t>(base::Relaxed_Load( \
813 reinterpret_cast<const base::Atomic8*>(FIELD_ADDR(p, offset))))
815 #define ACQUIRE_READ_BYTE_FIELD(p, offset) \
816 static_cast<uint8_t>(base::Acquire_Load( \
817 reinterpret_cast<const base::Atomic8*>(FIELD_ADDR(p, offset))))
819 #define RELAXED_WRITE_BYTE_FIELD(p, offset, value) \
820 base::Relaxed_Store(reinterpret_cast<base::Atomic8*>(FIELD_ADDR(p, offset)), \
821 static_cast<base::Atomic8>(value));
823 #define RELEASE_WRITE_BYTE_FIELD(p, offset, value) \
824 base::Release_Store(reinterpret_cast<base::Atomic8*>(FIELD_ADDR(p, offset)), \
825 static_cast<base::Atomic8>(value));
828 #define DECL_PRINTER(Name) void Name##Print(std::ostream& os);
830 #define DECL_PRINTER(Name)
834 #define DECL_VERIFIER(Name) void Name##Verify(Isolate* isolate);
835 #define EXPORT_DECL_VERIFIER(Name) \
836 V8_EXPORT_PRIVATE void Name##Verify(Isolate* isolate);
837 #define DECL_STATIC_VERIFIER(Name) \
838 static void Name##Verify(Tagged<Name> obj, Isolate* isolate);
839 #define EXPORT_DECL_STATIC_VERIFIER(Name) \
840 V8_EXPORT_PRIVATE static void Name##Verify(Tagged<Name> obj, \
843 #define DECL_VERIFIER(Name)
844 #define EXPORT_DECL_VERIFIER(Name)
845 #define DECL_STATIC_VERIFIER(Name)
846 #define EXPORT_DECL_STATIC_VERIFIER(Name)
849 #define DEFINE_DEOPT_ELEMENT_ACCESSORS(name, type) \
850 type DeoptimizationData::name() const { \
851 return type::cast(get(k##name##Index)); \
853 void DeoptimizationData::Set##name(type value) { set(k##name##Index, value); }
855 #define DEFINE_DEOPT_ENTRY_ACCESSORS(name, type) \
856 type DeoptimizationData::name(int i) const { \
857 return type::cast(get(IndexForEntry(i) + k##name##Offset)); \
859 void DeoptimizationData::Set##name(int i, type value) { \
860 set(IndexForEntry(i) + k##name##Offset, value); \
863 #define TQ_OBJECT_CONSTRUCTORS(Type) \
864 OBJECT_CONSTRUCTORS(Type, TorqueGenerated##Type<Type, Super>); \
865 friend class TorqueGenerated##Type<Type, Super>;
867 #define TQ_OBJECT_CONSTRUCTORS_IMPL(Type) \
868 inline Type::Type(Address ptr) \
869 : TorqueGenerated##Type<Type, Type::Super>(ptr) {}
871 #define TQ_CPP_OBJECT_DEFINITION_ASSERTS(_class, parent) \
872 template class TorqueGenerated##_class##Asserts<_class, parent>;