#ifndef V8_OBJECTS_OBJECTS_BODY_DESCRIPTORS_H_
#define V8_OBJECTS_OBJECTS_BODY_DESCRIPTORS_H_
#include "src/objects/map.h"
#include "src/objects/objects.h"
namespace v8::internal {
class BodyDescriptorBase {
public:
template <typename ObjectVisitor>
static inline void IteratePointers(Tagged<HeapObject> obj, int start_offset,
int end_offset, ObjectVisitor* v);
template <typename ObjectVisitor>
static inline void IteratePointer(Tagged<HeapObject> obj, int offset,
ObjectVisitor* v);
template <typename ObjectVisitor>
static inline void IterateCustomWeakPointers(Tagged<HeapObject> obj,
int start_offset, int end_offset,
ObjectVisitor* v);
template <typename ObjectVisitor>
static inline void IterateCustomWeakPointer(Tagged<HeapObject> obj,
int offset, ObjectVisitor* v);
template <typename ObjectVisitor>
static inline void IterateEphemeron(Tagged<HeapObject> obj, int index,
int key_offset, int value_offset,
ObjectVisitor* v);
template <typename ObjectVisitor>
static inline void IterateMaybeWeakPointers(Tagged<HeapObject> obj,
int start_offset, int end_offset,
ObjectVisitor* v);
template <typename ObjectVisitor>
static inline void IterateMaybeWeakPointer(Tagged<HeapObject> obj, int offset,
ObjectVisitor* v);
template <typename ObjectVisitor>
static inline void IterateTrustedPointer(Tagged<HeapObject> obj, int offset,
ObjectVisitor* visitor,
IndirectPointerMode mode,
IndirectPointerTag tag);
template <typename ObjectVisitor>
static inline void IterateCodePointer(Tagged<HeapObject> obj, int offset,
ObjectVisitor* visitor,
IndirectPointerMode mode);
template <typename ObjectVisitor>
static inline void IterateSelfIndirectPointer(Tagged<HeapObject> obj,
IndirectPointerTag tag,
ObjectVisitor* v);
template <typename ObjectVisitor>
static inline void IterateProtectedPointer(Tagged<HeapObject> obj, int offset,
ObjectVisitor* v);
template <typename ObjectVisitor>
static inline void IterateJSDispatchEntry(Tagged<HeapObject> obj, int offset,
ObjectVisitor* v);
protected:
static inline bool IsValidEmbedderJSObjectSlotImpl(Tagged<Map> map,
Tagged<HeapObject> obj,
int offset);
template <typename ObjectVisitor>
static inline void IterateJSObjectBodyImpl(Tagged<Map> map,
Tagged<HeapObject> obj,
int start_offset, int end_offset,
ObjectVisitor* v);
template <typename ObjectVisitor>
static inline void IterateJSObjectBodyWithoutEmbedderFieldsImpl(
Tagged<Map> map, Tagged<HeapObject> obj, int start_offset, int end_offset,
ObjectVisitor* v);
};
class DataOnlyBodyDescriptor : public BodyDescriptorBase {
public:
template <typename ObjectVisitor>
static inline void IterateBody(Tagged<Map> map, Tagged<HeapObject> obj,
int object_size, ObjectVisitor* v) {}
private:
};
template <int start_offset, int end_offset>
class FixedRangeBodyDescriptor : public BodyDescriptorBase {
public:
static const int kStartOffset = start_offset;
static const int kEndOffset = end_offset;
template <typename ObjectVisitor>
static inline void IterateBody(Tagged<Map> map, Tagged<HeapObject> obj,
ObjectVisitor* v) {
IteratePointers(obj, start_offset, end_offset, v);
}
template <typename ObjectVisitor>
static inline void IterateBody(Tagged<Map> map, Tagged<HeapObject> obj,
int object_size, ObjectVisitor* v) {
IterateBody(map, obj, v);
}
};
template <int start_offset, int end_offset, int size>
class FixedBodyDescriptor
: public std::conditional_t<
start_offset == end_offset, DataOnlyBodyDescriptor,
FixedRangeBodyDescriptor<start_offset, end_offset>> {
public:
static constexpr int kSize = size;
static inline int SizeOf(Tagged<Map> map, Tagged<HeapObject> object) {
DCHECK_EQ(kSize, map->instance_size());
return kSize;
}
};
template <typename T>
using FixedBodyDescriptorFor =
FixedBodyDescriptor<T::kStartOfStrongFieldsOffset,
T::kEndOfStrongFieldsOffset, T::kSize>;
template <int start_offset>
class SuffixRangeBodyDescriptor : public BodyDescriptorBase {
public:
static const int kStartOffset = start_offset;
template <typename ObjectVisitor>
static inline void IterateBody(Tagged<Map> map, Tagged<HeapObject> obj,
int object_size, ObjectVisitor* v) {
IteratePointers(obj, start_offset, object_size, v);
}
};
template <int start_offset>
class FlexibleBodyDescriptor : public SuffixRangeBodyDescriptor<start_offset> {
public:
static inline int SizeOf(Tagged<Map> map, Tagged<HeapObject> object);
};
class StructBodyDescriptor
: public FlexibleBodyDescriptor<HeapObject::kHeaderSize> {};
template <int start_offset>
class SuffixRangeWeakBodyDescriptor : public BodyDescriptorBase {
public:
static const int kStartOffset = start_offset;
template <typename ObjectVisitor>
static inline void IterateBody(Tagged<Map> map, Tagged<HeapObject> obj,
int object_size, ObjectVisitor* v) {
IterateMaybeWeakPointers(obj, start_offset, object_size, v);
}
};
template <int start_offset, int end_offset, int size>
class FixedWeakBodyDescriptor : public BodyDescriptorBase {
public:
static constexpr int kSize = size;
template <typename ObjectVisitor>
static inline void IterateBody(Tagged<Map> map, Tagged<HeapObject> obj,
int object_size, ObjectVisitor* v) {
IterateMaybeWeakPointers(obj, start_offset, end_offset, v);
}
static inline int SizeOf(Tagged<Map> map, Tagged<HeapObject> object) {
DCHECK_EQ(kSize, map->instance_size());
return kSize;
}
};
template <int start_offset>
class FlexibleWeakBodyDescriptor
: public SuffixRangeWeakBodyDescriptor<start_offset> {
public:
static inline int SizeOf(Tagged<Map> map, Tagged<HeapObject> object);
};
template <class ParentBodyDescriptor, class ChildBodyDescriptor>
class SubclassBodyDescriptor : public BodyDescriptorBase {
public:
template <typename ObjectVisitor>
static inline void IterateBody(Tagged<Map> map, Tagged<HeapObject> obj,
ObjectVisitor* v) {
if constexpr (!std::is_same_v<DataOnlyBodyDescriptor,
ChildBodyDescriptor>) {
static_assert(ParentBodyDescriptor::kSize <=
ChildBodyDescriptor::kStartOffset);
}
ParentBodyDescriptor::IterateBody(map, obj, v);
ChildBodyDescriptor::IterateBody(map, obj, v);
}
template <typename ObjectVisitor>
static inline void IterateBody(Tagged<Map> map, Tagged<HeapObject> obj,
int object_size, ObjectVisitor* v) {
ParentBodyDescriptor::IterateBody(map, obj, object_size, v);
ChildBodyDescriptor::IterateBody(map, obj, object_size, v);
}
static inline int SizeOf(Tagged<Map> map, Tagged<HeapObject> object) {
return ChildBodyDescriptor::SizeOf(map, object);
}
};
template <typename T, IndirectPointerTag kTag>
class FixedExposedTrustedObjectBodyDescriptor
: public FixedBodyDescriptorFor<T> {
static_assert(std::is_base_of_v<ExposedTrustedObject, T>);
using Base = FixedBodyDescriptorFor<T>;
public:
template <typename ObjectVisitor>
static inline void IterateBody(Tagged<Map> map, Tagged<HeapObject> obj,
int object_size, ObjectVisitor* v) {
Base::IterateSelfIndirectPointer(obj, kTag, v);
Base::IterateBody(map, obj, object_size, v);
}
};
template <size_t kFieldOffset, IndirectPointerTag kTag>
struct WithStrongTrustedPointer {
template <typename Base>
class BodyDescriptor : public Base {
public:
template <typename ObjectVisitor>
static inline void IterateBody(Tagged<Map> map, Tagged<HeapObject> obj,
int object_size, ObjectVisitor* v) {
Base::IterateBody(map, obj, object_size, v);
Base::IterateTrustedPointer(obj, kFieldOffset, v,
IndirectPointerMode::kStrong, kTag);
}
};
};
template <size_t kFieldOffset>
using WithStrongCodePointer =
WithStrongTrustedPointer<kFieldOffset, kCodeIndirectPointerTag>;
template <size_t kFieldOffset, ExternalPointerTagRange kTagRange>
struct WithExternalPointer {
template <typename Base>
class BodyDescriptor : public Base {
public:
template <typename ObjectVisitor>
static inline void IterateBody(Tagged<Map> map, Tagged<HeapObject> obj,
int object_size, ObjectVisitor* v) {
Base::IterateBody(map, obj, object_size, v);
v->VisitExternalPointer(
obj, obj->RawExternalPointerField(kFieldOffset, kTagRange));
}
};
};
template <size_t kFieldOffset>
struct WithProtectedPointer {
template <typename Base>
class BodyDescriptor : public Base {
public:
template <typename ObjectVisitor>
static inline void IterateBody(Tagged<Map> map, Tagged<HeapObject> obj,
int object_size, ObjectVisitor* v) {
Base::IterateBody(map, obj, object_size, v);
Base::IterateProtectedPointer(obj, kFieldOffset, v);
}
};
};
template <typename Base, typename FirstMixin, typename... MoreMixins>
class StackedBodyDescriptor
: public StackedBodyDescriptor<
typename FirstMixin::template BodyDescriptor<Base>, MoreMixins...> {};
template <typename Base, typename FirstMixin>
class StackedBodyDescriptor<Base, FirstMixin>
: public FirstMixin::template BodyDescriptor<Base> {};
}
#endif