diff --git a/BUILD.gn b/BUILD.gn index bdb4a4f120..003b02d6e0 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -2577,6 +2577,9 @@ v8_source_set("v8_base_without_compiler") { "src/objects/string.h", "src/objects/struct-inl.h", "src/objects/struct.h", + "src/objects/tagged-impl-inl.h", + "src/objects/tagged-impl.cc", + "src/objects/tagged-impl.h", "src/objects/template-objects-inl.h", "src/objects/template-objects.cc", "src/objects/template-objects.h", diff --git a/src/globals.h b/src/globals.h index 85f5ea7a0f..044aa7652a 100644 --- a/src/globals.h +++ b/src/globals.h @@ -548,6 +548,11 @@ static const intptr_t kPageAlignmentMask = (intptr_t{1} << kPageSizeBits) - 1; // If looking only at the top 32 bits, the QNaN mask is bits 19 to 30. constexpr uint32_t kQuietNaNHighBitsMask = 0xfff << (51 - 32); +enum class HeapObjectReferenceType { + WEAK, + STRONG, +}; + // ----------------------------------------------------------------------------- // Forward declarations for frequently used classes @@ -600,6 +605,8 @@ class NewSpace; class NewLargeObjectSpace; class NumberDictionary; class Object; +template +class TaggedImpl; class CompressedObjectSlot; class CompressedMaybeObjectSlot; class CompressedMapWordSlot; @@ -619,6 +626,7 @@ class Smi; template class SplayTree; class String; +class StringStream; class Struct; class Symbol; class Variable; @@ -1453,11 +1461,6 @@ enum IsolateAddressId { kIsolateAddressCount }; -enum class HeapObjectReferenceType { - WEAK, - STRONG, -}; - enum class PoisoningMitigationLevel { kPoisonAll, kDontPoison, diff --git a/src/heap/heap-write-barrier-inl.h b/src/heap/heap-write-barrier-inl.h index afab3630a6..f2eb1c4a46 100644 --- a/src/heap/heap-write-barrier-inl.h +++ b/src/heap/heap-write-barrier-inl.h @@ -19,7 +19,7 @@ #include "src/objects/fixed-array.h" #include "src/objects/heap-object.h" #include "src/objects/maybe-object-inl.h" -#include "src/objects/slots.h" +#include "src/objects/slots-inl.h" namespace v8 { namespace internal { diff --git a/src/heap/heap-write-barrier.h b/src/heap/heap-write-barrier.h index 665151db1b..9b2bf859e0 100644 --- a/src/heap/heap-write-barrier.h +++ b/src/heap/heap-write-barrier.h @@ -14,9 +14,6 @@ namespace internal { class Code; class FixedArray; class Heap; -class HeapObject; -class MaybeObject; -class Object; class RelocInfo; class EphemeronHashTable; diff --git a/src/objects-printer.cc b/src/objects-printer.cc index d2282b1476..b3ac8e3e64 100644 --- a/src/objects-printer.cc +++ b/src/objects-printer.cc @@ -2396,13 +2396,15 @@ void InterpreterData::InterpreterDataPrint(std::ostream& os) { // NOLINT os << "\n"; } -void MaybeObject::Print() { +template +void TaggedImpl::Print() { StdoutStream os; this->Print(os); os << std::flush; } -void MaybeObject::Print(std::ostream& os) { +template +void TaggedImpl::Print(std::ostream& os) { Smi smi; HeapObject heap_object; if (ToSmi(&smi)) { diff --git a/src/objects.cc b/src/objects.cc index 7c3209daae..7a93f16cdc 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1804,22 +1804,6 @@ std::ostream& operator<<(std::ostream& os, const Object& obj) { return os; } -void MaybeObject::ShortPrint(FILE* out) { - OFStream os(out); - os << Brief(*this); -} - -void MaybeObject::ShortPrint(StringStream* accumulator) { - std::ostringstream os; - os << Brief(*this); - accumulator->Add(os.str().c_str()); -} - -void MaybeObject::ShortPrint(std::ostream& os) { os << Brief(*this); } - -Brief::Brief(const Object v) : value(v->ptr()) {} -Brief::Brief(const MaybeObject v) : value(v.ptr()) {} - std::ostream& operator<<(std::ostream& os, const Brief& v) { MaybeObject maybe_object(v.value); Smi smi; diff --git a/src/objects.h b/src/objects.h index 60f6557423..d1b6ea192b 100644 --- a/src/objects.h +++ b/src/objects.h @@ -24,6 +24,7 @@ #include "src/message-template.h" #include "src/objects-definitions.h" #include "src/objects/object-list-macros.h" +#include "src/objects/tagged-impl.h" #include "src/property-details.h" #include "src/utils.h" @@ -716,8 +717,8 @@ bool Object::IsHeapObject() const { } struct Brief { - V8_EXPORT_PRIVATE explicit Brief(const Object v); - explicit Brief(const MaybeObject v); + template + explicit Brief(TObject v) : value{v.ptr()} {} // {value} is a tagged heap object reference (weak or strong), equivalent to // a MaybeObject's payload. It has a plain Address type to keep #includes // lightweight. diff --git a/src/objects/code.h b/src/objects/code.h index 99d721af07..fa2580db17 100644 --- a/src/objects/code.h +++ b/src/objects/code.h @@ -22,7 +22,6 @@ class ByteArray; class BytecodeArray; class CodeDataContainer; class CodeDesc; -class MaybeObject; namespace interpreter { class Register; diff --git a/src/objects/descriptor-array-inl.h b/src/objects/descriptor-array-inl.h index 7b91ffd588..64d117e785 100644 --- a/src/objects/descriptor-array-inl.h +++ b/src/objects/descriptor-array-inl.h @@ -14,7 +14,7 @@ #include "src/lookup-cache-inl.h" #include "src/maybe-handles-inl.h" #include "src/objects/heap-object-inl.h" -#include "src/objects/maybe-object.h" +#include "src/objects/maybe-object-inl.h" #include "src/objects/struct-inl.h" #include "src/property.h" diff --git a/src/objects/heap-object-inl.h b/src/objects/heap-object-inl.h index be97f8bb79..e5c61a0eea 100644 --- a/src/objects/heap-object-inl.h +++ b/src/objects/heap-object-inl.h @@ -17,9 +17,6 @@ namespace v8 { namespace internal { -OBJECT_CONSTRUCTORS_IMPL(HeapObject, Object) -CAST_ACCESSOR(HeapObject) - HeapObject::HeapObject(Address ptr, AllowInlineSmiStorage allow_smi) : Object(ptr) { SLOW_DCHECK( @@ -27,12 +24,6 @@ HeapObject::HeapObject(Address ptr, AllowInlineSmiStorage allow_smi) IsHeapObject()); } -// static -HeapObject HeapObject::FromAddress(Address address) { - DCHECK_TAG_ALIGNED(address); - return HeapObject(address + kHeapObjectTag); -} - // static Heap* NeverReadOnlySpaceObject::GetHeap(const HeapObject object) { return GetHeapFromWritableObject(object); diff --git a/src/objects/heap-object.h b/src/objects/heap-object.h index f42dc05b81..c2177d7945 100644 --- a/src/objects/heap-object.h +++ b/src/objects/heap-object.h @@ -85,7 +85,10 @@ class HeapObject : public Object { #undef DECL_STRUCT_PREDICATE // Converts an address to a HeapObject pointer. - static inline HeapObject FromAddress(Address address); + static inline HeapObject FromAddress(Address address) { + DCHECK_TAG_ALIGNED(address); + return HeapObject(address + kHeapObjectTag); + } // Returns the address of this HeapObject. inline Address address() const { return ptr() - kHeapObjectTag; } @@ -197,6 +200,9 @@ class HeapObject : public Object { OBJECT_CONSTRUCTORS(HeapObject, Object); }; +OBJECT_CONSTRUCTORS_IMPL(HeapObject, Object) +CAST_ACCESSOR(HeapObject) + // Helper class for objects that can never be in RO space. class NeverReadOnlySpaceObject { public: diff --git a/src/objects/maybe-object-inl.h b/src/objects/maybe-object-inl.h index 842b5a4b30..9a93602471 100644 --- a/src/objects/maybe-object-inl.h +++ b/src/objects/maybe-object-inl.h @@ -10,107 +10,52 @@ #ifdef V8_COMPRESS_POINTERS #include "src/isolate.h" #endif -#include "src/objects/heap-object-inl.h" -#include "src/objects/slots-inl.h" #include "src/objects/smi-inl.h" +#include "src/objects/tagged-impl-inl.h" namespace v8 { namespace internal { -bool MaybeObject::ToSmi(Smi* value) { - if (HAS_SMI_TAG(ptr_)) { - *value = Smi::cast(Object(ptr_)); - return true; - } - return false; +// +// MaybeObject implementation. +// + +// static +MaybeObject MaybeObject::FromSmi(Smi smi) { + DCHECK(HAS_SMI_TAG(smi->ptr())); + return MaybeObject(smi->ptr()); } -Smi MaybeObject::ToSmi() const { - DCHECK(HAS_SMI_TAG(ptr_)); - return Smi::cast(Object(ptr_)); +// static +MaybeObject MaybeObject::FromObject(Object object) { + DCHECK(!HAS_WEAK_HEAP_OBJECT_TAG(object.ptr())); + return MaybeObject(object.ptr()); } -bool MaybeObject::IsStrongOrWeak() const { - if (IsSmi() || IsCleared()) { - return false; - } - return true; -} - -bool MaybeObject::GetHeapObject(HeapObject* result) const { - if (IsSmi() || IsCleared()) { - return false; - } - *result = GetHeapObject(); - return true; -} - -bool MaybeObject::GetHeapObject(HeapObject* result, - HeapObjectReferenceType* reference_type) const { - if (IsSmi() || IsCleared()) { - return false; - } - *reference_type = HAS_WEAK_HEAP_OBJECT_TAG(ptr_) - ? HeapObjectReferenceType::WEAK - : HeapObjectReferenceType::STRONG; - *result = GetHeapObject(); - return true; -} - -bool MaybeObject::IsStrong() const { return HAS_STRONG_HEAP_OBJECT_TAG(ptr_); } - -bool MaybeObject::GetHeapObjectIfStrong(HeapObject* result) const { - if (!HAS_WEAK_HEAP_OBJECT_TAG(ptr_) && !IsSmi()) { - *result = HeapObject::cast(Object(ptr_)); - return true; - } - return false; -} - -HeapObject MaybeObject::GetHeapObjectAssumeStrong() const { - DCHECK(IsStrong()); - return HeapObject::cast(Object(ptr_)); -} - -bool MaybeObject::IsWeak() const { - return HAS_WEAK_HEAP_OBJECT_TAG(ptr_) && !IsCleared(); -} - -bool MaybeObject::IsWeakOrCleared() const { - return HAS_WEAK_HEAP_OBJECT_TAG(ptr_); -} - -bool MaybeObject::GetHeapObjectIfWeak(HeapObject* result) const { - if (IsWeak()) { - *result = GetHeapObject(); - return true; - } - return false; -} - -HeapObject MaybeObject::GetHeapObjectAssumeWeak() const { - DCHECK(IsWeak()); - return GetHeapObject(); -} - -HeapObject MaybeObject::GetHeapObject() const { - DCHECK(!IsSmi()); - DCHECK(!IsCleared()); - return HeapObject::cast(Object(ptr_ & ~kWeakHeapObjectMask)); -} - -Object MaybeObject::GetHeapObjectOrSmi() const { - if (IsSmi()) { - return Object(ptr_); - } - return GetHeapObject(); -} - -bool MaybeObject::IsObject() const { return IsSmi() || IsStrong(); } - MaybeObject MaybeObject::MakeWeak(MaybeObject object) { DCHECK(object.IsStrongOrWeak()); - return MaybeObject(object.ptr_ | kWeakHeapObjectMask); + return MaybeObject(object.ptr() | kWeakHeapObjectMask); +} + +// +// HeapObjectReference implementation. +// + +HeapObjectReference::HeapObjectReference(Object object) + : MaybeObject(object->ptr()) {} + +// static +HeapObjectReference HeapObjectReference::Strong(Object object) { + DCHECK(!object->IsSmi()); + DCHECK(!HasWeakHeapObjectTag(object)); + return HeapObjectReference(object); +} + +// static +HeapObjectReference HeapObjectReference::Weak(Object object) { + DCHECK(!object->IsSmi()); + DCHECK(!HasWeakHeapObjectTag(object)); + return HeapObjectReference(object->ptr() | kWeakHeapObjectMask); } // static diff --git a/src/objects/maybe-object.h b/src/objects/maybe-object.h index b3a3870d9d..a1645c0604 100644 --- a/src/objects/maybe-object.h +++ b/src/objects/maybe-object.h @@ -5,121 +5,31 @@ #ifndef V8_OBJECTS_MAYBE_OBJECT_H_ #define V8_OBJECTS_MAYBE_OBJECT_H_ -#include "include/v8-internal.h" -#include "include/v8.h" -#include "src/globals.h" -#include "src/objects.h" -#include "src/objects/smi.h" +#include "src/objects/tagged-impl.h" namespace v8 { namespace internal { -class HeapObject; -class Isolate; -class StringStream; - // A MaybeObject is either a SMI, a strong reference to a HeapObject, a weak // reference to a HeapObject, or a cleared weak reference. It's used for // implementing in-place weak references (see design doc: goo.gl/j6SdcK ) -class MaybeObject { +class MaybeObject : public TaggedImpl { public: - MaybeObject() : ptr_(kNullAddress) {} - explicit MaybeObject(Address ptr) : ptr_(ptr) {} + constexpr MaybeObject() : TaggedImpl(kNullAddress) {} + constexpr explicit MaybeObject(Address ptr) : TaggedImpl(ptr) {} - bool operator==(const MaybeObject& other) const { return ptr_ == other.ptr_; } - bool operator!=(const MaybeObject& other) const { return ptr_ != other.ptr_; } + // These operator->() overloads are required for handlified code. + constexpr const MaybeObject* operator->() const { return this; } - Address ptr() const { return ptr_; } + V8_INLINE static MaybeObject FromSmi(Smi smi); - // Enable incremental transition of client code. - MaybeObject* operator->() { return this; } - const MaybeObject* operator->() const { return this; } + V8_INLINE static MaybeObject FromObject(Object object); - bool IsSmi() const { return HAS_SMI_TAG(ptr_); } - inline bool ToSmi(Smi* value); - inline Smi ToSmi() const; - - bool IsCleared() const { - return static_cast(ptr_) == kClearedWeakHeapObjectLower32; - } - - inline bool IsStrongOrWeak() const; - inline bool IsStrong() const; - - // If this MaybeObject is a strong pointer to a HeapObject, returns true and - // sets *result. Otherwise returns false. - inline bool GetHeapObjectIfStrong(HeapObject* result) const; - - // DCHECKs that this MaybeObject is a strong pointer to a HeapObject and - // returns the HeapObject. - inline HeapObject GetHeapObjectAssumeStrong() const; - - inline bool IsWeak() const; - inline bool IsWeakOrCleared() const; - - // If this MaybeObject is a weak pointer to a HeapObject, returns true and - // sets *result. Otherwise returns false. - inline bool GetHeapObjectIfWeak(HeapObject* result) const; - - // DCHECKs that this MaybeObject is a weak pointer to a HeapObject and - // returns the HeapObject. - inline HeapObject GetHeapObjectAssumeWeak() const; - - // If this MaybeObject is a strong or weak pointer to a HeapObject, returns - // true and sets *result. Otherwise returns false. - inline bool GetHeapObject(HeapObject* result) const; - inline bool GetHeapObject(HeapObject* result, - HeapObjectReferenceType* reference_type) const; - - // DCHECKs that this MaybeObject is a strong or a weak pointer to a HeapObject - // and returns the HeapObject. - inline HeapObject GetHeapObject() const; - - // DCHECKs that this MaybeObject is a strong or a weak pointer to a HeapObject - // or a SMI and returns the HeapObject or SMI. - inline Object GetHeapObjectOrSmi() const; - - inline bool IsObject() const; - template - T cast() const { - DCHECK(!HAS_WEAK_HEAP_OBJECT_TAG(ptr_)); - return T::cast(Object(ptr_)); - } - - static MaybeObject FromSmi(Smi smi) { - DCHECK(HAS_SMI_TAG(smi->ptr())); - return MaybeObject(smi->ptr()); - } - - static MaybeObject FromObject(Object object) { - DCHECK(!HasWeakHeapObjectTag(object)); - return MaybeObject(object.ptr()); - } - - static inline MaybeObject MakeWeak(MaybeObject object); + V8_INLINE static MaybeObject MakeWeak(MaybeObject object); #ifdef VERIFY_HEAP static void VerifyMaybeObjectPointer(Isolate* isolate, MaybeObject p); #endif - - // Prints this object without details. - void ShortPrint(FILE* out = stdout); - - // Prints this object without details to a message accumulator. - void ShortPrint(StringStream* accumulator); - - void ShortPrint(std::ostream& os); - -#ifdef OBJECT_PRINT - void Print(); - void Print(std::ostream& os); -#else - void Print() { ShortPrint(); } - void Print(std::ostream& os) { ShortPrint(os); } -#endif - - private: - Address ptr_; }; // A HeapObjectReference is either a strong reference to a HeapObject, a weak @@ -127,19 +37,11 @@ class MaybeObject { class HeapObjectReference : public MaybeObject { public: explicit HeapObjectReference(Address address) : MaybeObject(address) {} - explicit HeapObjectReference(Object object) : MaybeObject(object->ptr()) {} + V8_INLINE explicit HeapObjectReference(Object object); - static HeapObjectReference Strong(Object object) { - DCHECK(!object->IsSmi()); - DCHECK(!HasWeakHeapObjectTag(object)); - return HeapObjectReference(object); - } + V8_INLINE static HeapObjectReference Strong(Object object); - static HeapObjectReference Weak(Object object) { - DCHECK(!object->IsSmi()); - DCHECK(!HasWeakHeapObjectTag(object)); - return HeapObjectReference(object->ptr() | kWeakHeapObjectMask); - } + V8_INLINE static HeapObjectReference Weak(Object object); V8_INLINE static HeapObjectReference ClearedValue(Isolate* isolate); diff --git a/src/objects/slots-inl.h b/src/objects/slots-inl.h index e0a42fbd91..0f3b5e16b4 100644 --- a/src/objects/slots-inl.h +++ b/src/objects/slots-inl.h @@ -10,7 +10,7 @@ #include "src/base/atomic-utils.h" #include "src/memcopy.h" #include "src/objects.h" -#include "src/objects/heap-object-inl.h" +#include "src/objects/heap-object.h" #include "src/objects/maybe-object.h" #include "src/ptr-compr-inl.h" diff --git a/src/objects/smi-inl.h b/src/objects/smi-inl.h index 38d644fbea..b355a5b1bd 100644 --- a/src/objects/smi-inl.h +++ b/src/objects/smi-inl.h @@ -13,9 +13,7 @@ namespace v8 { namespace internal { -CAST_ACCESSOR(Smi) - -int Smi::ToInt(const Object object) { return Smi::cast(object)->value(); } +// TODO(ishell): remove this file } // namespace internal } // namespace v8 diff --git a/src/objects/smi.h b/src/objects/smi.h index 938fc5504d..293999de2d 100644 --- a/src/objects/smi.h +++ b/src/objects/smi.h @@ -41,7 +41,9 @@ class Smi : public Object { } // Convert a Smi object to an int. - static inline int ToInt(const Object object); + static inline int ToInt(const Object object) { + return Smi::cast(object).value(); + } // Convert a value to a Smi object. static inline constexpr Smi FromInt(int value) { @@ -107,6 +109,8 @@ class Smi : public Object { static constexpr int kMaxValue = kSmiMaxValue; }; +CAST_ACCESSOR(Smi) + } // namespace internal } // namespace v8 diff --git a/src/objects/tagged-impl-inl.h b/src/objects/tagged-impl-inl.h new file mode 100644 index 0000000000..46602797d5 --- /dev/null +++ b/src/objects/tagged-impl-inl.h @@ -0,0 +1,113 @@ +// Copyright 2019 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_OBJECTS_TAGGED_IMPL_INL_H_ +#define V8_OBJECTS_TAGGED_IMPL_INL_H_ + +#include "src/objects/tagged-impl.h" + +#ifdef V8_COMPRESS_POINTERS +#include "src/isolate.h" +#endif +#include "src/objects/heap-object.h" +#include "src/objects/smi.h" + +namespace v8 { +namespace internal { + +template +bool TaggedImpl::ToSmi(Smi* value) const { + if (HAS_SMI_TAG(ptr_)) { + *value = Smi::cast(Object(ptr_)); + return true; + } + return false; +} + +template +Smi TaggedImpl::ToSmi() const { + DCHECK(HAS_SMI_TAG(ptr_)); + return Smi::cast(Object(ptr_)); +} + +template +bool TaggedImpl::GetHeapObject( + HeapObject* result) const { + if (!IsStrongOrWeak()) return false; + *result = GetHeapObject(); + return true; +} + +template +bool TaggedImpl::GetHeapObject( + HeapObject* result, HeapObjectReferenceType* reference_type) const { + if (!IsStrongOrWeak()) return false; + *reference_type = IsWeakOrCleared() ? HeapObjectReferenceType::WEAK + : HeapObjectReferenceType::STRONG; + *result = GetHeapObject(); + return true; +} + +template +bool TaggedImpl::GetHeapObjectIfStrong( + HeapObject* result) const { + if (IsStrong()) { + *result = HeapObject::cast(Object(ptr_)); + return true; + } + return false; +} + +template +HeapObject TaggedImpl::GetHeapObjectAssumeStrong() + const { + DCHECK(IsStrong()); + return HeapObject::cast(Object(ptr_)); +} + +template +bool TaggedImpl::GetHeapObjectIfWeak( + HeapObject* result) const { + if (kCanBeWeak) { + if (IsWeak()) { + *result = GetHeapObject(); + return true; + } + return false; + } else { + DCHECK(!HAS_WEAK_HEAP_OBJECT_TAG(ptr_)); + return false; + } +} + +template +HeapObject TaggedImpl::GetHeapObjectAssumeWeak() const { + DCHECK(IsWeak()); + return GetHeapObject(); +} + +template +HeapObject TaggedImpl::GetHeapObject() const { + DCHECK(!IsSmi()); + if (kCanBeWeak) { + DCHECK(!IsCleared()); + return HeapObject::cast(Object(ptr_ & ~kWeakHeapObjectMask)); + } else { + DCHECK(!HAS_WEAK_HEAP_OBJECT_TAG(ptr_)); + return HeapObject::cast(Object(ptr_)); + } +} + +template +Object TaggedImpl::GetHeapObjectOrSmi() const { + if (IsSmi()) { + return Object(ptr_); + } + return GetHeapObject(); +} + +} // namespace internal +} // namespace v8 + +#endif // V8_OBJECTS_TAGGED_IMPL_INL_H_ diff --git a/src/objects/tagged-impl.cc b/src/objects/tagged-impl.cc new file mode 100644 index 0000000000..2356ecd6bc --- /dev/null +++ b/src/objects/tagged-impl.cc @@ -0,0 +1,39 @@ +// Copyright 2019 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/objects/tagged-impl.h" + +#include + +#include "src/objects.h" +#include "src/ostreams.h" +#include "src/string-stream.h" + +namespace v8 { +namespace internal { + +template +void TaggedImpl::ShortPrint(FILE* out) { + OFStream os(out); + os << Brief(*this); +} + +template +void TaggedImpl::ShortPrint(StringStream* accumulator) { + std::ostringstream os; + os << Brief(*this); + accumulator->Add(os.str().c_str()); +} + +template +void TaggedImpl::ShortPrint(std::ostream& os) { + os << Brief(*this); +} + +// Explicit instantiation declarations. +template class TaggedImpl; +template class TaggedImpl; + +} // namespace internal +} // namespace v8 diff --git a/src/objects/tagged-impl.h b/src/objects/tagged-impl.h new file mode 100644 index 0000000000..8e62cf5357 --- /dev/null +++ b/src/objects/tagged-impl.h @@ -0,0 +1,153 @@ +// Copyright 2019 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_OBJECTS_TAGGED_IMPL_H_ +#define V8_OBJECTS_TAGGED_IMPL_H_ + +#include "include/v8-internal.h" +#include "include/v8.h" +#include "src/globals.h" + +namespace v8 { +namespace internal { + +// An TaggedImpl is a base class for Object (which is either a Smi or a strong +// reference to a HeapObject) and MaybeObject (which is either a Smi, a strong +// reference to a HeapObject, a weak reference to a HeapObject, or a cleared +// weak reference. +// This class provides storage and one canonical implementation of various +// predicates that check Smi and heap object tags' values and also take into +// account whether the tagged value is expected to be weak reference to a +// HeapObject or cleared weak reference. +template +class TaggedImpl { + public: + static const bool kCanBeWeak = kRefType == HeapObjectReferenceType::WEAK; + + constexpr TaggedImpl() : ptr_{} {} + explicit constexpr TaggedImpl(StorageType ptr) : ptr_(ptr) {} + + // Make clang on Linux catch what MSVC complains about on Windows: + operator bool() const = delete; + + constexpr bool operator==(TaggedImpl other) const { + return ptr_ == other.ptr_; + } + constexpr bool operator!=(TaggedImpl other) const { + return ptr_ != other.ptr_; + } + + // For using in std::set and std::map. + constexpr bool operator<(TaggedImpl other) const { + return ptr_ < other.ptr(); + } + + constexpr StorageType ptr() const { return ptr_; } + + // Returns true if this tagged value is a strong pointer to a HeapObject or + // Smi. + constexpr inline bool IsObject() const { return !IsWeakOrCleared(); } + + // Returns true if this tagged value is a Smi. + constexpr bool IsSmi() const { return HAS_SMI_TAG(ptr_); } + inline bool ToSmi(Smi* value) const; + inline Smi ToSmi() const; + + // Returns true if this tagged value is a strong pointer to a HeapObject. + constexpr inline bool IsHeapObject() const { return IsStrong(); } + + // Returns true if this tagged value is a cleared weak reference. + constexpr inline bool IsCleared() const { + return kCanBeWeak && + (static_cast(ptr_) == kClearedWeakHeapObjectLower32); + } + + // Returns true if this tagged value is a strong or weak pointer to a + // HeapObject. + constexpr inline bool IsStrongOrWeak() const { + return !IsSmi() && !IsCleared(); + } + + // Returns true if this tagged value is a strong pointer to a HeapObject. + constexpr inline bool IsStrong() const { +#ifdef V8_CAN_HAVE_DCHECK_IN_CONSTEXPR + DCHECK_IMPLIES(!kCanBeWeak, !IsSmi() == HAS_STRONG_HEAP_OBJECT_TAG(ptr_)); +#endif + return kCanBeWeak ? HAS_STRONG_HEAP_OBJECT_TAG(ptr_) : !IsSmi(); + } + + // Returns true if this tagged value is a weak pointer to a HeapObject. + constexpr inline bool IsWeak() const { + return IsWeakOrCleared() && !IsCleared(); + } + + // Returns true if this tagged value is a weak pointer to a HeapObject or + // cleared weak reference. + constexpr inline bool IsWeakOrCleared() const { + return kCanBeWeak && HAS_WEAK_HEAP_OBJECT_TAG(ptr_); + } + + // If this tagged value is a strong pointer to a HeapObject, returns true and + // sets *result. Otherwise returns false. + inline bool GetHeapObjectIfStrong(HeapObject* result) const; + + // DCHECKs that this tagged value is a strong pointer to a HeapObject and + // returns the HeapObject. + inline HeapObject GetHeapObjectAssumeStrong() const; + + // If this tagged value is a weak pointer to a HeapObject, returns true and + // sets *result. Otherwise returns false. + inline bool GetHeapObjectIfWeak(HeapObject* result) const; + + // DCHECKs that this tagged value is a weak pointer to a HeapObject and + // returns the HeapObject. + inline HeapObject GetHeapObjectAssumeWeak() const; + + // If this tagged value is a strong or weak pointer to a HeapObject, returns + // true and sets *result. Otherwise returns false. + inline bool GetHeapObject(HeapObject* result) const; + inline bool GetHeapObject(HeapObject* result, + HeapObjectReferenceType* reference_type) const; + + // DCHECKs that this tagged value is a strong or a weak pointer to a + // HeapObject and returns the HeapObject. + inline HeapObject GetHeapObject() const; + + // DCHECKs that this tagged value is a strong or a weak pointer to a + // HeapObject or a Smi and returns the HeapObject or Smi. + inline Object GetHeapObjectOrSmi() const; + + template + T cast() const { + DCHECK(!HAS_WEAK_HEAP_OBJECT_TAG(ptr_)); + return T::cast(Object(ptr_)); + } + + // Prints this object without details. + void ShortPrint(FILE* out = stdout); + + // Prints this object without details to a message accumulator. + void ShortPrint(StringStream* accumulator); + + void ShortPrint(std::ostream& os); + +#ifdef OBJECT_PRINT + void Print(); + void Print(std::ostream& os); +#else + void Print() { ShortPrint(); } + void Print(std::ostream& os) { ShortPrint(os); } +#endif + + private: + friend class CompressedObjectSlot; + friend class FullObjectSlot; + + StorageType ptr_; +}; + +} // namespace internal +} // namespace v8 + +#endif // V8_OBJECTS_TAGGED_IMPL_H_ diff --git a/src/visitors.h b/src/visitors.h index 840fa29a7b..befb90130f 100644 --- a/src/visitors.h +++ b/src/visitors.h @@ -15,8 +15,6 @@ namespace v8 { namespace internal { class CodeDataContainer; -class MaybeObject; -class Object; #define ROOT_ID_LIST(V) \ V(kStringTable, "(Internalized strings)") \