#ifndef V8_OBJECTS_TAGGED_IMPL_H_
#define V8_OBJECTS_TAGGED_IMPL_H_
#include "include/v8-internal.h"
#include "src/base/export-template.h"
#include "src/base/macros.h"
#include "src/common/checks.h"
#include "src/common/globals.h"
#include "src/common/ptr-compr.h"
namespace v8 {
namespace internal {
#if defined(V8_EXTERNAL_CODE_SPACE) || defined(V8_ENABLE_SANDBOX)
bool V8_EXPORT_PRIVATE CheckObjectComparisonAllowed(Address a, Address b);
#endif
template <HeapObjectReferenceType kRefType, typename StorageType>
class TaggedImpl {
public:
static_assert(std::is_same_v<StorageType, Address> ||
std::is_same_v<StorageType, Tagged_t>,
"StorageType must be either Address or Tagged_t");
static const bool kIsFull = sizeof(StorageType) == kSystemPointerSize;
static const bool kCanBeWeak = kRefType == HeapObjectReferenceType::WEAK;
V8_INLINE constexpr TaggedImpl() : ptr_{} {}
V8_INLINE explicit constexpr TaggedImpl(StorageType ptr) : ptr_(ptr) {}
explicit operator bool() const = delete;
template <HeapObjectReferenceType kOtherRefType, typename U>
constexpr bool operator==(TaggedImpl<kOtherRefType, U> other) const {
static_assert(std::is_same_v<U, Address> || std::is_same_v<U, Tagged_t>,
"U must be either Address or Tagged_t");
#if defined(V8_EXTERNAL_CODE_SPACE) || defined(V8_ENABLE_SANDBOX)
if (std::is_same_v<StorageType, Address> && std::is_same_v<U, Address>) {
SLOW_DCHECK(CheckObjectComparisonAllowed(ptr_, other.ptr()));
}
#endif
return static_cast<Tagged_t>(ptr_) == static_cast<Tagged_t>(other.ptr());
}
template <HeapObjectReferenceType kOtherRefType, typename U>
constexpr bool operator!=(TaggedImpl<kOtherRefType, U> other) const {
static_assert(std::is_same_v<U, Address> || std::is_same_v<U, Tagged_t>,
"U must be either Address or Tagged_t");
#if defined(V8_EXTERNAL_CODE_SPACE) || defined(V8_ENABLE_SANDBOX)
if (std::is_same_v<StorageType, Address> && std::is_same_v<U, Address>) {
SLOW_DCHECK(CheckObjectComparisonAllowed(ptr_, other.ptr()));
}
#endif
return static_cast<Tagged_t>(ptr_) != static_cast<Tagged_t>(other.ptr());
}
template <HeapObjectReferenceType kOtherRefType>
constexpr bool SafeEquals(
TaggedImpl<kOtherRefType, StorageType> other) const {
static_assert(std::is_same_v<StorageType, Address>,
"Safe comparison is allowed only for full tagged values");
if (V8_EXTERNAL_CODE_SPACE_BOOL || V8_ENABLE_SANDBOX_BOOL) {
return ptr_ == other.ptr();
}
return this->operator==(other);
}
constexpr bool operator<(TaggedImpl other) const {
#if defined(V8_EXTERNAL_CODE_SPACE) || defined(V8_ENABLE_SANDBOX)
if (std::is_same_v<StorageType, Address>) {
SLOW_DCHECK(CheckObjectComparisonAllowed(ptr_, other.ptr()));
}
#endif
return static_cast<Tagged_t>(ptr_) < static_cast<Tagged_t>(other.ptr());
}
V8_INLINE constexpr StorageType ptr() const { return ptr_; }
constexpr inline bool IsObject() const { return !IsWeakOrCleared(); }
constexpr bool IsSmi() const { return HAS_SMI_TAG(ptr_); }
inline bool ToSmi(Tagged<Smi>* value) const;
inline Tagged<Smi> ToSmi() const;
constexpr inline bool IsHeapObject() const { return IsStrong(); }
constexpr inline bool IsCleared() const {
return kCanBeWeak &&
(static_cast<uint32_t>(ptr_) == kClearedWeakHeapObjectLower32);
}
constexpr inline bool IsStrongOrWeak() const {
return !IsSmi() && !IsCleared();
}
constexpr inline bool IsStrong() const {
DCHECK(kCanBeWeak || (!IsSmi() == HAS_STRONG_HEAP_OBJECT_TAG(ptr_)));
return kCanBeWeak ? HAS_STRONG_HEAP_OBJECT_TAG(ptr_) : !IsSmi();
}
constexpr inline bool IsStrongOrSmi() const {
return !kCanBeWeak || !HAS_WEAK_HEAP_OBJECT_TAG(ptr_);
}
constexpr inline bool IsWeak() const {
return IsWeakOrCleared() && !IsCleared();
}
constexpr inline bool IsWeakOrCleared() const {
return kCanBeWeak && HAS_WEAK_HEAP_OBJECT_TAG(ptr_);
}
#ifdef V8_COMPRESS_POINTERS
constexpr inline bool IsInMainCageBase();
constexpr inline bool IsInTrustedCageBase();
#endif
inline bool GetHeapObjectIfStrong(Tagged<HeapObject>* result) const;
inline bool GetHeapObjectIfStrong(Isolate* isolate,
Tagged<HeapObject>* result) const;
inline Tagged<HeapObject> GetHeapObjectAssumeStrong() const;
inline Tagged<HeapObject> GetHeapObjectAssumeStrong(Isolate* isolate) const;
inline bool GetHeapObjectIfWeak(Tagged<HeapObject>* result) const;
inline bool GetHeapObjectIfWeak(Isolate* isolate,
Tagged<HeapObject>* result) const;
inline Tagged<HeapObject> GetHeapObjectAssumeWeak() const;
inline Tagged<HeapObject> GetHeapObjectAssumeWeak(Isolate* isolate) const;
inline bool GetHeapObject(Tagged<HeapObject>* result) const;
inline bool GetHeapObject(Isolate* isolate, Tagged<HeapObject>* result) const;
inline bool GetHeapObject(Tagged<HeapObject>* result,
HeapObjectReferenceType* reference_type) const;
inline bool GetHeapObject(Isolate* isolate, Tagged<HeapObject>* result,
HeapObjectReferenceType* reference_type) const;
inline Tagged<HeapObject> GetHeapObject() const;
inline Tagged<HeapObject> GetHeapObject(Isolate* isolate) const;
inline Tagged<Object> GetHeapObjectOrSmi() const;
inline Tagged<Object> GetHeapObjectOrSmi(Isolate* isolate) const;
template <typename T>
Tagged<T> cast() const {
CHECK(kIsFull);
DCHECK(!HAS_WEAK_HEAP_OBJECT_TAG(ptr_));
return Cast<T>(Tagged<Object>(ptr_));
}
protected:
StorageType* ptr_location() { return &ptr_; }
const StorageType* ptr_location() const { return &ptr_; }
private:
friend class CompressedObjectSlot;
friend class CompressedMaybeObjectSlot;
friend class FullObjectSlot;
friend class FullMaybeObjectSlot;
friend class FullHeapObjectSlot;
StorageType ptr_;
};
template <HeapObjectReferenceType kRefType, typename StorageType>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
void ShortPrint(TaggedImpl<kRefType, StorageType> ptr, FILE* out = stdout);
template <HeapObjectReferenceType kRefType, typename StorageType>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
void ShortPrint(TaggedImpl<kRefType, StorageType> ptr,
StringStream* accumulator);
template <HeapObjectReferenceType kRefType, typename StorageType>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
void ShortPrint(TaggedImpl<kRefType, StorageType> ptr, std::ostream& os);
#ifdef OBJECT_PRINT
template <HeapObjectReferenceType kRefType, typename StorageType>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
void Print(TaggedImpl<kRefType, StorageType> ptr);
template <HeapObjectReferenceType kRefType, typename StorageType>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
void Print(TaggedImpl<kRefType, StorageType> ptr, std::ostream& os);
#else
template <HeapObjectReferenceType kRefType, typename StorageType>
void Print(TaggedImpl<kRefType, StorageType> ptr) {
ShortPrint(ptr);
}
template <HeapObjectReferenceType kRefType, typename StorageType>
void Print(TaggedImpl<kRefType, StorageType> ptr, std::ostream& os) {
ShortPrint(ptr, os);
}
#endif
}
}
#endif