From 4170e328e0e22256653493d18fd7f40522129278 Mon Sep 17 00:00:00 2001 From: Igor Sheludko Date: Thu, 9 May 2019 15:47:33 +0200 Subject: [PATCH] [ptr-compr][cleanup] Introduce TaggedImpl<> as a base for MaybeObject This is a first step towards unification of Object and MaybeObject definitions. Having an TaggedImpl template will simplify adding compressed variants of Object and MaybeObject which is required for avoiding unnecessary value decompression in tight value copying loops and write barrier implementations. Bug: v8:7703, v8:9183 Change-Id: I4c1931c22359533d50cf4a2c7f1339dd55c0c707 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1588460 Reviewed-by: Ulan Degenbaev Reviewed-by: Jakob Kummerow Commit-Queue: Igor Sheludko Cr-Commit-Position: refs/heads/master@{#61385} --- BUILD.gn | 3 + src/globals.h | 13 ++- src/heap/heap-write-barrier-inl.h | 2 +- src/heap/heap-write-barrier.h | 3 - src/objects-printer.cc | 6 +- src/objects.cc | 16 --- src/objects.h | 5 +- src/objects/code.h | 1 - src/objects/descriptor-array-inl.h | 2 +- src/objects/heap-object-inl.h | 9 -- src/objects/heap-object.h | 8 +- src/objects/maybe-object-inl.h | 125 +++++++---------------- src/objects/maybe-object.h | 122 +++-------------------- src/objects/slots-inl.h | 2 +- src/objects/smi-inl.h | 4 +- src/objects/smi.h | 6 +- src/objects/tagged-impl-inl.h | 113 +++++++++++++++++++++ src/objects/tagged-impl.cc | 39 ++++++++ src/objects/tagged-impl.h | 153 +++++++++++++++++++++++++++++ src/visitors.h | 2 - 20 files changed, 386 insertions(+), 248 deletions(-) create mode 100644 src/objects/tagged-impl-inl.h create mode 100644 src/objects/tagged-impl.cc create mode 100644 src/objects/tagged-impl.h 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)") \