Commit 719fdae2 authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[ptr-compr] Adding [Heap]Object::IsXXX(Isolate* isolate) predicates

... in addition to existing [Heap]Object::IsXXX().

The idea is to use these getters in hot C++ code since passing isolate
explicitly makes it trivial to compute isolate root value and reduces
the C++ code size.

For full-pointer mode the unused isolate argument will be optimized
away by the compiler, so full-pointer mode should not be affected
in any sense.

Bug: v8:9353
Change-Id: I405cd54e8895b58f60f797fdb1c1b5654acb56f3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1664337
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62335}
parent 6d5731d5
......@@ -14,6 +14,14 @@
namespace v8 {
namespace internal {
inline Isolate* GetIsolateForPtrCompr(HeapObject object) {
#ifdef V8_COMPRESS_POINTERS
return Isolate::FromRoot(GetIsolateRoot(object.ptr()));
#else
return nullptr;
#endif // V8_COMPRESS_POINTERS
}
V8_INLINE Heap* GetHeapFromWritableObject(HeapObject object) {
#ifdef V8_COMPRESS_POINTERS
return GetIsolateFromWritableObject(object)->heap();
......
......@@ -10,6 +10,12 @@
namespace v8 {
namespace internal {
// Computes isolate from any read only or writable heap object. The resulting
// value is intended to be used only as a hoisted computation of isolate root
// inside trivial accessors for optmizing value decompression.
// When pointer compression is disabled this function always returns nullptr.
V8_INLINE Isolate* GetIsolateForPtrCompr(HeapObject object);
V8_INLINE Heap* GetHeapFromWritableObject(HeapObject object);
V8_INLINE Isolate* GetIsolateFromWritableObject(HeapObject object);
......
......@@ -30,6 +30,7 @@ class HeapObject : public Object {
// [map]: Contains a map which contains the object's reflective
// information.
inline Map map() const;
inline Map map(Isolate* isolate) const;
inline void set_map(Map value);
inline ObjectSlot map_slot() const;
......@@ -59,6 +60,7 @@ class HeapObject : public Object {
// During garbage collection, the map word of a heap object does not
// necessarily contain a map pointer.
inline MapWord map_word() const;
inline MapWord map_word(Isolate* isolate) const;
inline void set_map_word(MapWord map_word);
// TODO(v8:7464): Once RO_SPACE is shared between isolates, this method can be
......@@ -67,9 +69,16 @@ class HeapObject : public Object {
// way that doesn't require passing Isolate/Heap down huge call chains or to
// places where it might not be safe to access it.
inline ReadOnlyRoots GetReadOnlyRoots() const;
// This version is intended to be used for the isolate values produced by
// i::GetIsolateForPtrCompr(HeapObject) function which may return nullptr.
inline ReadOnlyRoots GetReadOnlyRoots(Isolate* isolate) const;
#define IS_TYPE_FUNCTION_DECL(Type) V8_INLINE bool Is##Type() const;
#define IS_TYPE_FUNCTION_DECL(Type) \
V8_INLINE bool Is##Type() const; \
V8_INLINE bool Is##Type(Isolate* isolate) const;
HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
IS_TYPE_FUNCTION_DECL(HashTableBase)
IS_TYPE_FUNCTION_DECL(SmallOrderedHashTable)
#undef IS_TYPE_FUNCTION_DECL
bool IsExternal(Isolate* isolate) const;
......@@ -81,13 +90,12 @@ class HeapObject : public Object {
V8_INLINE bool Is##Type(ReadOnlyRoots roots) const; \
V8_INLINE bool Is##Type() const;
ODDBALL_LIST(IS_TYPE_FUNCTION_DECL)
IS_TYPE_FUNCTION_DECL(NullOrUndefined, /* unused */)
#undef IS_TYPE_FUNCTION_DECL
V8_INLINE bool IsNullOrUndefined(Isolate* isolate) const;
V8_INLINE bool IsNullOrUndefined(ReadOnlyRoots roots) const;
V8_INLINE bool IsNullOrUndefined() const;
#define DECL_STRUCT_PREDICATE(NAME, Name, name) V8_INLINE bool Is##Name() const;
#define DECL_STRUCT_PREDICATE(NAME, Name, name) \
V8_INLINE bool Is##Name() const; \
V8_INLINE bool Is##Name(Isolate* isolate) const;
STRUCT_LIST(DECL_STRUCT_PREDICATE)
#undef DECL_STRUCT_PREDICATE
......
......@@ -788,8 +788,8 @@ int NormalizedMapCache::GetIndex(Handle<Map> map) {
return map->Hash() % NormalizedMapCache::kEntries;
}
bool HeapObject::IsNormalizedMapCache() const {
if (!IsWeakFixedArray()) return false;
bool HeapObject::IsNormalizedMapCache(Isolate* isolate) const {
if (!IsWeakFixedArray(isolate)) return false;
if (WeakFixedArray::cast(*this).length() != NormalizedMapCache::kEntries) {
return false;
}
......
......@@ -994,7 +994,7 @@ class NormalizedMapCache : public WeakFixedArray {
DECL_VERIFIER(NormalizedMapCache)
private:
friend bool HeapObject::IsNormalizedMapCache() const;
friend bool HeapObject::IsNormalizedMapCache(Isolate* isolate) const;
static const int kEntries = 64;
......
......@@ -44,8 +44,10 @@ void Symbol::set_is_private_name() {
set_flags(Symbol::IsPrivateNameBit::update(flags(), true));
}
bool Name::IsUniqueName() const {
uint32_t type = map().instance_type();
ISOLATELESS_GETTER(Name, IsUniqueName, bool)
bool Name::IsUniqueName(Isolate* isolate) const {
uint32_t type = map(isolate).instance_type();
bool result = (type & (kIsNotStringMask | kIsNotInternalizedMask)) !=
(kStringTag | kNotInternalizedTag);
SLOW_DCHECK(result == HeapObject::IsUniqueName());
......@@ -91,17 +93,23 @@ uint32_t Name::Hash() {
return String::cast(*this).ComputeAndSetHash();
}
bool Name::IsInterestingSymbol() const {
return IsSymbol() && Symbol::cast(*this).is_interesting_symbol();
ISOLATELESS_GETTER(Name, IsInterestingSymbol, bool)
bool Name::IsInterestingSymbol(Isolate* isolate) const {
return IsSymbol(isolate) && Symbol::cast(*this).is_interesting_symbol();
}
bool Name::IsPrivate() {
return this->IsSymbol() && Symbol::cast(*this).is_private();
ISOLATELESS_GETTER(Name, IsPrivate, bool)
bool Name::IsPrivate(Isolate* isolate) const {
return this->IsSymbol(isolate) && Symbol::cast(*this).is_private();
}
bool Name::IsPrivateName() {
ISOLATELESS_GETTER(Name, IsPrivateName, bool)
bool Name::IsPrivateName(Isolate* isolate) const {
bool is_private_name =
this->IsSymbol() && Symbol::cast(*this).is_private_name();
this->IsSymbol(isolate) && Symbol::cast(*this).is_private_name();
DCHECK_IMPLIES(is_private_name, IsPrivate());
return is_private_name;
}
......
......@@ -43,15 +43,19 @@ class Name : public HeapObject {
// symbol properties are added, so we can optimize lookups on objects
// that don't have the flag.
inline bool IsInterestingSymbol() const;
inline bool IsInterestingSymbol(Isolate* isolate) const;
// If the name is private, it can only name own properties.
inline bool IsPrivate();
inline bool IsPrivate() const;
inline bool IsPrivate(Isolate* isolate) const;
// If the name is a private name, it should behave like a private
// symbol but also throw on property access miss.
inline bool IsPrivateName();
inline bool IsPrivateName() const;
inline bool IsPrivateName(Isolate* isolate) const;
inline bool IsUniqueName() const;
inline bool IsUniqueName(Isolate* isolate) const;
static inline bool ContainsCachedArrayIndex(uint32_t hash);
......
......@@ -25,6 +25,7 @@
#undef RELAXED_INT32_ACCESSORS
#undef UINT16_ACCESSORS
#undef UINT8_ACCESSORS
#undef ISOLATELESS_GETTER
#undef ACCESSORS_CHECKED2
#undef ACCESSORS_CHECKED
#undef ACCESSORS
......
......@@ -111,6 +111,15 @@
WriteField<uint8_t>(offset, value); \
}
// TODO(ishell): eventually isolate-less getters should not be used anymore.
// For full pointer-mode the C++ compiler should optimize away unused isolate
// parameter.
#define ISOLATELESS_GETTER(holder, name, type) \
type holder::name() const { \
Isolate* isolate = GetIsolateForPtrCompr(*this); \
return holder::name(isolate); \
}
#define ACCESSORS_CHECKED2(holder, name, type, offset, get_condition, \
set_condition) \
type holder::name() const { \
......@@ -236,9 +245,9 @@
return instance_type == forinstancetype; \
}
#define TYPE_CHECKER(type, ...) \
bool HeapObject::Is##type() const { \
return InstanceTypeChecker::Is##type(map().instance_type()); \
#define TYPE_CHECKER(type, ...) \
bool HeapObject::Is##type(Isolate* isolate) const { \
return InstanceTypeChecker::Is##type(map(isolate).instance_type()); \
}
#define RELAXED_INT16_ACCESSORS(holder, name, offset) \
......
This diff is collapsed.
......@@ -267,9 +267,13 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> {
constexpr Object() : TaggedImpl(kNullAddress) {}
explicit constexpr Object(Address ptr) : TaggedImpl(ptr) {}
#define IS_TYPE_FUNCTION_DECL(Type) V8_INLINE bool Is##Type() const;
#define IS_TYPE_FUNCTION_DECL(Type) \
V8_INLINE bool Is##Type() const; \
V8_INLINE bool Is##Type(Isolate* isolate) const;
OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
IS_TYPE_FUNCTION_DECL(HashTableBase)
IS_TYPE_FUNCTION_DECL(SmallOrderedHashTable)
#undef IS_TYPE_FUNCTION_DECL
// Oddball checks are faster when they are raw pointer comparisons, so the
......@@ -279,18 +283,17 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> {
V8_INLINE bool Is##Type(ReadOnlyRoots roots) const; \
V8_INLINE bool Is##Type() const;
ODDBALL_LIST(IS_TYPE_FUNCTION_DECL)
IS_TYPE_FUNCTION_DECL(NullOrUndefined, /* unused */)
#undef IS_TYPE_FUNCTION_DECL
V8_INLINE bool IsNullOrUndefined(Isolate* isolate) const;
V8_INLINE bool IsNullOrUndefined(ReadOnlyRoots roots) const;
V8_INLINE bool IsNullOrUndefined() const;
V8_INLINE bool IsZero() const;
V8_INLINE bool IsNoSharedNameSentinel() const;
enum class Conversion { kToNumber, kToNumeric };
#define DECL_STRUCT_PREDICATE(NAME, Name, name) V8_INLINE bool Is##Name() const;
#define DECL_STRUCT_PREDICATE(NAME, Name, name) \
V8_INLINE bool Is##Name() const; \
V8_INLINE bool Is##Name(Isolate* isolate) const;
STRUCT_LIST(DECL_STRUCT_PREDICATE)
#undef DECL_STRUCT_PREDICATE
......@@ -298,9 +301,6 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> {
V8_INLINE
V8_WARN_UNUSED_RESULT static Maybe<bool> IsArray(Handle<Object> object);
V8_INLINE bool IsHashTableBase() const;
V8_INLINE bool IsSmallOrderedHashTable() const;
// Extract the number.
inline double Number() const;
V8_INLINE bool IsNaN() const;
......
......@@ -38,8 +38,8 @@ Handle<Object> Oddball::ToNumber(Isolate* isolate, Handle<Oddball> input) {
return Handle<Object>(input->to_number(), isolate);
}
bool HeapObject::IsBoolean() const {
return IsOddball() &&
bool HeapObject::IsBoolean(Isolate* isolate) const {
return IsOddball(isolate) &&
((Oddball::cast(*this).kind() & Oddball::kNotBooleanMask) == 0);
}
......
......@@ -105,9 +105,9 @@ CAST_ACCESSOR(UncompiledDataWithPreparseData)
ACCESSORS(UncompiledDataWithPreparseData, preparse_data, PreparseData,
kPreparseDataOffset)
bool HeapObject::IsUncompiledData() const {
return IsUncompiledDataWithoutPreparseData() ||
IsUncompiledDataWithPreparseData();
bool HeapObject::IsUncompiledData(Isolate* isolate) const {
return IsUncompiledDataWithoutPreparseData(isolate) ||
IsUncompiledDataWithPreparseData(isolate);
}
OBJECT_CONSTRUCTORS_IMPL(InterpreterData, Struct)
......
......@@ -147,16 +147,21 @@ STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) ==
STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
bool String::IsOneByteRepresentation() const {
uint32_t type = map().instance_type();
ISOLATELESS_GETTER(String, IsOneByteRepresentation, bool)
bool String::IsOneByteRepresentation(Isolate* isolate) const {
uint32_t type = map(isolate).instance_type();
return (type & kStringEncodingMask) == kOneByteStringTag;
}
bool String::IsTwoByteRepresentation() const {
uint32_t type = map().instance_type();
ISOLATELESS_GETTER(String, IsTwoByteRepresentation, bool)
bool String::IsTwoByteRepresentation(Isolate* isolate) const {
uint32_t type = map(isolate).instance_type();
return (type & kStringEncodingMask) == kTwoByteStringTag;
}
// static
bool String::IsOneByteRepresentationUnderneath(String string) {
while (true) {
uint32_t type = string.map().instance_type();
......
......@@ -166,7 +166,9 @@ class String : public Name {
// two-byte. Such strings may appear when the embedder prefers
// two-byte external representations even for one-byte data.
inline bool IsOneByteRepresentation() const;
inline bool IsOneByteRepresentation(Isolate* isolate) const;
inline bool IsTwoByteRepresentation() const;
inline bool IsTwoByteRepresentation(Isolate* isolate) const;
// Cons and slices have an encoding flag that may not represent the actual
// encoding of the underlying string. This is taken into account here.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment