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) \
......
......@@ -66,30 +66,38 @@ int PropertyDetails::field_width_in_words() const {
return representation().IsDouble() ? kDoubleSize / kTaggedSize : 1;
}
bool HeapObject::IsSloppyArgumentsElements() const {
return IsFixedArrayExact();
bool HeapObject::IsSloppyArgumentsElements(Isolate* isolate) const {
return IsFixedArrayExact(isolate);
}
bool HeapObject::IsJSSloppyArgumentsObject() const {
return IsJSArgumentsObject();
bool HeapObject::IsJSSloppyArgumentsObject(Isolate* isolate) const {
return IsJSArgumentsObject(isolate);
}
bool HeapObject::IsJSGeneratorObject() const {
return map().instance_type() == JS_GENERATOR_OBJECT_TYPE ||
IsJSAsyncFunctionObject() || IsJSAsyncGeneratorObject();
bool HeapObject::IsJSGeneratorObject(Isolate* isolate) const {
return map(isolate).instance_type() == JS_GENERATOR_OBJECT_TYPE ||
IsJSAsyncFunctionObject(isolate) || IsJSAsyncGeneratorObject(isolate);
}
bool HeapObject::IsDataHandler() const {
return IsLoadHandler() || IsStoreHandler();
bool HeapObject::IsDataHandler(Isolate* isolate) const {
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_) \
bool Object::Is##type_() const { \
return IsHeapObject() && HeapObject::cast(*this).Is##type_(); \
}
#define IS_TYPE_FUNCTION_DEF(type_) \
bool Object::Is##type_() const { \
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)
IS_TYPE_FUNCTION_DEF(HashTableBase)
IS_TYPE_FUNCTION_DEF(SmallOrderedHashTable)
#undef IS_TYPE_FUNCTION_DEF
#define IS_TYPE_FUNCTION_DEF(Type, Value) \
......@@ -142,123 +150,168 @@ bool HeapObject::IsNullOrUndefined() const {
return IsNullOrUndefined(GetReadOnlyRoots());
}
bool HeapObject::IsUniqueName() const {
return IsInternalizedString() || IsSymbol();
bool HeapObject::IsUniqueName(Isolate* isolate) const {
return IsInternalizedString(isolate) || IsSymbol(isolate);
}
bool HeapObject::IsFunction() const {
bool HeapObject::IsFunction(Isolate* isolate) const {
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 {
return IsCallable() && IsJSProxy();
bool HeapObject::IsCallableJSProxy(Isolate* isolate) const {
return IsCallable(isolate) && IsJSProxy(isolate);
}
bool HeapObject::IsCallableApiObject() const {
InstanceType type = map().instance_type();
return IsCallable() &&
bool HeapObject::IsCallableApiObject(Isolate* isolate) const {
InstanceType type = map(isolate).instance_type();
return IsCallable(isolate) &&
(type == JS_API_OBJECT_TYPE || type == JS_SPECIAL_API_OBJECT_TYPE);
}
bool HeapObject::IsNonNullForeign() const {
return IsForeign() && Foreign::cast(*this).foreign_address() != kNullAddress;
bool HeapObject::IsNonNullForeign(Isolate* isolate) const {
return IsForeign(isolate) &&
Foreign::cast(*this).foreign_address() != kNullAddress;
}
bool HeapObject::IsConstructor() const { return map().is_constructor(); }
bool HeapObject::IsConstructor(Isolate* isolate) const {
return map(isolate).is_constructor();
}
bool HeapObject::IsSourceTextModuleInfo() const {
return map() == GetReadOnlyRoots().module_info_map();
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::IsTemplateInfo() const {
return IsObjectTemplateInfo() || IsFunctionTemplateInfo();
bool HeapObject::IsTemplateInfo(Isolate* isolate) const {
return IsObjectTemplateInfo(isolate) || IsFunctionTemplateInfo(isolate);
}
bool HeapObject::IsConsString() const {
if (!IsString()) return false;
return StringShape(String::cast(*this)).IsCons();
bool HeapObject::IsConsString(Isolate* isolate) const {
if (!IsString(isolate)) return false;
return StringShape(String::cast(*this).map(isolate)).IsCons();
}
bool HeapObject::IsThinString() const {
if (!IsString()) return false;
return StringShape(String::cast(*this)).IsThin();
bool HeapObject::IsThinString(Isolate* isolate) const {
if (!IsString(isolate)) return false;
return StringShape(String::cast(*this).map(isolate)).IsThin();
}
bool HeapObject::IsSlicedString() const {
if (!IsString()) return false;
return StringShape(String::cast(*this)).IsSliced();
bool HeapObject::IsSlicedString(Isolate* isolate) const {
if (!IsString(isolate)) return false;
return StringShape(String::cast(*this).map(isolate)).IsSliced();
}
bool HeapObject::IsSeqString() const {
if (!IsString()) return false;
return StringShape(String::cast(*this)).IsSequential();
bool HeapObject::IsSeqString(Isolate* isolate) const {
if (!IsString(isolate)) return false;
return StringShape(String::cast(*this).map(isolate)).IsSequential();
}
bool HeapObject::IsSeqOneByteString() const {
if (!IsString()) return false;
return StringShape(String::cast(*this)).IsSequential() &&
String::cast(*this).IsOneByteRepresentation();
bool HeapObject::IsSeqOneByteString(Isolate* isolate) const {
if (!IsString(isolate)) return false;
return StringShape(String::cast(*this).map(isolate)).IsSequential() &&
String::cast(*this).IsOneByteRepresentation(isolate);
}
bool HeapObject::IsSeqTwoByteString() const {
if (!IsString()) return false;
return StringShape(String::cast(*this)).IsSequential() &&
String::cast(*this).IsTwoByteRepresentation();
bool HeapObject::IsSeqTwoByteString(Isolate* isolate) const {
if (!IsString(isolate)) return false;
return StringShape(String::cast(*this).map(isolate)).IsSequential() &&
String::cast(*this).IsTwoByteRepresentation(isolate);
}
bool HeapObject::IsExternalString() const {
if (!IsString()) return false;
return StringShape(String::cast(*this)).IsExternal();
bool HeapObject::IsExternalString(Isolate* isolate) const {
if (!IsString(isolate)) return false;
return StringShape(String::cast(*this).map(isolate)).IsExternal();
}
bool HeapObject::IsExternalOneByteString() const {
if (!IsString()) return false;
return StringShape(String::cast(*this)).IsExternal() &&
String::cast(*this).IsOneByteRepresentation();
bool HeapObject::IsExternalOneByteString(Isolate* isolate) const {
if (!IsString(isolate)) return false;
return StringShape(String::cast(*this).map(isolate)).IsExternal() &&
String::cast(*this).IsOneByteRepresentation(isolate);
}
bool HeapObject::IsExternalTwoByteString() const {
if (!IsString()) return false;
return StringShape(String::cast(*this)).IsExternal() &&
String::cast(*this).IsTwoByteRepresentation();
bool HeapObject::IsExternalTwoByteString(Isolate* isolate) const {
if (!IsString(isolate)) return false;
return StringShape(String::cast(*this).map(isolate)).IsExternal() &&
String::cast(*this).IsTwoByteRepresentation(isolate);
}
bool Object::IsNumber() const { return IsSmi() || IsHeapNumber(); }
bool Object::IsNumber() const {
if (IsSmi()) return true;
HeapObject this_heap_object = HeapObject::cast(*this);
Isolate* isolate = GetIsolateForPtrCompr(this_heap_object);
return this_heap_object.IsHeapNumber(isolate);
}
bool Object::IsNumeric() const { return IsNumber() || IsBigInt(); }
bool Object::IsNumber(Isolate* isolate) const {
return IsSmi() || IsHeapNumber(isolate);
}
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 HeapObject::IsFiller() const {
InstanceType instance_type = map().instance_type();
bool Object::IsNumeric(Isolate* isolate) const {
return IsNumber(isolate) || IsBigInt(isolate);
}
bool HeapObject::IsFiller(Isolate* isolate) const {
InstanceType instance_type = map(isolate).instance_type();
return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
}
bool HeapObject::IsJSWeakCollection() const {
return IsJSWeakMap() || IsJSWeakSet();
bool HeapObject::IsJSWeakCollection(Isolate* isolate) const {
return IsJSWeakMap(isolate) || IsJSWeakSet(isolate);
}
bool HeapObject::IsJSCollection(Isolate* isolate) const {
return IsJSMap(isolate) || IsJSSet(isolate);
}
bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); }
bool HeapObject::IsPromiseReactionJobTask(Isolate* isolate) const {
return IsPromiseFulfillReactionJobTask(isolate) ||
IsPromiseRejectReactionJobTask(isolate);
}
bool HeapObject::IsPromiseReactionJobTask() const {
return IsPromiseFulfillReactionJobTask() || IsPromiseRejectReactionJobTask();
bool HeapObject::IsFrameArray(Isolate* isolate) const {
return IsFixedArrayExact(isolate);
}
bool HeapObject::IsFrameArray() const { return IsFixedArrayExact(); }
bool HeapObject::IsArrayList(Isolate* isolate) const {
// Can't use ReadOnlyRoots(isolate) as this isolate could be produced by
// i::GetIsolateForPtrCompr(HeapObject).
ReadOnlyRoots roots = GetReadOnlyRoots(isolate);
return *this == roots.empty_fixed_array() ||
map(isolate) == roots.array_list_map();
}
bool HeapObject::IsArrayList() const {
return map() == GetReadOnlyRoots().array_list_map() ||
*this == GetReadOnlyRoots().empty_fixed_array();
bool HeapObject::IsRegExpMatchInfo(Isolate* isolate) const {
return IsFixedArrayExact(isolate);
}
bool HeapObject::IsRegExpMatchInfo() const { return IsFixedArrayExact(); }
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.
if (!IsFixedArrayExact()) return false;
if (!IsFixedArrayExact(isolate)) return false;
// 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
......@@ -271,83 +324,102 @@ bool HeapObject::IsDeoptimizationData() const {
return length >= 0 && length % DeoptimizationData::kDeoptEntrySize == 0;
}
bool HeapObject::IsHandlerTable() const {
if (!IsFixedArrayExact()) return false;
bool HeapObject::IsHandlerTable(Isolate* isolate) const {
if (!IsFixedArrayExact(isolate)) return false;
// There's actually no way to see the difference between a fixed array and
// a handler table array.
return true;
}
bool HeapObject::IsTemplateList() const {
if (!IsFixedArrayExact()) return false;
bool HeapObject::IsTemplateList(Isolate* isolate) const {
if (!IsFixedArrayExact(isolate)) return false;
// There's actually no way to see the difference between a fixed array and
// a template list.
if (FixedArray::cast(*this).length() < 1) return false;
return true;
}
bool HeapObject::IsDependentCode() const {
if (!IsWeakFixedArray()) return false;
bool HeapObject::IsDependentCode(Isolate* isolate) const {
if (!IsWeakFixedArray(isolate)) return false;
// There's actually no way to see the difference between a weak fixed array
// and a dependent codes array.
return true;
}
bool HeapObject::IsAbstractCode() const {
return IsBytecodeArray() || IsCode();
bool HeapObject::IsAbstractCode(Isolate* isolate) const {
return IsBytecodeArray(isolate) || IsCode(isolate);
}
bool HeapObject::IsStringWrapper() const {
return IsJSValue() && JSValue::cast(*this).value().IsString();
bool HeapObject::IsStringWrapper(Isolate* isolate) const {
return IsJSValue(isolate) && JSValue::cast(*this).value().IsString(isolate);
}
bool HeapObject::IsBooleanWrapper() const {
return IsJSValue() && JSValue::cast(*this).value().IsBoolean();
bool HeapObject::IsBooleanWrapper(Isolate* isolate) const {
return IsJSValue(isolate) && JSValue::cast(*this).value().IsBoolean(isolate);
}
bool HeapObject::IsScriptWrapper() const {
return IsJSValue() && JSValue::cast(*this).value().IsScript();
bool HeapObject::IsScriptWrapper(Isolate* isolate) const {
return IsJSValue(isolate) && JSValue::cast(*this).value().IsScript(isolate);
}
bool HeapObject::IsNumberWrapper() const {
return IsJSValue() && JSValue::cast(*this).value().IsNumber();
bool HeapObject::IsNumberWrapper(Isolate* isolate) const {
return IsJSValue(isolate) && JSValue::cast(*this).value().IsNumber(isolate);
}
bool HeapObject::IsBigIntWrapper() const {
return IsJSValue() && JSValue::cast(*this).value().IsBigInt();
bool HeapObject::IsBigIntWrapper(Isolate* isolate) const {
return IsJSValue(isolate) && JSValue::cast(*this).value().IsBigInt(isolate);
}
bool HeapObject::IsSymbolWrapper() const {
return IsJSValue() && JSValue::cast(*this).value().IsSymbol();
bool HeapObject::IsSymbolWrapper(Isolate* isolate) const {
return IsJSValue(isolate) && JSValue::cast(*this).value().IsSymbol(isolate);
}
bool HeapObject::IsJSArrayBufferView() const {
return IsJSDataView() || IsJSTypedArray();
bool HeapObject::IsJSArrayBufferView(Isolate* isolate) const {
return IsJSDataView(isolate) || IsJSTypedArray(isolate);
}
bool HeapObject::IsJSCollectionIterator() const {
return IsJSMapIterator() || IsJSSetIterator();
bool HeapObject::IsJSCollectionIterator(Isolate* isolate) const {
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 {
return IsSmallOrderedHashSet() || IsSmallOrderedHashMap() ||
IsSmallOrderedNameDictionary();
bool HeapObject::IsSmallOrderedHashTable(Isolate* isolate) const {
return IsSmallOrderedHashSet(isolate) || IsSmallOrderedHashMap(isolate) ||
IsSmallOrderedNameDictionary(isolate);
}
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
......@@ -359,19 +431,21 @@ Maybe<bool> Object::IsArray(Handle<Object> 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 {
if (IsJSGlobalProxy()) {
bool HeapObject::IsAccessCheckNeeded(Isolate* isolate) const {
if (IsJSGlobalProxy(isolate)) {
const JSGlobalProxy proxy = JSGlobalProxy::cast(*this);
JSGlobalObject global = proxy.GetIsolate()->context().global_object();
return proxy.IsDetachedFrom(global);
}
return map().is_access_check_needed();
return map(isolate).is_access_check_needed();
}
bool HeapObject::IsStruct() const {
switch (map().instance_type()) {
bool HeapObject::IsStruct(Isolate* isolate) const {
switch (map(isolate).instance_type()) {
#define MAKE_STRUCT_CASE(TYPE, Name, name) \
case TYPE: \
return true;
......@@ -394,10 +468,14 @@ bool HeapObject::IsStruct() const {
}
}
#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
bool Object::Is##Name() const { \
return IsHeapObject() && HeapObject::cast(*this).Is##Name(); \
} \
#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
bool Object::Is##Name() const { \
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)
STRUCT_LIST(MAKE_STRUCT_PREDICATE)
#undef MAKE_STRUCT_PREDICATE
......@@ -659,7 +737,19 @@ ReadOnlyRoots HeapObject::GetReadOnlyRoots() const {
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) {
if (!value.is_null()) {
......@@ -717,7 +807,11 @@ ObjectSlot HeapObject::map_slot() const {
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) {
MapField::Relaxed_Store(*this, map_word);
......
......@@ -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