// Copyright 2018 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_MAYBE_OBJECT_INL_H_ #define V8_OBJECTS_MAYBE_OBJECT_INL_H_ #include "src/objects/maybe-object.h" #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" namespace v8 { namespace internal { bool MaybeObject::ToSmi(Smi* value) { if (HAS_SMI_TAG(ptr_)) { *value = Smi::cast(Object(ptr_)); return true; } return false; } Smi MaybeObject::ToSmi() const { DCHECK(HAS_SMI_TAG(ptr_)); return Smi::cast(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 = HasWeakHeapObjectTag(ptr_) ? HeapObjectReferenceType::WEAK : HeapObjectReferenceType::STRONG; *result = GetHeapObject(); return true; } bool MaybeObject::IsStrong() const { return !HasWeakHeapObjectTag(ptr_) && !IsSmi(); } bool MaybeObject::GetHeapObjectIfStrong(HeapObject* result) const { if (!HasWeakHeapObjectTag(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 HasWeakHeapObjectTag(ptr_) && !IsCleared(); } bool MaybeObject::IsWeakOrCleared() const { return HasWeakHeapObjectTag(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); } // static HeapObjectReference HeapObjectReference::ClearedValue(Isolate* isolate) { // Construct cleared weak ref value. Address raw_value = kClearedWeakHeapObjectLower32; #ifdef V8_COMPRESS_POINTERS // This is necessary to make pointer decompression computation also // suitable for cleared weak references. Address isolate_root = isolate->isolate_root(); raw_value |= isolate_root; DCHECK_EQ(raw_value & (~static_cast<Address>(kClearedWeakHeapObjectLower32)), isolate_root); #endif // The rest of the code will check only the lower 32-bits. DCHECK_EQ(kClearedWeakHeapObjectLower32, static_cast<uint32_t>(raw_value)); return HeapObjectReference(raw_value); } template <typename THeapObjectSlot> void HeapObjectReference::Update(THeapObjectSlot slot, HeapObject value) { static_assert(std::is_same<THeapObjectSlot, FullHeapObjectSlot>::value || std::is_same<THeapObjectSlot, HeapObjectSlot>::value, "Only FullHeapObjectSlot and HeapObjectSlot are expected here"); Address old_value = (*slot).ptr(); DCHECK(!HAS_SMI_TAG(old_value)); Address new_value = value->ptr(); DCHECK(Internals::HasHeapObjectTag(new_value)); #ifdef DEBUG bool weak_before = HasWeakHeapObjectTag(old_value); #endif slot.store( HeapObjectReference(new_value | (old_value & kWeakHeapObjectMask))); #ifdef DEBUG bool weak_after = HasWeakHeapObjectTag((*slot).ptr()); DCHECK_EQ(weak_before, weak_after); #endif } } // namespace internal } // namespace v8 #endif // V8_OBJECTS_MAYBE_OBJECT_INL_H_