[ptr-compr] Introduce StrongTaggedValue and TaggedValue
... which represent potentially compressed Object and MaybeObject values respectively. They provide methods for checking the smi/weak tags which don't require decompression and conversion to Smi/HeapObject combined with tag checks. The new classes should help to write a bit more efficient runtime (C++) code for the cases when we don't need the full decompressed value immediately. Drive-by-fix: fix ptr-compr build after Object::operator->() removal. Bug: v8:7703 Change-Id: I7a3d747ab6679120a2cca14e45b0d8bcf33fc496 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1624786 Reviewed-by: Toon Verwaest <verwaest@chromium.org> Commit-Queue: Igor Sheludko <ishell@chromium.org> Cr-Commit-Position: refs/heads/master@{#61804}
This commit is contained in:
parent
a3a18a736e
commit
ae348e30ed
2
BUILD.gn
2
BUILD.gn
@ -2628,6 +2628,8 @@ v8_source_set("v8_base_without_compiler") {
|
||||
"src/objects/tagged-impl-inl.h",
|
||||
"src/objects/tagged-impl.cc",
|
||||
"src/objects/tagged-impl.h",
|
||||
"src/objects/tagged-value-inl.h",
|
||||
"src/objects/tagged-value.h",
|
||||
"src/objects/template-objects-inl.h",
|
||||
"src/objects/template-objects.cc",
|
||||
"src/objects/template-objects.h",
|
||||
|
@ -977,9 +977,7 @@ void StandardFrame::IterateCompiledFrame(RootVisitor* v) const {
|
||||
parameters_limit);
|
||||
}
|
||||
|
||||
#ifdef V8_COMPRESS_POINTERS
|
||||
Address isolate_root = isolate()->isolate_root();
|
||||
#endif
|
||||
DEFINE_ROOT_VALUE(isolate());
|
||||
// Visit pointer spill slots and locals.
|
||||
for (unsigned index = 0; index < stack_slots; index++) {
|
||||
int byte_index = index >> kBitsPerByteLog2;
|
||||
@ -998,8 +996,7 @@ void StandardFrame::IterateCompiledFrame(RootVisitor* v) const {
|
||||
if (!HAS_SMI_TAG(compressed_value)) {
|
||||
// We don't need to update smi values.
|
||||
*spill_slot.location() =
|
||||
DecompressTaggedPointer<OnHeapAddressKind::kIsolateRoot>(
|
||||
isolate_root, compressed_value);
|
||||
DecompressTaggedPointer(ROOT_VALUE, compressed_value);
|
||||
}
|
||||
#endif
|
||||
v->VisitRootPointer(Root::kTop, nullptr, spill_slot);
|
||||
|
@ -212,6 +212,15 @@ constexpr size_t kReservedCodeRangePages = 0;
|
||||
|
||||
STATIC_ASSERT(kSystemPointerSize == (1 << kSystemPointerSizeLog2));
|
||||
|
||||
// This macro is used for declaring and defining HeapObject getter methods that
|
||||
// are a bit more efficient for the pointer compression case than the default
|
||||
// parameterless getters because isolate root doesn't have to be computed from
|
||||
// arbitrary field address but it comes "for free" instead.
|
||||
// These alternatives are always defined (in order to avoid #ifdef mess but
|
||||
// are not supposed to be used when pointer compression is not enabled.
|
||||
#define ROOT_VALUE isolate_for_root
|
||||
#define ROOT_PARAM Isolate* const ROOT_VALUE
|
||||
|
||||
#ifdef V8_COMPRESS_POINTERS
|
||||
static_assert(
|
||||
kSystemPointerSize == kInt64Size,
|
||||
@ -225,6 +234,11 @@ constexpr int kTaggedSizeLog2 = 2;
|
||||
using Tagged_t = int32_t;
|
||||
using AtomicTagged_t = base::Atomic32;
|
||||
|
||||
#define DEFINE_ROOT_VALUE(isolate) ROOT_PARAM = isolate
|
||||
#define WITH_ROOT_PARAM(...) ROOT_PARAM, ##__VA_ARGS__
|
||||
#define WITH_ROOT_VALUE(...) ROOT_VALUE, ##__VA_ARGS__
|
||||
#define WITH_ROOT(isolate_for_root, ...) isolate_for_root, ##__VA_ARGS__
|
||||
|
||||
#else
|
||||
|
||||
constexpr int kTaggedSize = kSystemPointerSize;
|
||||
@ -235,6 +249,11 @@ constexpr int kTaggedSizeLog2 = kSystemPointerSizeLog2;
|
||||
using Tagged_t = Address;
|
||||
using AtomicTagged_t = base::AtomicWord;
|
||||
|
||||
#define DEFINE_ROOT_VALUE(isolate)
|
||||
#define WITH_ROOT_PARAM(...) __VA_ARGS__
|
||||
#define WITH_ROOT_VALUE(...) __VA_ARGS__
|
||||
#define WITH_ROOT(isolate_for_root, ...) __VA_ARGS__
|
||||
|
||||
#endif // V8_COMPRESS_POINTERS
|
||||
|
||||
// Defines whether the branchless or branchful implementation of pointer
|
||||
@ -614,6 +633,8 @@ class NumberDictionary;
|
||||
class Object;
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
class TaggedImpl;
|
||||
class StrongTaggedValue;
|
||||
class TaggedValue;
|
||||
class CompressedObjectSlot;
|
||||
class CompressedMaybeObjectSlot;
|
||||
class CompressedMapWordSlot;
|
||||
|
@ -41,7 +41,7 @@ bool BodyDescriptorBase::IsValidJSObjectSlotImpl(Map map, HeapObject obj,
|
||||
#ifdef V8_COMPRESS_POINTERS
|
||||
STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize);
|
||||
int embedder_fields_offset = JSObject::GetEmbedderFieldsStartOffset(map);
|
||||
int inobject_fields_offset = map->GetInObjectPropertyOffset(0);
|
||||
int inobject_fields_offset = map.GetInObjectPropertyOffset(0);
|
||||
// |embedder_fields_offset| may be greater than |inobject_fields_offset| if
|
||||
// the object does not have embedder fields but the check handles this
|
||||
// case properly.
|
||||
@ -77,7 +77,7 @@ void BodyDescriptorBase::IterateJSObjectBodyImpl(Map map, HeapObject obj,
|
||||
#ifdef V8_COMPRESS_POINTERS
|
||||
STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize);
|
||||
int header_size = JSObject::GetHeaderSize(map);
|
||||
int inobject_fields_offset = map->GetInObjectPropertyOffset(0);
|
||||
int inobject_fields_offset = map.GetInObjectPropertyOffset(0);
|
||||
// We are always requested to process header and embedder fields.
|
||||
DCHECK_LE(inobject_fields_offset, end_offset);
|
||||
// Embedder fields are located between header and inobject properties.
|
||||
|
@ -28,7 +28,7 @@ Object CompressedObjectSlot::operator*() const {
|
||||
}
|
||||
|
||||
void CompressedObjectSlot::store(Object value) const {
|
||||
*location() = CompressTagged(value->ptr());
|
||||
*location() = CompressTagged(value.ptr());
|
||||
}
|
||||
|
||||
Object CompressedObjectSlot::Acquire_Load() const {
|
||||
@ -42,19 +42,19 @@ Object CompressedObjectSlot::Relaxed_Load() const {
|
||||
}
|
||||
|
||||
void CompressedObjectSlot::Relaxed_Store(Object value) const {
|
||||
Tagged_t ptr = CompressTagged(value->ptr());
|
||||
Tagged_t ptr = CompressTagged(value.ptr());
|
||||
AsAtomicTagged::Relaxed_Store(location(), ptr);
|
||||
}
|
||||
|
||||
void CompressedObjectSlot::Release_Store(Object value) const {
|
||||
Tagged_t ptr = CompressTagged(value->ptr());
|
||||
Tagged_t ptr = CompressTagged(value.ptr());
|
||||
AsAtomicTagged::Release_Store(location(), ptr);
|
||||
}
|
||||
|
||||
Object CompressedObjectSlot::Release_CompareAndSwap(Object old,
|
||||
Object target) const {
|
||||
Tagged_t old_ptr = CompressTagged(old->ptr());
|
||||
Tagged_t target_ptr = CompressTagged(target->ptr());
|
||||
Tagged_t old_ptr = CompressTagged(old.ptr());
|
||||
Tagged_t target_ptr = CompressTagged(target.ptr());
|
||||
Tagged_t result =
|
||||
AsAtomicTagged::Release_CompareAndSwap(location(), old_ptr, target_ptr);
|
||||
return Object(DecompressTaggedAny(address(), result));
|
||||
@ -95,14 +95,14 @@ Object CompressedMapWordSlot::Acquire_Load() const {
|
||||
}
|
||||
|
||||
void CompressedMapWordSlot::Release_Store(Object value) const {
|
||||
Tagged_t ptr = CompressTagged(value->ptr());
|
||||
Tagged_t ptr = CompressTagged(value.ptr());
|
||||
AsAtomicTagged::Release_Store(location(), ptr);
|
||||
}
|
||||
|
||||
Object CompressedMapWordSlot::Release_CompareAndSwap(Object old,
|
||||
Object target) const {
|
||||
Tagged_t old_ptr = CompressTagged(old->ptr());
|
||||
Tagged_t target_ptr = CompressTagged(target->ptr());
|
||||
Tagged_t old_ptr = CompressTagged(old.ptr());
|
||||
Tagged_t target_ptr = CompressTagged(target.ptr());
|
||||
Tagged_t result =
|
||||
AsAtomicTagged::Release_CompareAndSwap(location(), old_ptr, target_ptr);
|
||||
return Object(DecompressTaggedPointer(address(), result));
|
||||
@ -118,7 +118,7 @@ MaybeObject CompressedMaybeObjectSlot::operator*() const {
|
||||
}
|
||||
|
||||
void CompressedMaybeObjectSlot::store(MaybeObject value) const {
|
||||
*location() = CompressTagged(value->ptr());
|
||||
*location() = CompressTagged(value.ptr());
|
||||
}
|
||||
|
||||
MaybeObject CompressedMaybeObjectSlot::Relaxed_Load() const {
|
||||
@ -127,14 +127,14 @@ MaybeObject CompressedMaybeObjectSlot::Relaxed_Load() const {
|
||||
}
|
||||
|
||||
void CompressedMaybeObjectSlot::Relaxed_Store(MaybeObject value) const {
|
||||
Tagged_t ptr = CompressTagged(value->ptr());
|
||||
Tagged_t ptr = CompressTagged(value.ptr());
|
||||
AsAtomicTagged::Relaxed_Store(location(), ptr);
|
||||
}
|
||||
|
||||
void CompressedMaybeObjectSlot::Release_CompareAndSwap(
|
||||
MaybeObject old, MaybeObject target) const {
|
||||
Tagged_t old_ptr = CompressTagged(old->ptr());
|
||||
Tagged_t target_ptr = CompressTagged(target->ptr());
|
||||
Tagged_t old_ptr = CompressTagged(old.ptr());
|
||||
Tagged_t target_ptr = CompressTagged(target.ptr());
|
||||
AsAtomicTagged::Release_CompareAndSwap(location(), old_ptr, target_ptr);
|
||||
}
|
||||
|
||||
@ -158,7 +158,7 @@ HeapObject CompressedHeapObjectSlot::ToHeapObject() const {
|
||||
}
|
||||
|
||||
void CompressedHeapObjectSlot::StoreHeapObject(HeapObject value) const {
|
||||
*location() = CompressTagged(value->ptr());
|
||||
*location() = CompressTagged(value.ptr());
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -476,8 +476,9 @@ static void SortIndices(Isolate* isolate, Handle<FixedArray> indices,
|
||||
AtomicSlot end(start + sort_size);
|
||||
std::sort(start, end, [isolate](Tagged_t elementA, Tagged_t elementB) {
|
||||
#ifdef V8_COMPRESS_POINTERS
|
||||
Object a(DecompressTaggedAny(isolate->isolate_root(), elementA));
|
||||
Object b(DecompressTaggedAny(isolate->isolate_root(), elementB));
|
||||
DEFINE_ROOT_VALUE(isolate);
|
||||
Object a(DecompressTaggedAny(ROOT_VALUE, elementA));
|
||||
Object b(DecompressTaggedAny(ROOT_VALUE, elementB));
|
||||
#else
|
||||
Object a(elementA);
|
||||
Object b(elementB);
|
||||
|
@ -12,6 +12,8 @@
|
||||
#endif
|
||||
#include "src/objects/heap-object.h"
|
||||
#include "src/objects/smi.h"
|
||||
#include "src/ptr-compr-inl.h"
|
||||
#include "src/roots-inl.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -19,7 +21,7 @@ namespace internal {
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
bool TaggedImpl<kRefType, StorageType>::ToSmi(Smi* value) const {
|
||||
if (HAS_SMI_TAG(ptr_)) {
|
||||
*value = Smi::cast(Object(ptr_));
|
||||
*value = ToSmi();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -28,20 +30,46 @@ bool TaggedImpl<kRefType, StorageType>::ToSmi(Smi* value) const {
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
Smi TaggedImpl<kRefType, StorageType>::ToSmi() const {
|
||||
DCHECK(HAS_SMI_TAG(ptr_));
|
||||
return Smi::cast(Object(ptr_));
|
||||
if (kIsFull) {
|
||||
return Smi(ptr_);
|
||||
}
|
||||
// Implementation for compressed pointers.
|
||||
return Smi(DecompressTaggedSigned(static_cast<Tagged_t>(ptr_)));
|
||||
}
|
||||
|
||||
//
|
||||
// TaggedImpl::GetHeapObject(HeapObject* result) implementation.
|
||||
//
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
bool TaggedImpl<kRefType, StorageType>::GetHeapObject(
|
||||
HeapObject* result) const {
|
||||
CHECK(kIsFull);
|
||||
if (!IsStrongOrWeak()) return false;
|
||||
*result = GetHeapObject();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
bool TaggedImpl<kRefType, StorageType>::GetHeapObject(
|
||||
ROOT_PARAM, HeapObject* result) const {
|
||||
if (kIsFull) return GetHeapObject(result);
|
||||
// Implementation for compressed pointers.
|
||||
if (!IsStrongOrWeak()) return false;
|
||||
*result = GetHeapObject(ROOT_VALUE);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// TaggedImpl::GetHeapObject(HeapObject* result,
|
||||
// HeapObjectReferenceType* reference_type)
|
||||
// implementation.
|
||||
//
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
bool TaggedImpl<kRefType, StorageType>::GetHeapObject(
|
||||
HeapObject* result, HeapObjectReferenceType* reference_type) const {
|
||||
CHECK(kIsFull);
|
||||
if (!IsStrongOrWeak()) return false;
|
||||
*reference_type = IsWeakOrCleared() ? HeapObjectReferenceType::WEAK
|
||||
: HeapObjectReferenceType::STRONG;
|
||||
@ -49,9 +77,27 @@ bool TaggedImpl<kRefType, StorageType>::GetHeapObject(
|
||||
return true;
|
||||
}
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
bool TaggedImpl<kRefType, StorageType>::GetHeapObject(
|
||||
ROOT_PARAM, HeapObject* result,
|
||||
HeapObjectReferenceType* reference_type) const {
|
||||
if (kIsFull) return GetHeapObject(result, reference_type);
|
||||
// Implementation for compressed pointers.
|
||||
if (!IsStrongOrWeak()) return false;
|
||||
*reference_type = IsWeakOrCleared() ? HeapObjectReferenceType::WEAK
|
||||
: HeapObjectReferenceType::STRONG;
|
||||
*result = GetHeapObject(ROOT_VALUE);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// TaggedImpl::GetHeapObjectIfStrong(HeapObject* result) implementation.
|
||||
//
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
bool TaggedImpl<kRefType, StorageType>::GetHeapObjectIfStrong(
|
||||
HeapObject* result) const {
|
||||
CHECK(kIsFull);
|
||||
if (IsStrong()) {
|
||||
*result = HeapObject::cast(Object(ptr_));
|
||||
return true;
|
||||
@ -59,16 +105,48 @@ bool TaggedImpl<kRefType, StorageType>::GetHeapObjectIfStrong(
|
||||
return false;
|
||||
}
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
bool TaggedImpl<kRefType, StorageType>::GetHeapObjectIfStrong(
|
||||
ROOT_PARAM, HeapObject* result) const {
|
||||
if (kIsFull) return GetHeapObjectIfStrong(result);
|
||||
// Implementation for compressed pointers.
|
||||
if (IsStrong()) {
|
||||
*result =
|
||||
HeapObject::cast(Object(DecompressTaggedPointer(ROOT_VALUE, ptr_)));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// TaggedImpl::GetHeapObjectAssumeStrong() implementation.
|
||||
//
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
HeapObject TaggedImpl<kRefType, StorageType>::GetHeapObjectAssumeStrong()
|
||||
const {
|
||||
CHECK(kIsFull);
|
||||
DCHECK(IsStrong());
|
||||
return HeapObject::cast(Object(ptr_));
|
||||
}
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
HeapObject TaggedImpl<kRefType, StorageType>::GetHeapObjectAssumeStrong(
|
||||
ROOT_PARAM) const {
|
||||
if (kIsFull) return GetHeapObjectAssumeStrong();
|
||||
// Implementation for compressed pointers.
|
||||
DCHECK(IsStrong());
|
||||
return HeapObject::cast(Object(DecompressTaggedPointer(ROOT_VALUE, ptr_)));
|
||||
}
|
||||
|
||||
//
|
||||
// TaggedImpl::GetHeapObjectIfWeak(HeapObject* result) implementation
|
||||
//
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
bool TaggedImpl<kRefType, StorageType>::GetHeapObjectIfWeak(
|
||||
HeapObject* result) const {
|
||||
CHECK(kIsFull);
|
||||
if (kCanBeWeak) {
|
||||
if (IsWeak()) {
|
||||
*result = GetHeapObject();
|
||||
@ -81,14 +159,50 @@ bool TaggedImpl<kRefType, StorageType>::GetHeapObjectIfWeak(
|
||||
}
|
||||
}
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
bool TaggedImpl<kRefType, StorageType>::GetHeapObjectIfWeak(
|
||||
ROOT_PARAM, HeapObject* result) const {
|
||||
if (kIsFull) return GetHeapObjectIfWeak(result);
|
||||
// Implementation for compressed pointers.
|
||||
if (kCanBeWeak) {
|
||||
if (IsWeak()) {
|
||||
*result = GetHeapObject(ROOT_VALUE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
DCHECK(!HAS_WEAK_HEAP_OBJECT_TAG(ptr_));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TaggedImpl::GetHeapObjectAssumeWeak() implementation.
|
||||
//
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
HeapObject TaggedImpl<kRefType, StorageType>::GetHeapObjectAssumeWeak() const {
|
||||
CHECK(kIsFull);
|
||||
DCHECK(IsWeak());
|
||||
return GetHeapObject();
|
||||
}
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
HeapObject TaggedImpl<kRefType, StorageType>::GetHeapObjectAssumeWeak(
|
||||
ROOT_PARAM) const {
|
||||
if (kIsFull) return GetHeapObjectAssumeWeak();
|
||||
// Implementation for compressed pointers.
|
||||
DCHECK(IsWeak());
|
||||
return GetHeapObject(ROOT_VALUE);
|
||||
}
|
||||
|
||||
//
|
||||
// TaggedImpl::GetHeapObject() implementation.
|
||||
//
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
HeapObject TaggedImpl<kRefType, StorageType>::GetHeapObject() const {
|
||||
CHECK(kIsFull);
|
||||
DCHECK(!IsSmi());
|
||||
if (kCanBeWeak) {
|
||||
DCHECK(!IsCleared());
|
||||
@ -99,14 +213,44 @@ HeapObject TaggedImpl<kRefType, StorageType>::GetHeapObject() const {
|
||||
}
|
||||
}
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
HeapObject TaggedImpl<kRefType, StorageType>::GetHeapObject(ROOT_PARAM) const {
|
||||
if (kIsFull) return GetHeapObject();
|
||||
// Implementation for compressed pointers.
|
||||
DCHECK(!IsSmi());
|
||||
if (kCanBeWeak) {
|
||||
DCHECK(!IsCleared());
|
||||
return HeapObject::cast(Object(
|
||||
DecompressTaggedPointer(ROOT_VALUE, ptr_ & ~kWeakHeapObjectMask)));
|
||||
} else {
|
||||
DCHECK(!HAS_WEAK_HEAP_OBJECT_TAG(ptr_));
|
||||
return HeapObject::cast(Object(DecompressTaggedPointer(ROOT_VALUE, ptr_)));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TaggedImpl::GetHeapObjectOrSmi() implementation.
|
||||
//
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
Object TaggedImpl<kRefType, StorageType>::GetHeapObjectOrSmi() const {
|
||||
CHECK(kIsFull);
|
||||
if (IsSmi()) {
|
||||
return Object(ptr_);
|
||||
}
|
||||
return GetHeapObject();
|
||||
}
|
||||
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
Object TaggedImpl<kRefType, StorageType>::GetHeapObjectOrSmi(ROOT_PARAM) const {
|
||||
if (kIsFull) return GetHeapObjectOrSmi();
|
||||
// Implementation for compressed pointers.
|
||||
if (IsSmi()) {
|
||||
return Object(DecompressTaggedSigned(ptr_));
|
||||
}
|
||||
return GetHeapObject(ROOT_VALUE);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
@ -23,6 +23,15 @@ namespace internal {
|
||||
template <HeapObjectReferenceType kRefType, typename StorageType>
|
||||
class TaggedImpl {
|
||||
public:
|
||||
static_assert(std::is_same<StorageType, Address>::value ||
|
||||
std::is_same<StorageType, Tagged_t>::value,
|
||||
"StorageType must be either Address or Tagged_t");
|
||||
|
||||
// True for those TaggedImpl instantiations that represent uncompressed
|
||||
// tagged values and false for TaggedImpl instantiations that represent
|
||||
// compressed tagged values.
|
||||
static const bool kIsFull = sizeof(StorageType) == kSystemPointerSize;
|
||||
|
||||
static const bool kCanBeWeak = kRefType == HeapObjectReferenceType::WEAK;
|
||||
|
||||
constexpr TaggedImpl() : ptr_{} {}
|
||||
@ -88,38 +97,57 @@ class TaggedImpl {
|
||||
return kCanBeWeak && HAS_WEAK_HEAP_OBJECT_TAG(ptr_);
|
||||
}
|
||||
|
||||
//
|
||||
// The following set of methods get HeapObject out of the tagged value
|
||||
// which may involve decompression in which case the ROOT_PARAM is required.
|
||||
// If the pointer compression is not enabled then the variants with
|
||||
// ROOT_PARAM will be exactly the same as non-ROOT_PARAM ones.
|
||||
//
|
||||
|
||||
// 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;
|
||||
inline bool GetHeapObjectIfStrong(ROOT_PARAM, HeapObject* result) const;
|
||||
|
||||
// DCHECKs that this tagged value is a strong pointer to a HeapObject and
|
||||
// returns the HeapObject.
|
||||
inline HeapObject GetHeapObjectAssumeStrong() const;
|
||||
inline HeapObject GetHeapObjectAssumeStrong(ROOT_PARAM) 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;
|
||||
inline bool GetHeapObjectIfWeak(ROOT_PARAM, HeapObject* result) const;
|
||||
|
||||
// DCHECKs that this tagged value is a weak pointer to a HeapObject and
|
||||
// returns the HeapObject.
|
||||
inline HeapObject GetHeapObjectAssumeWeak() const;
|
||||
inline HeapObject GetHeapObjectAssumeWeak(ROOT_PARAM) 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(ROOT_PARAM, HeapObject* result) const;
|
||||
|
||||
inline bool GetHeapObject(HeapObject* result,
|
||||
HeapObjectReferenceType* reference_type) const;
|
||||
inline bool GetHeapObject(ROOT_PARAM, 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;
|
||||
inline HeapObject GetHeapObject(ROOT_PARAM) 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;
|
||||
inline Object GetHeapObjectOrSmi(ROOT_PARAM) const;
|
||||
|
||||
// Cast operation is available only for full non-weak tagged values.
|
||||
template <typename T>
|
||||
T cast() const {
|
||||
CHECK(kIsFull);
|
||||
DCHECK(!HAS_WEAK_HEAP_OBJECT_TAG(ptr_));
|
||||
return T::cast(Object(ptr_));
|
||||
}
|
||||
|
39
src/objects/tagged-value-inl.h
Normal file
39
src/objects/tagged-value-inl.h
Normal file
@ -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.
|
||||
|
||||
#ifndef V8_OBJECTS_TAGGED_VALUE_INL_H_
|
||||
#define V8_OBJECTS_TAGGED_VALUE_INL_H_
|
||||
|
||||
#include "src/objects/tagged-value.h"
|
||||
|
||||
#include "include/v8-internal.h"
|
||||
#include "src/objects/heap-object-inl.h"
|
||||
#include "src/objects/oddball.h"
|
||||
#include "src/objects/tagged-impl-inl.h"
|
||||
#include "src/ptr-compr-inl.h"
|
||||
#include "src/roots-inl.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
Object StrongTaggedValue::ToObject(WITH_ROOT_PARAM(StrongTaggedValue object)) {
|
||||
#ifdef V8_COMPRESS_POINTERS
|
||||
return Object(DecompressTaggedAny(ROOT_VALUE, object.ptr()));
|
||||
#else
|
||||
return Object(object.ptr());
|
||||
#endif
|
||||
}
|
||||
|
||||
MaybeObject TaggedValue::ToMaybeObject(WITH_ROOT_PARAM(TaggedValue object)) {
|
||||
#ifdef V8_COMPRESS_POINTERS
|
||||
return MaybeObject(DecompressTaggedAny(ROOT_VALUE, object.ptr()));
|
||||
#else
|
||||
return MaybeObject(object.ptr());
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_OBJECTS_TAGGED_VALUE_INL_H_
|
42
src/objects/tagged-value.h
Normal file
42
src/objects/tagged-value.h
Normal file
@ -0,0 +1,42 @@
|
||||
// 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_VALUE_H_
|
||||
#define V8_OBJECTS_TAGGED_VALUE_H_
|
||||
|
||||
#include "src/objects/objects.h"
|
||||
|
||||
#include "include/v8-internal.h"
|
||||
#include "src/objects/tagged-impl.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// Almost same as Object but this one deals with in-heap and potentially
|
||||
// compressed representation of Objects and provide only limited functionality
|
||||
// which doesn't require decompression.
|
||||
class StrongTaggedValue
|
||||
: public TaggedImpl<HeapObjectReferenceType::STRONG, Tagged_t> {
|
||||
public:
|
||||
constexpr StrongTaggedValue() : TaggedImpl() {}
|
||||
explicit constexpr StrongTaggedValue(Tagged_t ptr) : TaggedImpl(ptr) {}
|
||||
|
||||
inline static Object ToObject(WITH_ROOT_PARAM(StrongTaggedValue object));
|
||||
};
|
||||
|
||||
// Almost same as MaybeObject but this one deals with in-heap and potentially
|
||||
// compressed representation of Objects and provide only limited functionality
|
||||
// which doesn't require decompression.
|
||||
class TaggedValue : public TaggedImpl<HeapObjectReferenceType::WEAK, Tagged_t> {
|
||||
public:
|
||||
constexpr TaggedValue() : TaggedImpl() {}
|
||||
explicit constexpr TaggedValue(Tagged_t ptr) : TaggedImpl(ptr) {}
|
||||
|
||||
inline static MaybeObject ToMaybeObject(WITH_ROOT_PARAM(TaggedValue object));
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_OBJECTS_TAGGED_VALUE_H_
|
@ -5,8 +5,8 @@
|
||||
#ifndef V8_PTR_COMPR_INL_H_
|
||||
#define V8_PTR_COMPR_INL_H_
|
||||
|
||||
|
||||
#include "include/v8-internal.h"
|
||||
#include "src/execution/isolate.h"
|
||||
#include "src/ptr-compr.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -19,34 +19,49 @@ V8_INLINE Tagged_t CompressTagged(Address tagged) {
|
||||
return static_cast<Tagged_t>(static_cast<uint32_t>(tagged));
|
||||
}
|
||||
|
||||
enum class OnHeapAddressKind {
|
||||
kAnyOnHeapAddress,
|
||||
kIsolateRoot,
|
||||
};
|
||||
|
||||
// Calculates isolate root value from any on-heap address.
|
||||
template <OnHeapAddressKind kAddressKind = OnHeapAddressKind::kAnyOnHeapAddress>
|
||||
V8_INLINE Address GetRootFromOnHeapAddress(Address on_heap_addr) {
|
||||
if (kAddressKind == OnHeapAddressKind::kIsolateRoot) return on_heap_addr;
|
||||
return RoundDown(on_heap_addr + kPtrComprIsolateRootBias,
|
||||
kPtrComprIsolateRootAlignment);
|
||||
template <typename TOnHeapAddress>
|
||||
V8_INLINE Address GetIsolateRoot(TOnHeapAddress on_heap_addr);
|
||||
|
||||
template <>
|
||||
V8_INLINE Address GetIsolateRoot<Address>(Address on_heap_addr) {
|
||||
return RoundDown<kPtrComprIsolateRootAlignment>(on_heap_addr +
|
||||
kPtrComprIsolateRootBias);
|
||||
}
|
||||
|
||||
template <>
|
||||
V8_INLINE Address GetIsolateRoot<Isolate*>(Isolate* isolate) {
|
||||
return isolate->isolate_root();
|
||||
}
|
||||
|
||||
template <>
|
||||
V8_INLINE Address GetIsolateRoot<const Isolate*>(const Isolate* isolate) {
|
||||
return isolate->isolate_root();
|
||||
}
|
||||
|
||||
// Decompresses smi value.
|
||||
V8_INLINE Address DecompressTaggedSigned(Tagged_t raw_value) {
|
||||
// Current compression scheme requires |raw_value| to be sign-extended
|
||||
// from int32_t to intptr_t.
|
||||
intptr_t value = static_cast<intptr_t>(static_cast<int32_t>(raw_value));
|
||||
return static_cast<Address>(value);
|
||||
}
|
||||
|
||||
// Decompresses weak or strong heap object pointer or forwarding pointer,
|
||||
// preserving both weak- and smi- tags.
|
||||
template <OnHeapAddressKind kAddressKind = OnHeapAddressKind::kAnyOnHeapAddress>
|
||||
V8_INLINE Address DecompressTaggedPointer(Address on_heap_addr,
|
||||
template <typename TOnHeapAddress>
|
||||
V8_INLINE Address DecompressTaggedPointer(TOnHeapAddress on_heap_addr,
|
||||
Tagged_t raw_value) {
|
||||
// Current compression scheme requires |raw_value| to be sign-extended
|
||||
// from int32_t to intptr_t.
|
||||
intptr_t value = static_cast<intptr_t>(static_cast<int32_t>(raw_value));
|
||||
Address root = GetRootFromOnHeapAddress<kAddressKind>(on_heap_addr);
|
||||
Address root = GetIsolateRoot(on_heap_addr);
|
||||
return root + static_cast<Address>(value);
|
||||
}
|
||||
|
||||
// Decompresses any tagged value, preserving both weak- and smi- tags.
|
||||
template <OnHeapAddressKind kAddressKind = OnHeapAddressKind::kAnyOnHeapAddress>
|
||||
V8_INLINE Address DecompressTaggedAny(Address on_heap_addr,
|
||||
template <typename TOnHeapAddress>
|
||||
V8_INLINE Address DecompressTaggedAny(TOnHeapAddress on_heap_addr,
|
||||
Tagged_t raw_value) {
|
||||
// Current compression scheme requires |raw_value| to be sign-extended
|
||||
// from int32_t to intptr_t.
|
||||
@ -54,14 +69,12 @@ V8_INLINE Address DecompressTaggedAny(Address on_heap_addr,
|
||||
if (kUseBranchlessPtrDecompression) {
|
||||
// |root_mask| is 0 if the |value| was a smi or -1 otherwise.
|
||||
Address root_mask = static_cast<Address>(-(value & kSmiTagMask));
|
||||
Address root_or_zero =
|
||||
root_mask & GetRootFromOnHeapAddress<kAddressKind>(on_heap_addr);
|
||||
Address root_or_zero = root_mask & GetIsolateRoot(on_heap_addr);
|
||||
return root_or_zero + static_cast<Address>(value);
|
||||
} else {
|
||||
return HAS_SMI_TAG(value)
|
||||
? static_cast<Address>(value)
|
||||
: (GetRootFromOnHeapAddress<kAddressKind>(on_heap_addr) +
|
||||
static_cast<Address>(value));
|
||||
: (GetIsolateRoot(on_heap_addr) + static_cast<Address>(value));
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,6 +92,20 @@ STATIC_ASSERT(kPtrComprIsolateRootAlignment ==
|
||||
|
||||
V8_INLINE Tagged_t CompressTagged(Address tagged) { UNREACHABLE(); }
|
||||
|
||||
V8_INLINE Address DecompressTaggedSigned(Tagged_t raw_value) { UNREACHABLE(); }
|
||||
|
||||
template <typename TOnHeapAddress>
|
||||
V8_INLINE Address DecompressTaggedPointer(TOnHeapAddress on_heap_addr,
|
||||
Tagged_t raw_value) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
template <typename TOnHeapAddress>
|
||||
V8_INLINE Address DecompressTaggedAny(TOnHeapAddress on_heap_addr,
|
||||
Tagged_t raw_value) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
#endif // V8_TARGET_ARCH_64_BIT
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -326,11 +326,10 @@ HeapObject RelocInfo::target_object() {
|
||||
HeapObject RelocInfo::target_object_no_host(Isolate* isolate) {
|
||||
DCHECK(IsCodeTarget(rmode_) || IsEmbeddedObjectMode(rmode_));
|
||||
if (IsCompressedEmbeddedObject(rmode_)) {
|
||||
Address root = isolate->isolate_root();
|
||||
Object o = static_cast<Object>(
|
||||
DecompressTaggedPointer<OnHeapAddressKind::kIsolateRoot>(
|
||||
root, ReadUnalignedValue<Tagged_t>(pc_)));
|
||||
return HeapObject::cast(o);
|
||||
Tagged_t compressed = ReadUnalignedValue<Tagged_t>(pc_);
|
||||
DCHECK(!HAS_SMI_TAG(compressed));
|
||||
Object obj(DecompressTaggedPointer(isolate, compressed));
|
||||
return HeapObject::cast(obj);
|
||||
}
|
||||
return HeapObject::cast(Object(ReadUnalignedValue<Address>(pc_)));
|
||||
}
|
||||
@ -377,10 +376,9 @@ void RelocInfo::set_target_object(Heap* heap, HeapObject target,
|
||||
ICacheFlushMode icache_flush_mode) {
|
||||
DCHECK(IsCodeTarget(rmode_) || IsEmbeddedObjectMode(rmode_));
|
||||
if (IsCompressedEmbeddedObject(rmode_)) {
|
||||
#ifdef V8_COMPRESS_POINTERS
|
||||
Tagged_t tagged = CompressTagged(target->ptr());
|
||||
DCHECK(COMPRESS_POINTERS_BOOL);
|
||||
Tagged_t tagged = CompressTagged(target.ptr());
|
||||
WriteUnalignedValue(pc_, tagged);
|
||||
#endif // V8_COMPRESS_POINTERS
|
||||
} else {
|
||||
WriteUnalignedValue(pc_, target.ptr());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user