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 @@ ...@@ -14,6 +14,14 @@
namespace v8 { namespace v8 {
namespace internal { 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) { V8_INLINE Heap* GetHeapFromWritableObject(HeapObject object) {
#ifdef V8_COMPRESS_POINTERS #ifdef V8_COMPRESS_POINTERS
return GetIsolateFromWritableObject(object)->heap(); return GetIsolateFromWritableObject(object)->heap();
......
...@@ -10,6 +10,12 @@ ...@@ -10,6 +10,12 @@
namespace v8 { namespace v8 {
namespace internal { 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 Heap* GetHeapFromWritableObject(HeapObject object);
V8_INLINE Isolate* GetIsolateFromWritableObject(HeapObject object); V8_INLINE Isolate* GetIsolateFromWritableObject(HeapObject object);
......
...@@ -30,6 +30,7 @@ class HeapObject : public Object { ...@@ -30,6 +30,7 @@ class HeapObject : public Object {
// [map]: Contains a map which contains the object's reflective // [map]: Contains a map which contains the object's reflective
// information. // information.
inline Map map() const; inline Map map() const;
inline Map map(Isolate* isolate) const;
inline void set_map(Map value); inline void set_map(Map value);
inline ObjectSlot map_slot() const; inline ObjectSlot map_slot() const;
...@@ -59,6 +60,7 @@ class HeapObject : public Object { ...@@ -59,6 +60,7 @@ class HeapObject : public Object {
// During garbage collection, the map word of a heap object does not // During garbage collection, the map word of a heap object does not
// necessarily contain a map pointer. // necessarily contain a map pointer.
inline MapWord map_word() const; inline MapWord map_word() const;
inline MapWord map_word(Isolate* isolate) const;
inline void set_map_word(MapWord map_word); inline void set_map_word(MapWord map_word);
// TODO(v8:7464): Once RO_SPACE is shared between isolates, this method can be // TODO(v8:7464): Once RO_SPACE is shared between isolates, this method can be
...@@ -67,9 +69,16 @@ class HeapObject : public Object { ...@@ -67,9 +69,16 @@ class HeapObject : public Object {
// way that doesn't require passing Isolate/Heap down huge call chains or to // way that doesn't require passing Isolate/Heap down huge call chains or to
// places where it might not be safe to access it. // places where it might not be safe to access it.
inline ReadOnlyRoots GetReadOnlyRoots() const; 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) HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
IS_TYPE_FUNCTION_DECL(HashTableBase)
IS_TYPE_FUNCTION_DECL(SmallOrderedHashTable)
#undef IS_TYPE_FUNCTION_DECL #undef IS_TYPE_FUNCTION_DECL
bool IsExternal(Isolate* isolate) const; bool IsExternal(Isolate* isolate) const;
...@@ -81,13 +90,12 @@ class HeapObject : public Object { ...@@ -81,13 +90,12 @@ class HeapObject : public Object {
V8_INLINE bool Is##Type(ReadOnlyRoots roots) const; \ V8_INLINE bool Is##Type(ReadOnlyRoots roots) const; \
V8_INLINE bool Is##Type() const; V8_INLINE bool Is##Type() const;
ODDBALL_LIST(IS_TYPE_FUNCTION_DECL) ODDBALL_LIST(IS_TYPE_FUNCTION_DECL)
IS_TYPE_FUNCTION_DECL(NullOrUndefined, /* unused */)
#undef IS_TYPE_FUNCTION_DECL #undef IS_TYPE_FUNCTION_DECL
V8_INLINE bool IsNullOrUndefined(Isolate* isolate) const; #define DECL_STRUCT_PREDICATE(NAME, Name, name) \
V8_INLINE bool IsNullOrUndefined(ReadOnlyRoots roots) const; V8_INLINE bool Is##Name() const; \
V8_INLINE bool IsNullOrUndefined() const; V8_INLINE bool Is##Name(Isolate* isolate) const;
#define DECL_STRUCT_PREDICATE(NAME, Name, name) V8_INLINE bool Is##Name() const;
STRUCT_LIST(DECL_STRUCT_PREDICATE) STRUCT_LIST(DECL_STRUCT_PREDICATE)
#undef DECL_STRUCT_PREDICATE #undef DECL_STRUCT_PREDICATE
......
...@@ -788,8 +788,8 @@ int NormalizedMapCache::GetIndex(Handle<Map> map) { ...@@ -788,8 +788,8 @@ int NormalizedMapCache::GetIndex(Handle<Map> map) {
return map->Hash() % NormalizedMapCache::kEntries; return map->Hash() % NormalizedMapCache::kEntries;
} }
bool HeapObject::IsNormalizedMapCache() const { bool HeapObject::IsNormalizedMapCache(Isolate* isolate) const {
if (!IsWeakFixedArray()) return false; if (!IsWeakFixedArray(isolate)) return false;
if (WeakFixedArray::cast(*this).length() != NormalizedMapCache::kEntries) { if (WeakFixedArray::cast(*this).length() != NormalizedMapCache::kEntries) {
return false; return false;
} }
......
...@@ -994,7 +994,7 @@ class NormalizedMapCache : public WeakFixedArray { ...@@ -994,7 +994,7 @@ class NormalizedMapCache : public WeakFixedArray {
DECL_VERIFIER(NormalizedMapCache) DECL_VERIFIER(NormalizedMapCache)
private: private:
friend bool HeapObject::IsNormalizedMapCache() const; friend bool HeapObject::IsNormalizedMapCache(Isolate* isolate) const;
static const int kEntries = 64; static const int kEntries = 64;
......
...@@ -44,8 +44,10 @@ void Symbol::set_is_private_name() { ...@@ -44,8 +44,10 @@ void Symbol::set_is_private_name() {
set_flags(Symbol::IsPrivateNameBit::update(flags(), true)); set_flags(Symbol::IsPrivateNameBit::update(flags(), true));
} }
bool Name::IsUniqueName() const { ISOLATELESS_GETTER(Name, IsUniqueName, bool)
uint32_t type = map().instance_type();
bool Name::IsUniqueName(Isolate* isolate) const {
uint32_t type = map(isolate).instance_type();
bool result = (type & (kIsNotStringMask | kIsNotInternalizedMask)) != bool result = (type & (kIsNotStringMask | kIsNotInternalizedMask)) !=
(kStringTag | kNotInternalizedTag); (kStringTag | kNotInternalizedTag);
SLOW_DCHECK(result == HeapObject::IsUniqueName()); SLOW_DCHECK(result == HeapObject::IsUniqueName());
...@@ -91,17 +93,23 @@ uint32_t Name::Hash() { ...@@ -91,17 +93,23 @@ uint32_t Name::Hash() {
return String::cast(*this).ComputeAndSetHash(); return String::cast(*this).ComputeAndSetHash();
} }
bool Name::IsInterestingSymbol() const { ISOLATELESS_GETTER(Name, IsInterestingSymbol, bool)
return IsSymbol() && Symbol::cast(*this).is_interesting_symbol();
bool Name::IsInterestingSymbol(Isolate* isolate) const {
return IsSymbol(isolate) && Symbol::cast(*this).is_interesting_symbol();
} }
bool Name::IsPrivate() { ISOLATELESS_GETTER(Name, IsPrivate, bool)
return this->IsSymbol() && Symbol::cast(*this).is_private();
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 = 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()); DCHECK_IMPLIES(is_private_name, IsPrivate());
return is_private_name; return is_private_name;
} }
......
...@@ -43,15 +43,19 @@ class Name : public HeapObject { ...@@ -43,15 +43,19 @@ class Name : public HeapObject {
// symbol properties are added, so we can optimize lookups on objects // symbol properties are added, so we can optimize lookups on objects
// that don't have the flag. // that don't have the flag.
inline bool IsInterestingSymbol() const; inline bool IsInterestingSymbol() const;
inline bool IsInterestingSymbol(Isolate* isolate) const;
// If the name is private, it can only name own properties. // 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 // If the name is a private name, it should behave like a private
// symbol but also throw on property access miss. // 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() const;
inline bool IsUniqueName(Isolate* isolate) const;
static inline bool ContainsCachedArrayIndex(uint32_t hash); static inline bool ContainsCachedArrayIndex(uint32_t hash);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#undef RELAXED_INT32_ACCESSORS #undef RELAXED_INT32_ACCESSORS
#undef UINT16_ACCESSORS #undef UINT16_ACCESSORS
#undef UINT8_ACCESSORS #undef UINT8_ACCESSORS
#undef ISOLATELESS_GETTER
#undef ACCESSORS_CHECKED2 #undef ACCESSORS_CHECKED2
#undef ACCESSORS_CHECKED #undef ACCESSORS_CHECKED
#undef ACCESSORS #undef ACCESSORS
......
...@@ -111,6 +111,15 @@ ...@@ -111,6 +111,15 @@
WriteField<uint8_t>(offset, value); \ 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, \ #define ACCESSORS_CHECKED2(holder, name, type, offset, get_condition, \
set_condition) \ set_condition) \
type holder::name() const { \ type holder::name() const { \
...@@ -237,8 +246,8 @@ ...@@ -237,8 +246,8 @@
} }
#define TYPE_CHECKER(type, ...) \ #define TYPE_CHECKER(type, ...) \
bool HeapObject::Is##type() const { \ bool HeapObject::Is##type(Isolate* isolate) const { \
return InstanceTypeChecker::Is##type(map().instance_type()); \ return InstanceTypeChecker::Is##type(map(isolate).instance_type()); \
} }
#define RELAXED_INT16_ACCESSORS(holder, name, offset) \ #define RELAXED_INT16_ACCESSORS(holder, name, offset) \
......
...@@ -66,30 +66,38 @@ int PropertyDetails::field_width_in_words() const { ...@@ -66,30 +66,38 @@ int PropertyDetails::field_width_in_words() const {
return representation().IsDouble() ? kDoubleSize / kTaggedSize : 1; return representation().IsDouble() ? kDoubleSize / kTaggedSize : 1;
} }
bool HeapObject::IsSloppyArgumentsElements() const { bool HeapObject::IsSloppyArgumentsElements(Isolate* isolate) const {
return IsFixedArrayExact(); return IsFixedArrayExact(isolate);
} }
bool HeapObject::IsJSSloppyArgumentsObject() const { bool HeapObject::IsJSSloppyArgumentsObject(Isolate* isolate) const {
return IsJSArgumentsObject(); return IsJSArgumentsObject(isolate);
} }
bool HeapObject::IsJSGeneratorObject() const { bool HeapObject::IsJSGeneratorObject(Isolate* isolate) const {
return map().instance_type() == JS_GENERATOR_OBJECT_TYPE || return map(isolate).instance_type() == JS_GENERATOR_OBJECT_TYPE ||
IsJSAsyncFunctionObject() || IsJSAsyncGeneratorObject(); IsJSAsyncFunctionObject(isolate) || IsJSAsyncGeneratorObject(isolate);
} }
bool HeapObject::IsDataHandler() const { bool HeapObject::IsDataHandler(Isolate* isolate) const {
return IsLoadHandler() || IsStoreHandler(); return IsLoadHandler(isolate) || IsStoreHandler(isolate);
} }
bool HeapObject::IsClassBoilerplate() const { return IsFixedArrayExact(); } bool HeapObject::IsClassBoilerplate(Isolate* isolate) const {
return IsFixedArrayExact(isolate);
}
#define IS_TYPE_FUNCTION_DEF(type_) \ #define IS_TYPE_FUNCTION_DEF(type_) \
bool Object::Is##type_() const { \ bool Object::Is##type_() const { \
return IsHeapObject() && HeapObject::cast(*this).Is##type_(); \ return IsHeapObject() && HeapObject::cast(*this).Is##type_(); \
} } \
bool Object::Is##type_(Isolate* isolate) const { \
return IsHeapObject() && HeapObject::cast(*this).Is##type_(isolate); \
} \
ISOLATELESS_GETTER(HeapObject, Is##type_, bool)
HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DEF) HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DEF)
IS_TYPE_FUNCTION_DEF(HashTableBase)
IS_TYPE_FUNCTION_DEF(SmallOrderedHashTable)
#undef IS_TYPE_FUNCTION_DEF #undef IS_TYPE_FUNCTION_DEF
#define IS_TYPE_FUNCTION_DEF(Type, Value) \ #define IS_TYPE_FUNCTION_DEF(Type, Value) \
...@@ -142,123 +150,168 @@ bool HeapObject::IsNullOrUndefined() const { ...@@ -142,123 +150,168 @@ bool HeapObject::IsNullOrUndefined() const {
return IsNullOrUndefined(GetReadOnlyRoots()); return IsNullOrUndefined(GetReadOnlyRoots());
} }
bool HeapObject::IsUniqueName() const { bool HeapObject::IsUniqueName(Isolate* isolate) const {
return IsInternalizedString() || IsSymbol(); return IsInternalizedString(isolate) || IsSymbol(isolate);
} }
bool HeapObject::IsFunction() const { bool HeapObject::IsFunction(Isolate* isolate) const {
STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
return map().instance_type() >= FIRST_FUNCTION_TYPE; return map(isolate).instance_type() >= FIRST_FUNCTION_TYPE;
} }
bool HeapObject::IsCallable() const { return map().is_callable(); } bool HeapObject::IsCallable(Isolate* isolate) const {
return map(isolate).is_callable();
}
bool HeapObject::IsCallableJSProxy() const { bool HeapObject::IsCallableJSProxy(Isolate* isolate) const {
return IsCallable() && IsJSProxy(); return IsCallable(isolate) && IsJSProxy(isolate);
} }
bool HeapObject::IsCallableApiObject() const { bool HeapObject::IsCallableApiObject(Isolate* isolate) const {
InstanceType type = map().instance_type(); InstanceType type = map(isolate).instance_type();
return IsCallable() && return IsCallable(isolate) &&
(type == JS_API_OBJECT_TYPE || type == JS_SPECIAL_API_OBJECT_TYPE); (type == JS_API_OBJECT_TYPE || type == JS_SPECIAL_API_OBJECT_TYPE);
} }
bool HeapObject::IsNonNullForeign() const { bool HeapObject::IsNonNullForeign(Isolate* isolate) const {
return IsForeign() && Foreign::cast(*this).foreign_address() != kNullAddress; return IsForeign(isolate) &&
Foreign::cast(*this).foreign_address() != kNullAddress;
}
bool HeapObject::IsConstructor(Isolate* isolate) const {
return map(isolate).is_constructor();
}
bool HeapObject::IsSourceTextModuleInfo(Isolate* isolate) const {
// Can't use ReadOnlyRoots(isolate) as this isolate could be produced by
// i::GetIsolateForPtrCompr(HeapObject).
return map(isolate) == GetReadOnlyRoots(isolate).module_info_map();
} }
bool HeapObject::IsConstructor() const { return map().is_constructor(); } bool HeapObject::IsTemplateInfo(Isolate* isolate) const {
return IsObjectTemplateInfo(isolate) || IsFunctionTemplateInfo(isolate);
}
bool HeapObject::IsSourceTextModuleInfo() const { bool HeapObject::IsConsString(Isolate* isolate) const {
return map() == GetReadOnlyRoots().module_info_map(); if (!IsString(isolate)) return false;
return StringShape(String::cast(*this).map(isolate)).IsCons();
} }
bool HeapObject::IsTemplateInfo() const { bool HeapObject::IsThinString(Isolate* isolate) const {
return IsObjectTemplateInfo() || IsFunctionTemplateInfo(); if (!IsString(isolate)) return false;
return StringShape(String::cast(*this).map(isolate)).IsThin();
} }
bool HeapObject::IsConsString() const { bool HeapObject::IsSlicedString(Isolate* isolate) const {
if (!IsString()) return false; if (!IsString(isolate)) return false;
return StringShape(String::cast(*this)).IsCons(); return StringShape(String::cast(*this).map(isolate)).IsSliced();
} }
bool HeapObject::IsThinString() const { bool HeapObject::IsSeqString(Isolate* isolate) const {
if (!IsString()) return false; if (!IsString(isolate)) return false;
return StringShape(String::cast(*this)).IsThin(); return StringShape(String::cast(*this).map(isolate)).IsSequential();
} }
bool HeapObject::IsSlicedString() const { bool HeapObject::IsSeqOneByteString(Isolate* isolate) const {
if (!IsString()) return false; if (!IsString(isolate)) return false;
return StringShape(String::cast(*this)).IsSliced(); return StringShape(String::cast(*this).map(isolate)).IsSequential() &&
String::cast(*this).IsOneByteRepresentation(isolate);
} }
bool HeapObject::IsSeqString() const { bool HeapObject::IsSeqTwoByteString(Isolate* isolate) const {
if (!IsString()) return false; if (!IsString(isolate)) return false;
return StringShape(String::cast(*this)).IsSequential(); return StringShape(String::cast(*this).map(isolate)).IsSequential() &&
String::cast(*this).IsTwoByteRepresentation(isolate);
} }
bool HeapObject::IsSeqOneByteString() const { bool HeapObject::IsExternalString(Isolate* isolate) const {
if (!IsString()) return false; if (!IsString(isolate)) return false;
return StringShape(String::cast(*this)).IsSequential() && return StringShape(String::cast(*this).map(isolate)).IsExternal();
String::cast(*this).IsOneByteRepresentation();
} }
bool HeapObject::IsSeqTwoByteString() const { bool HeapObject::IsExternalOneByteString(Isolate* isolate) const {
if (!IsString()) return false; if (!IsString(isolate)) return false;
return StringShape(String::cast(*this)).IsSequential() && return StringShape(String::cast(*this).map(isolate)).IsExternal() &&
String::cast(*this).IsTwoByteRepresentation(); String::cast(*this).IsOneByteRepresentation(isolate);
} }
bool HeapObject::IsExternalString() const { bool HeapObject::IsExternalTwoByteString(Isolate* isolate) const {
if (!IsString()) return false; if (!IsString(isolate)) return false;
return StringShape(String::cast(*this)).IsExternal(); return StringShape(String::cast(*this).map(isolate)).IsExternal() &&
String::cast(*this).IsTwoByteRepresentation(isolate);
} }
bool HeapObject::IsExternalOneByteString() const { bool Object::IsNumber() const {
if (!IsString()) return false; if (IsSmi()) return true;
return StringShape(String::cast(*this)).IsExternal() && HeapObject this_heap_object = HeapObject::cast(*this);
String::cast(*this).IsOneByteRepresentation(); Isolate* isolate = GetIsolateForPtrCompr(this_heap_object);
return this_heap_object.IsHeapNumber(isolate);
} }
bool HeapObject::IsExternalTwoByteString() const { bool Object::IsNumber(Isolate* isolate) const {
if (!IsString()) return false; return IsSmi() || IsHeapNumber(isolate);
return StringShape(String::cast(*this)).IsExternal() &&
String::cast(*this).IsTwoByteRepresentation();
} }
bool Object::IsNumber() const { return IsSmi() || IsHeapNumber(); } bool Object::IsNumeric() const {
if (IsSmi()) return true;
HeapObject this_heap_object = HeapObject::cast(*this);
Isolate* isolate = GetIsolateForPtrCompr(this_heap_object);
return this_heap_object.IsHeapNumber(isolate) ||
this_heap_object.IsBigInt(isolate);
}
bool Object::IsNumeric() const { return IsNumber() || IsBigInt(); } bool Object::IsNumeric(Isolate* isolate) const {
return IsNumber(isolate) || IsBigInt(isolate);
}
bool HeapObject::IsFiller() const { bool HeapObject::IsFiller(Isolate* isolate) const {
InstanceType instance_type = map().instance_type(); InstanceType instance_type = map(isolate).instance_type();
return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE; return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
} }
bool HeapObject::IsJSWeakCollection() const { bool HeapObject::IsJSWeakCollection(Isolate* isolate) const {
return IsJSWeakMap() || IsJSWeakSet(); return IsJSWeakMap(isolate) || IsJSWeakSet(isolate);
} }
bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); } bool HeapObject::IsJSCollection(Isolate* isolate) const {
return IsJSMap(isolate) || IsJSSet(isolate);
}
bool HeapObject::IsPromiseReactionJobTask() const { bool HeapObject::IsPromiseReactionJobTask(Isolate* isolate) const {
return IsPromiseFulfillReactionJobTask() || IsPromiseRejectReactionJobTask(); return IsPromiseFulfillReactionJobTask(isolate) ||
IsPromiseRejectReactionJobTask(isolate);
} }
bool HeapObject::IsFrameArray() const { return IsFixedArrayExact(); } bool HeapObject::IsFrameArray(Isolate* isolate) const {
return IsFixedArrayExact(isolate);
}
bool HeapObject::IsArrayList() const { bool HeapObject::IsArrayList(Isolate* isolate) const {
return map() == GetReadOnlyRoots().array_list_map() || // Can't use ReadOnlyRoots(isolate) as this isolate could be produced by
*this == GetReadOnlyRoots().empty_fixed_array(); // i::GetIsolateForPtrCompr(HeapObject).
ReadOnlyRoots roots = GetReadOnlyRoots(isolate);
return *this == roots.empty_fixed_array() ||
map(isolate) == roots.array_list_map();
} }
bool HeapObject::IsRegExpMatchInfo() const { return IsFixedArrayExact(); } bool HeapObject::IsRegExpMatchInfo(Isolate* isolate) const {
return IsFixedArrayExact(isolate);
}
bool Object::IsLayoutDescriptor() const {
if (IsSmi()) return true;
HeapObject this_heap_object = HeapObject::cast(*this);
Isolate* isolate = GetIsolateForPtrCompr(this_heap_object);
return this_heap_object.IsByteArray(isolate);
}
bool Object::IsLayoutDescriptor() const { return IsSmi() || IsByteArray(); } bool Object::IsLayoutDescriptor(Isolate* isolate) const {
return IsSmi() || IsByteArray(isolate);
}
bool HeapObject::IsDeoptimizationData() const { bool HeapObject::IsDeoptimizationData(Isolate* isolate) const {
// Must be a fixed array. // Must be a fixed array.
if (!IsFixedArrayExact()) return false; if (!IsFixedArrayExact(isolate)) return false;
// There's no sure way to detect the difference between a fixed array and // There's no sure way to detect the difference between a fixed array and
// a deoptimization data array. Since this is used for asserts we can // a deoptimization data array. Since this is used for asserts we can
...@@ -271,83 +324,102 @@ bool HeapObject::IsDeoptimizationData() const { ...@@ -271,83 +324,102 @@ bool HeapObject::IsDeoptimizationData() const {
return length >= 0 && length % DeoptimizationData::kDeoptEntrySize == 0; return length >= 0 && length % DeoptimizationData::kDeoptEntrySize == 0;
} }
bool HeapObject::IsHandlerTable() const { bool HeapObject::IsHandlerTable(Isolate* isolate) const {
if (!IsFixedArrayExact()) return false; if (!IsFixedArrayExact(isolate)) return false;
// There's actually no way to see the difference between a fixed array and // There's actually no way to see the difference between a fixed array and
// a handler table array. // a handler table array.
return true; return true;
} }
bool HeapObject::IsTemplateList() const { bool HeapObject::IsTemplateList(Isolate* isolate) const {
if (!IsFixedArrayExact()) return false; if (!IsFixedArrayExact(isolate)) return false;
// There's actually no way to see the difference between a fixed array and // There's actually no way to see the difference between a fixed array and
// a template list. // a template list.
if (FixedArray::cast(*this).length() < 1) return false; if (FixedArray::cast(*this).length() < 1) return false;
return true; return true;
} }
bool HeapObject::IsDependentCode() const { bool HeapObject::IsDependentCode(Isolate* isolate) const {
if (!IsWeakFixedArray()) return false; if (!IsWeakFixedArray(isolate)) return false;
// There's actually no way to see the difference between a weak fixed array // There's actually no way to see the difference between a weak fixed array
// and a dependent codes array. // and a dependent codes array.
return true; return true;
} }
bool HeapObject::IsAbstractCode() const { bool HeapObject::IsAbstractCode(Isolate* isolate) const {
return IsBytecodeArray() || IsCode(); return IsBytecodeArray(isolate) || IsCode(isolate);
} }
bool HeapObject::IsStringWrapper() const { bool HeapObject::IsStringWrapper(Isolate* isolate) const {
return IsJSValue() && JSValue::cast(*this).value().IsString(); return IsJSValue(isolate) && JSValue::cast(*this).value().IsString(isolate);
} }
bool HeapObject::IsBooleanWrapper() const { bool HeapObject::IsBooleanWrapper(Isolate* isolate) const {
return IsJSValue() && JSValue::cast(*this).value().IsBoolean(); return IsJSValue(isolate) && JSValue::cast(*this).value().IsBoolean(isolate);
} }
bool HeapObject::IsScriptWrapper() const { bool HeapObject::IsScriptWrapper(Isolate* isolate) const {
return IsJSValue() && JSValue::cast(*this).value().IsScript(); return IsJSValue(isolate) && JSValue::cast(*this).value().IsScript(isolate);
} }
bool HeapObject::IsNumberWrapper() const { bool HeapObject::IsNumberWrapper(Isolate* isolate) const {
return IsJSValue() && JSValue::cast(*this).value().IsNumber(); return IsJSValue(isolate) && JSValue::cast(*this).value().IsNumber(isolate);
} }
bool HeapObject::IsBigIntWrapper() const { bool HeapObject::IsBigIntWrapper(Isolate* isolate) const {
return IsJSValue() && JSValue::cast(*this).value().IsBigInt(); return IsJSValue(isolate) && JSValue::cast(*this).value().IsBigInt(isolate);
} }
bool HeapObject::IsSymbolWrapper() const { bool HeapObject::IsSymbolWrapper(Isolate* isolate) const {
return IsJSValue() && JSValue::cast(*this).value().IsSymbol(); return IsJSValue(isolate) && JSValue::cast(*this).value().IsSymbol(isolate);
} }
bool HeapObject::IsJSArrayBufferView() const { bool HeapObject::IsJSArrayBufferView(Isolate* isolate) const {
return IsJSDataView() || IsJSTypedArray(); return IsJSDataView(isolate) || IsJSTypedArray(isolate);
} }
bool HeapObject::IsJSCollectionIterator() const { bool HeapObject::IsJSCollectionIterator(Isolate* isolate) const {
return IsJSMapIterator() || IsJSSetIterator(); return IsJSMapIterator(isolate) || IsJSSetIterator(isolate);
} }
bool HeapObject::IsStringSet() const { return IsHashTable(); } bool HeapObject::IsStringSet(Isolate* isolate) const {
return IsHashTable(isolate);
}
bool HeapObject::IsObjectHashSet() const { return IsHashTable(); } bool HeapObject::IsObjectHashSet(Isolate* isolate) const {
return IsHashTable(isolate);
}
bool HeapObject::IsCompilationCacheTable() const { return IsHashTable(); } bool HeapObject::IsCompilationCacheTable(Isolate* isolate) const {
return IsHashTable(isolate);
}
bool HeapObject::IsMapCache() const { return IsHashTable(); } bool HeapObject::IsMapCache(Isolate* isolate) const {
return IsHashTable(isolate);
}
bool HeapObject::IsObjectHashTable() const { return IsHashTable(); } bool HeapObject::IsObjectHashTable(Isolate* isolate) const {
return IsHashTable(isolate);
}
bool Object::IsHashTableBase() const { return IsHashTable(); } bool HeapObject::IsHashTableBase(Isolate* isolate) const {
return IsHashTable(isolate);
}
bool Object::IsSmallOrderedHashTable() const { bool HeapObject::IsSmallOrderedHashTable(Isolate* isolate) const {
return IsSmallOrderedHashSet() || IsSmallOrderedHashMap() || return IsSmallOrderedHashSet(isolate) || IsSmallOrderedHashMap(isolate) ||
IsSmallOrderedNameDictionary(); IsSmallOrderedNameDictionary(isolate);
} }
bool Object::IsPrimitive() const { bool Object::IsPrimitive() const {
return IsSmi() || HeapObject::cast(*this).map().IsPrimitiveMap(); if (IsSmi()) return true;
HeapObject this_heap_object = HeapObject::cast(*this);
Isolate* isolate = GetIsolateForPtrCompr(this_heap_object);
return this_heap_object.map(isolate).IsPrimitiveMap();
}
bool Object::IsPrimitive(Isolate* isolate) const {
return IsSmi() || HeapObject::cast(*this).map(isolate).IsPrimitiveMap();
} }
// static // static
...@@ -359,19 +431,21 @@ Maybe<bool> Object::IsArray(Handle<Object> object) { ...@@ -359,19 +431,21 @@ Maybe<bool> Object::IsArray(Handle<Object> object) {
return JSProxy::IsArray(Handle<JSProxy>::cast(object)); return JSProxy::IsArray(Handle<JSProxy>::cast(object));
} }
bool HeapObject::IsUndetectable() const { return map().is_undetectable(); } bool HeapObject::IsUndetectable(Isolate* isolate) const {
return map(isolate).is_undetectable();
}
bool HeapObject::IsAccessCheckNeeded() const { bool HeapObject::IsAccessCheckNeeded(Isolate* isolate) const {
if (IsJSGlobalProxy()) { if (IsJSGlobalProxy(isolate)) {
const JSGlobalProxy proxy = JSGlobalProxy::cast(*this); const JSGlobalProxy proxy = JSGlobalProxy::cast(*this);
JSGlobalObject global = proxy.GetIsolate()->context().global_object(); JSGlobalObject global = proxy.GetIsolate()->context().global_object();
return proxy.IsDetachedFrom(global); return proxy.IsDetachedFrom(global);
} }
return map().is_access_check_needed(); return map(isolate).is_access_check_needed();
} }
bool HeapObject::IsStruct() const { bool HeapObject::IsStruct(Isolate* isolate) const {
switch (map().instance_type()) { switch (map(isolate).instance_type()) {
#define MAKE_STRUCT_CASE(TYPE, Name, name) \ #define MAKE_STRUCT_CASE(TYPE, Name, name) \
case TYPE: \ case TYPE: \
return true; return true;
...@@ -398,6 +472,10 @@ bool HeapObject::IsStruct() const { ...@@ -398,6 +472,10 @@ bool HeapObject::IsStruct() const {
bool Object::Is##Name() const { \ bool Object::Is##Name() const { \
return IsHeapObject() && HeapObject::cast(*this).Is##Name(); \ return IsHeapObject() && HeapObject::cast(*this).Is##Name(); \
} \ } \
bool Object::Is##Name(Isolate* isolate) const { \
return IsHeapObject() && HeapObject::cast(*this).Is##Name(isolate); \
} \
ISOLATELESS_GETTER(HeapObject, Is##Name, bool) \
TYPE_CHECKER(Name) TYPE_CHECKER(Name)
STRUCT_LIST(MAKE_STRUCT_PREDICATE) STRUCT_LIST(MAKE_STRUCT_PREDICATE)
#undef MAKE_STRUCT_PREDICATE #undef MAKE_STRUCT_PREDICATE
...@@ -659,7 +737,19 @@ ReadOnlyRoots HeapObject::GetReadOnlyRoots() const { ...@@ -659,7 +737,19 @@ ReadOnlyRoots HeapObject::GetReadOnlyRoots() const {
return ReadOnlyHeap::GetReadOnlyRoots(*this); return ReadOnlyHeap::GetReadOnlyRoots(*this);
} }
Map HeapObject::map() const { return map_word().ToMap(); } ReadOnlyRoots HeapObject::GetReadOnlyRoots(Isolate* isolate) const {
#ifdef V8_COMPRESS_POINTERS
return ReadOnlyRoots(isolate);
#else
return GetReadOnlyRoots();
#endif
}
ISOLATELESS_GETTER(HeapObject, map, Map)
Map HeapObject::map(Isolate* isolate) const {
return map_word(isolate).ToMap();
}
void HeapObject::set_map(Map value) { void HeapObject::set_map(Map value) {
if (!value.is_null()) { if (!value.is_null()) {
...@@ -717,7 +807,11 @@ ObjectSlot HeapObject::map_slot() const { ...@@ -717,7 +807,11 @@ ObjectSlot HeapObject::map_slot() const {
return ObjectSlot(MapField::address(*this)); return ObjectSlot(MapField::address(*this));
} }
MapWord HeapObject::map_word() const { return MapField::Relaxed_Load(*this); } ISOLATELESS_GETTER(HeapObject, map_word, MapWord)
MapWord HeapObject::map_word(Isolate* isolate) const {
return MapField::Relaxed_Load(isolate, *this);
}
void HeapObject::set_map_word(MapWord map_word) { void HeapObject::set_map_word(MapWord map_word) {
MapField::Relaxed_Store(*this, map_word); MapField::Relaxed_Store(*this, map_word);
......
...@@ -267,9 +267,13 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> { ...@@ -267,9 +267,13 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> {
constexpr Object() : TaggedImpl(kNullAddress) {} constexpr Object() : TaggedImpl(kNullAddress) {}
explicit constexpr Object(Address ptr) : TaggedImpl(ptr) {} 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) OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
HEAP_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 #undef IS_TYPE_FUNCTION_DECL
// Oddball checks are faster when they are raw pointer comparisons, so the // Oddball checks are faster when they are raw pointer comparisons, so the
...@@ -279,18 +283,17 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> { ...@@ -279,18 +283,17 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> {
V8_INLINE bool Is##Type(ReadOnlyRoots roots) const; \ V8_INLINE bool Is##Type(ReadOnlyRoots roots) const; \
V8_INLINE bool Is##Type() const; V8_INLINE bool Is##Type() const;
ODDBALL_LIST(IS_TYPE_FUNCTION_DECL) ODDBALL_LIST(IS_TYPE_FUNCTION_DECL)
IS_TYPE_FUNCTION_DECL(NullOrUndefined, /* unused */)
#undef IS_TYPE_FUNCTION_DECL #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 IsZero() const;
V8_INLINE bool IsNoSharedNameSentinel() const; V8_INLINE bool IsNoSharedNameSentinel() const;
enum class Conversion { kToNumber, kToNumeric }; 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) STRUCT_LIST(DECL_STRUCT_PREDICATE)
#undef DECL_STRUCT_PREDICATE #undef DECL_STRUCT_PREDICATE
...@@ -298,9 +301,6 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> { ...@@ -298,9 +301,6 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> {
V8_INLINE V8_INLINE
V8_WARN_UNUSED_RESULT static Maybe<bool> IsArray(Handle<Object> object); V8_WARN_UNUSED_RESULT static Maybe<bool> IsArray(Handle<Object> object);
V8_INLINE bool IsHashTableBase() const;
V8_INLINE bool IsSmallOrderedHashTable() const;
// Extract the number. // Extract the number.
inline double Number() const; inline double Number() const;
V8_INLINE bool IsNaN() const; V8_INLINE bool IsNaN() const;
......
...@@ -38,8 +38,8 @@ Handle<Object> Oddball::ToNumber(Isolate* isolate, Handle<Oddball> input) { ...@@ -38,8 +38,8 @@ Handle<Object> Oddball::ToNumber(Isolate* isolate, Handle<Oddball> input) {
return Handle<Object>(input->to_number(), isolate); return Handle<Object>(input->to_number(), isolate);
} }
bool HeapObject::IsBoolean() const { bool HeapObject::IsBoolean(Isolate* isolate) const {
return IsOddball() && return IsOddball(isolate) &&
((Oddball::cast(*this).kind() & Oddball::kNotBooleanMask) == 0); ((Oddball::cast(*this).kind() & Oddball::kNotBooleanMask) == 0);
} }
......
...@@ -105,9 +105,9 @@ CAST_ACCESSOR(UncompiledDataWithPreparseData) ...@@ -105,9 +105,9 @@ CAST_ACCESSOR(UncompiledDataWithPreparseData)
ACCESSORS(UncompiledDataWithPreparseData, preparse_data, PreparseData, ACCESSORS(UncompiledDataWithPreparseData, preparse_data, PreparseData,
kPreparseDataOffset) kPreparseDataOffset)
bool HeapObject::IsUncompiledData() const { bool HeapObject::IsUncompiledData(Isolate* isolate) const {
return IsUncompiledDataWithoutPreparseData() || return IsUncompiledDataWithoutPreparseData(isolate) ||
IsUncompiledDataWithPreparseData(); IsUncompiledDataWithPreparseData(isolate);
} }
OBJECT_CONSTRUCTORS_IMPL(InterpreterData, Struct) OBJECT_CONSTRUCTORS_IMPL(InterpreterData, Struct)
......
...@@ -147,16 +147,21 @@ STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) == ...@@ -147,16 +147,21 @@ STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) ==
STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag); STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
bool String::IsOneByteRepresentation() const { ISOLATELESS_GETTER(String, IsOneByteRepresentation, bool)
uint32_t type = map().instance_type();
bool String::IsOneByteRepresentation(Isolate* isolate) const {
uint32_t type = map(isolate).instance_type();
return (type & kStringEncodingMask) == kOneByteStringTag; return (type & kStringEncodingMask) == kOneByteStringTag;
} }
bool String::IsTwoByteRepresentation() const { ISOLATELESS_GETTER(String, IsTwoByteRepresentation, bool)
uint32_t type = map().instance_type();
bool String::IsTwoByteRepresentation(Isolate* isolate) const {
uint32_t type = map(isolate).instance_type();
return (type & kStringEncodingMask) == kTwoByteStringTag; return (type & kStringEncodingMask) == kTwoByteStringTag;
} }
// static
bool String::IsOneByteRepresentationUnderneath(String string) { bool String::IsOneByteRepresentationUnderneath(String string) {
while (true) { while (true) {
uint32_t type = string.map().instance_type(); uint32_t type = string.map().instance_type();
......
...@@ -166,7 +166,9 @@ class String : public Name { ...@@ -166,7 +166,9 @@ class String : public Name {
// two-byte. Such strings may appear when the embedder prefers // two-byte. Such strings may appear when the embedder prefers
// two-byte external representations even for one-byte data. // two-byte external representations even for one-byte data.
inline bool IsOneByteRepresentation() const; inline bool IsOneByteRepresentation() const;
inline bool IsOneByteRepresentation(Isolate* isolate) const;
inline bool IsTwoByteRepresentation() const; inline bool IsTwoByteRepresentation() const;
inline bool IsTwoByteRepresentation(Isolate* isolate) const;
// Cons and slices have an encoding flag that may not represent the actual // Cons and slices have an encoding flag that may not represent the actual
// encoding of the underlying string. This is taken into account here. // 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