Commit c0282f60 authored by cbruni's avatar cbruni Committed by Commit bot

Add unittests to keep InstanceType lists in sync

STRUCT_LIST and INSTANCE_TYPE_LIST are now forced to have the same order
as the InstanceType enum.

Drive-by-fix 1: Move type check and cast functions closer together in objects-inl.h

Drive-by-fix 2: Remove unused instance types SIGNATURE_INFO_TYPE and  TYPE_SWITCH_INFO_TYPE.

BUG=

Review-Url: https://codereview.chromium.org/2578573002
Cr-Commit-Position: refs/heads/master@{#41804}
parent 99a5aa1b
......@@ -8380,8 +8380,8 @@ class Internals {
static const int kNodeIsIndependentShift = 3;
static const int kNodeIsActiveShift = 4;
static const int kJSObjectType = 0xbe;
static const int kJSApiObjectType = 0xbd;
static const int kJSApiObjectType = 0xbb;
static const int kJSObjectType = 0xbc;
static const int kFirstNonstringType = 0x80;
static const int kOddballType = 0x83;
static const int kForeignType = 0x87;
......
......@@ -303,8 +303,6 @@ AstType::bitset AstBitsetType::Lub(i::Map* map) {
case PROMISE_REACTION_JOB_INFO_TYPE:
case FUNCTION_TEMPLATE_INFO_TYPE:
case OBJECT_TEMPLATE_INFO_TYPE:
case SIGNATURE_INFO_TYPE:
case TYPE_SWITCH_INFO_TYPE:
case ALLOCATION_MEMENTO_TYPE:
case TYPE_FEEDBACK_INFO_TYPE:
case ALIASED_ARGUMENTS_ENTRY_TYPE:
......
......@@ -310,8 +310,6 @@ Type::bitset BitsetType::Lub(i::Map* map) {
case INTERCEPTOR_INFO_TYPE:
case CALL_HANDLER_INFO_TYPE:
case OBJECT_TEMPLATE_INFO_TYPE:
case SIGNATURE_INFO_TYPE:
case TYPE_SWITCH_INFO_TYPE:
case ALLOCATION_MEMENTO_TYPE:
case TYPE_FEEDBACK_INFO_TYPE:
case ALIASED_ARGUMENTS_ENTRY_TYPE:
......
......@@ -59,22 +59,6 @@ int PropertyDetails::field_width_in_words() const {
return representation().IsDouble() ? kDoubleSize / kPointerSize : 1;
}
#define TYPE_CHECKER(type, instancetype) \
bool HeapObject::Is##type() const { \
return map()->instance_type() == instancetype; \
}
#define CAST_ACCESSOR(type) \
type* type::cast(Object* object) { \
SLOW_DCHECK(object->Is##type()); \
return reinterpret_cast<type*>(object); \
} \
const type* type::cast(const Object* object) { \
SLOW_DCHECK(object->Is##type()); \
return reinterpret_cast<const type*>(object); \
}
#define INT_ACCESSORS(holder, name, offset) \
int holder::name() const { return READ_INT_FIELD(this, offset); } \
void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
......@@ -140,6 +124,60 @@ int PropertyDetails::field_width_in_words() const {
set_##field(BooleanBit::set(field(), offset, value)); \
}
#define TYPE_CHECKER(type, instancetype) \
bool HeapObject::Is##type() const { \
return map()->instance_type() == instancetype; \
}
TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
TYPE_CHECKER(BytecodeArray, BYTECODE_ARRAY_TYPE)
TYPE_CHECKER(Cell, CELL_TYPE)
TYPE_CHECKER(Code, CODE_TYPE)
TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
TYPE_CHECKER(Foreign, FOREIGN_TYPE)
TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE)
TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
TYPE_CHECKER(JSBoundFunction, JS_BOUND_FUNCTION_TYPE)
TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE)
TYPE_CHECKER(JSDate, JS_DATE_TYPE)
TYPE_CHECKER(JSError, JS_ERROR_TYPE)
TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE)
TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
TYPE_CHECKER(JSMapIterator, JS_MAP_ITERATOR_TYPE)
TYPE_CHECKER(JSMap, JS_MAP_TYPE)
TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
TYPE_CHECKER(JSModuleNamespace, JS_MODULE_NAMESPACE_TYPE)
TYPE_CHECKER(JSPromise, JS_PROMISE_TYPE)
TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE)
TYPE_CHECKER(JSSet, JS_SET_TYPE)
TYPE_CHECKER(JSStringIterator, JS_STRING_ITERATOR_TYPE)
TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE)
TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE)
TYPE_CHECKER(Map, MAP_TYPE)
TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE)
TYPE_CHECKER(Oddball, ODDBALL_TYPE)
TYPE_CHECKER(PropertyCell, PROPERTY_CELL_TYPE)
TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
TYPE_CHECKER(Simd128Value, SIMD128_VALUE_TYPE)
TYPE_CHECKER(Symbol, SYMBOL_TYPE)
TYPE_CHECKER(TransitionArray, TRANSITION_ARRAY_TYPE)
TYPE_CHECKER(WeakCell, WEAK_CELL_TYPE)
TYPE_CHECKER(WeakFixedArray, FIXED_ARRAY_TYPE)
#define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype, size) \
TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE)
TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER)
#undef TYPED_ARRAY_TYPE_CHECKER
#undef TYPE_CHECKER
bool HeapObject::IsFixedArrayBase() const {
return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase();
}
......@@ -150,18 +188,11 @@ bool HeapObject::IsFixedArray() const {
instance_type == TRANSITION_ARRAY_TYPE;
}
// External objects are not extensible, so the map check is enough.
bool HeapObject::IsExternal() const {
return map() == GetHeap()->external_map();
}
TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE)
TYPE_CHECKER(Symbol, SYMBOL_TYPE)
TYPE_CHECKER(Simd128Value, SIMD128_VALUE_TYPE)
#define SIMD128_TYPE_CHECKER(TYPE, Type, type, lane_count, lane_type) \
bool HeapObject::Is##Type() const { return map() == GetHeap()->type##_map(); }
SIMD128_TYPES(SIMD128_TYPE_CHECKER)
......@@ -266,741 +297,738 @@ bool HeapObject::IsExternalTwoByteString() const {
String::cast(this)->IsTwoByteRepresentation();
}
bool Object::HasValidElements() {
// Dictionary is covered under FixedArray.
return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase();
}
bool Object::IsNumber() const { return IsSmi() || IsHeapNumber(); }
bool Object::KeyEquals(Object* second) {
Object* first = this;
if (second->IsNumber()) {
if (first->IsNumber()) return first->Number() == second->Number();
Object* temp = first;
first = second;
second = temp;
}
if (first->IsNumber()) {
DCHECK_LE(0, first->Number());
uint32_t expected = static_cast<uint32_t>(first->Number());
uint32_t index;
return Name::cast(second)->AsArrayIndex(&index) && index == expected;
}
return Name::cast(first)->Equals(Name::cast(second));
bool HeapObject::IsFiller() const {
InstanceType instance_type = map()->instance_type();
return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
}
bool Object::FilterKey(PropertyFilter filter) {
if (IsSymbol()) {
if (filter & SKIP_SYMBOLS) return true;
if (Symbol::cast(this)->is_private()) return true;
} else {
if (filter & SKIP_STRINGS) return true;
}
return false;
bool HeapObject::IsFixedTypedArrayBase() const {
InstanceType instance_type = map()->instance_type();
return (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE);
}
Handle<Object> Object::NewStorageFor(Isolate* isolate,
Handle<Object> object,
Representation representation) {
if (representation.IsSmi() && object->IsUninitialized(isolate)) {
return handle(Smi::kZero, isolate);
}
if (!representation.IsDouble()) return object;
double value;
if (object->IsUninitialized(isolate)) {
value = 0;
} else if (object->IsMutableHeapNumber()) {
value = HeapNumber::cast(*object)->value();
} else {
value = object->Number();
}
return isolate->factory()->NewHeapNumber(value, MUTABLE);
bool HeapObject::IsJSReceiver() const {
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
return map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
}
Handle<Object> Object::WrapForRead(Isolate* isolate,
Handle<Object> object,
Representation representation) {
DCHECK(!object->IsUninitialized(isolate));
if (!representation.IsDouble()) {
DCHECK(object->FitsRepresentation(representation));
return object;
}
return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value());
bool HeapObject::IsJSObject() const {
STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
return map()->IsJSObjectMap();
}
bool HeapObject::IsJSProxy() const { return map()->IsJSProxyMap(); }
StringShape::StringShape(const String* str)
: type_(str->map()->instance_type()) {
set_valid();
DCHECK((type_ & kIsNotStringMask) == kStringTag);
bool HeapObject::IsJSArrayIterator() const {
InstanceType instance_type = map()->instance_type();
return (instance_type >= FIRST_ARRAY_ITERATOR_TYPE &&
instance_type <= LAST_ARRAY_ITERATOR_TYPE);
}
StringShape::StringShape(Map* map)
: type_(map->instance_type()) {
set_valid();
DCHECK((type_ & kIsNotStringMask) == kStringTag);
bool HeapObject::IsJSWeakCollection() const {
return IsJSWeakMap() || IsJSWeakSet();
}
bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); }
StringShape::StringShape(InstanceType t)
: type_(static_cast<uint32_t>(t)) {
set_valid();
DCHECK((type_ & kIsNotStringMask) == kStringTag);
}
bool HeapObject::IsDescriptorArray() const { return IsFixedArray(); }
bool HeapObject::IsFrameArray() const { return IsFixedArray(); }
bool StringShape::IsInternalized() {
DCHECK(valid());
STATIC_ASSERT(kNotInternalizedTag != 0);
return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) ==
(kStringTag | kInternalizedTag);
}
bool HeapObject::IsArrayList() const { return IsFixedArray(); }
bool HeapObject::IsRegExpMatchInfo() const { return IsFixedArray(); }
bool String::IsOneByteRepresentation() const {
uint32_t type = map()->instance_type();
return (type & kStringEncodingMask) == kOneByteStringTag;
bool Object::IsLayoutDescriptor() const {
return IsSmi() || IsFixedTypedArrayBase();
}
bool HeapObject::IsTypeFeedbackVector() const { return IsFixedArray(); }
bool String::IsTwoByteRepresentation() const {
uint32_t type = map()->instance_type();
return (type & kStringEncodingMask) == kTwoByteStringTag;
}
bool HeapObject::IsTypeFeedbackMetadata() const { return IsFixedArray(); }
bool HeapObject::IsLiteralsArray() const { return IsFixedArray(); }
bool String::IsOneByteRepresentationUnderneath() {
uint32_t type = map()->instance_type();
STATIC_ASSERT(kIsIndirectStringTag != 0);
STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
DCHECK(IsFlat());
switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
case kOneByteStringTag:
return true;
case kTwoByteStringTag:
return false;
default: // Cons or sliced string. Need to go deeper.
return GetUnderlying()->IsOneByteRepresentation();
}
}
bool HeapObject::IsDeoptimizationInputData() const {
// Must be a fixed array.
if (!IsFixedArray()) 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
// check that the length is zero or else the fixed size plus a multiple of
// the entry size.
int length = FixedArray::cast(this)->length();
if (length == 0) return true;
bool String::IsTwoByteRepresentationUnderneath() {
uint32_t type = map()->instance_type();
STATIC_ASSERT(kIsIndirectStringTag != 0);
STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
DCHECK(IsFlat());
switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
case kOneByteStringTag:
return false;
case kTwoByteStringTag:
return true;
default: // Cons or sliced string. Need to go deeper.
return GetUnderlying()->IsTwoByteRepresentation();
}
length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
return length >= 0 && length % DeoptimizationInputData::kDeoptEntrySize == 0;
}
bool String::HasOnlyOneByteChars() {
uint32_t type = map()->instance_type();
return (type & kOneByteDataHintMask) == kOneByteDataHintTag ||
IsOneByteRepresentation();
bool HeapObject::IsDeoptimizationOutputData() const {
if (!IsFixedArray()) return false;
// There's actually no way to see the difference between a fixed array and
// a deoptimization data array. Since this is used for asserts we can check
// that the length is plausible though.
if (FixedArray::cast(this)->length() % 2 != 0) return false;
return true;
}
bool StringShape::IsCons() {
return (type_ & kStringRepresentationMask) == kConsStringTag;
bool HeapObject::IsHandlerTable() const {
if (!IsFixedArray()) return false;
// There's actually no way to see the difference between a fixed array and
// a handler table array.
return true;
}
bool StringShape::IsSliced() {
return (type_ & kStringRepresentationMask) == kSlicedStringTag;
bool HeapObject::IsTemplateList() const {
if (!IsFixedArray()) 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 StringShape::IsIndirect() {
return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
bool HeapObject::IsDependentCode() const {
if (!IsFixedArray()) return false;
// There's actually no way to see the difference between a fixed array and
// a dependent codes array.
return true;
}
bool StringShape::IsExternal() {
return (type_ & kStringRepresentationMask) == kExternalStringTag;
bool HeapObject::IsContext() const {
Map* map = this->map();
Heap* heap = GetHeap();
return (
map == heap->function_context_map() || map == heap->catch_context_map() ||
map == heap->with_context_map() || map == heap->native_context_map() ||
map == heap->block_context_map() || map == heap->module_context_map() ||
map == heap->script_context_map() ||
map == heap->debug_evaluate_context_map());
}
bool StringShape::IsSequential() {
return (type_ & kStringRepresentationMask) == kSeqStringTag;
bool HeapObject::IsNativeContext() const {
return map() == GetHeap()->native_context_map();
}
StringRepresentationTag StringShape::representation_tag() {
uint32_t tag = (type_ & kStringRepresentationMask);
return static_cast<StringRepresentationTag>(tag);
bool HeapObject::IsScriptContextTable() const {
return map() == GetHeap()->script_context_table_map();
}
uint32_t StringShape::encoding_tag() {
return type_ & kStringEncodingMask;
bool HeapObject::IsScopeInfo() const {
return map() == GetHeap()->scope_info_map();
}
uint32_t StringShape::full_representation_tag() {
return (type_ & (kStringRepresentationMask | kStringEncodingMask));
bool HeapObject::IsModuleInfo() const {
return map() == GetHeap()->module_info_map();
}
STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) ==
Internals::kFullStringRepresentationMask);
STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) ==
Internals::kStringEncodingMask);
bool StringShape::IsSequentialOneByte() {
return full_representation_tag() == (kSeqStringTag | kOneByteStringTag);
template <>
inline bool Is<JSFunction>(Object* obj) {
return obj->IsJSFunction();
}
bool StringShape::IsSequentialTwoByte() {
return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
bool HeapObject::IsAbstractCode() const {
return IsBytecodeArray() || IsCode();
}
bool HeapObject::IsStringWrapper() const {
return IsJSValue() && JSValue::cast(this)->value()->IsString();
}
bool StringShape::IsExternalOneByte() {
return full_representation_tag() == (kExternalStringTag | kOneByteStringTag);
bool HeapObject::IsBoolean() const {
return IsOddball() &&
((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
}
bool HeapObject::IsJSArrayBufferView() const {
return IsJSDataView() || IsJSTypedArray();
}
STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) ==
Internals::kExternalOneByteRepresentationTag);
template <>
inline bool Is<JSArray>(Object* obj) {
return obj->IsJSArray();
}
STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag);
bool HeapObject::IsHashTable() const {
return map() == GetHeap()->hash_table_map();
}
bool HeapObject::IsWeakHashTable() const { return IsHashTable(); }
bool StringShape::IsExternalTwoByte() {
return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
bool HeapObject::IsDictionary() const {
return IsHashTable() && this != GetHeap()->string_table();
}
bool Object::IsNameDictionary() const { return IsDictionary(); }
STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) ==
Internals::kExternalTwoByteRepresentationTag);
STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
bool Object::IsGlobalDictionary() const { return IsDictionary(); }
bool Object::IsSeededNumberDictionary() const { return IsDictionary(); }
uc32 FlatStringReader::Get(int index) {
if (is_one_byte_) {
return Get<uint8_t>(index);
} else {
return Get<uc16>(index);
}
bool HeapObject::IsUnseededNumberDictionary() const {
return map() == GetHeap()->unseeded_number_dictionary_map();
}
bool HeapObject::IsStringTable() const { return IsHashTable(); }
template <typename Char>
Char FlatStringReader::Get(int index) {
DCHECK_EQ(is_one_byte_, sizeof(Char) == 1);
DCHECK(0 <= index && index <= length_);
if (sizeof(Char) == 1) {
return static_cast<Char>(static_cast<const uint8_t*>(start_)[index]);
} else {
return static_cast<Char>(static_cast<const uc16*>(start_)[index]);
}
}
bool HeapObject::IsStringSet() const { return IsHashTable(); }
bool HeapObject::IsObjectHashSet() const { return IsHashTable(); }
Handle<Object> StringTableShape::AsHandle(Isolate* isolate, HashTableKey* key) {
return key->AsHandle(isolate);
bool HeapObject::IsNormalizedMapCache() const {
return NormalizedMapCache::IsNormalizedMapCache(this);
}
Handle<Object> CompilationCacheShape::AsHandle(Isolate* isolate,
HashTableKey* key) {
return key->AsHandle(isolate);
int NormalizedMapCache::GetIndex(Handle<Map> map) {
return map->Hash() % NormalizedMapCache::kEntries;
}
Handle<Object> CodeCacheHashTableShape::AsHandle(Isolate* isolate,
HashTableKey* key) {
return key->AsHandle(isolate);
bool NormalizedMapCache::IsNormalizedMapCache(const HeapObject* obj) {
if (!obj->IsFixedArray()) return false;
if (FixedArray::cast(obj)->length() != NormalizedMapCache::kEntries) {
return false;
}
#ifdef VERIFY_HEAP
if (FLAG_verify_heap) {
reinterpret_cast<NormalizedMapCache*>(const_cast<HeapObject*>(obj))
->NormalizedMapCacheVerify();
}
#endif
return true;
}
template <typename Char>
class SequentialStringKey : public HashTableKey {
public:
explicit SequentialStringKey(Vector<const Char> string, uint32_t seed)
: string_(string), hash_field_(0), seed_(seed) { }
uint32_t Hash() override {
hash_field_ = StringHasher::HashSequentialString<Char>(string_.start(),
string_.length(),
seed_);
uint32_t result = hash_field_ >> String::kHashShift;
DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
return result;
}
bool HeapObject::IsCompilationCacheTable() const { return IsHashTable(); }
bool HeapObject::IsCodeCacheHashTable() const { return IsHashTable(); }
uint32_t HashForObject(Object* other) override {
return String::cast(other)->Hash();
}
bool HeapObject::IsMapCache() const { return IsHashTable(); }
Vector<const Char> string_;
uint32_t hash_field_;
uint32_t seed_;
};
bool HeapObject::IsObjectHashTable() const { return IsHashTable(); }
bool HeapObject::IsOrderedHashTable() const {
return map() == GetHeap()->ordered_hash_table_map();
}
class OneByteStringKey : public SequentialStringKey<uint8_t> {
public:
OneByteStringKey(Vector<const uint8_t> str, uint32_t seed)
: SequentialStringKey<uint8_t>(str, seed) { }
bool Object::IsOrderedHashSet() const { return IsOrderedHashTable(); }
bool IsMatch(Object* string) override {
return String::cast(string)->IsOneByteEqualTo(string_);
}
bool Object::IsOrderedHashMap() const { return IsOrderedHashTable(); }
Handle<Object> AsHandle(Isolate* isolate) override;
};
bool Object::IsPrimitive() const {
return IsSmi() || HeapObject::cast(this)->map()->IsPrimitiveMap();
}
bool HeapObject::IsJSGlobalProxy() const {
bool result = map()->instance_type() == JS_GLOBAL_PROXY_TYPE;
DCHECK(!result || map()->is_access_check_needed());
return result;
}
class SeqOneByteSubStringKey : public HashTableKey {
public:
SeqOneByteSubStringKey(Handle<SeqOneByteString> string, int from, int length)
: string_(string), from_(from), length_(length) {
DCHECK(string_->IsSeqOneByteString());
}
bool HeapObject::IsUndetectable() const { return map()->is_undetectable(); }
uint32_t Hash() override {
DCHECK(length_ >= 0);
DCHECK(from_ + length_ <= string_->length());
const uint8_t* chars = string_->GetChars() + from_;
hash_field_ = StringHasher::HashSequentialString(
chars, length_, string_->GetHeap()->HashSeed());
uint32_t result = hash_field_ >> String::kHashShift;
DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
return result;
bool HeapObject::IsAccessCheckNeeded() const {
if (IsJSGlobalProxy()) {
const JSGlobalProxy* proxy = JSGlobalProxy::cast(this);
JSGlobalObject* global = proxy->GetIsolate()->context()->global_object();
return proxy->IsDetachedFrom(global);
}
return map()->is_access_check_needed();
}
uint32_t HashForObject(Object* other) override {
return String::cast(other)->Hash();
bool HeapObject::IsStruct() const {
switch (map()->instance_type()) {
#define MAKE_STRUCT_CASE(NAME, Name, name) \
case NAME##_TYPE: \
return true;
STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
default:
return false;
}
}
bool IsMatch(Object* string) override;
Handle<Object> AsHandle(Isolate* isolate) override;
private:
Handle<SeqOneByteString> string_;
int from_;
int length_;
uint32_t hash_field_;
};
class TwoByteStringKey : public SequentialStringKey<uc16> {
public:
explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed)
: SequentialStringKey<uc16>(str, seed) { }
bool IsMatch(Object* string) override {
return String::cast(string)->IsTwoByteEqualTo(string_);
#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
bool Object::Is##Name() const { \
return IsHeapObject() && HeapObject::cast(this)->Is##Name(); \
} \
bool HeapObject::Is##Name() const { \
return map()->instance_type() == NAME##_TYPE; \
}
STRUCT_LIST(MAKE_STRUCT_PREDICATE)
#undef MAKE_STRUCT_PREDICATE
Handle<Object> AsHandle(Isolate* isolate) override;
};
double Object::Number() const {
DCHECK(IsNumber());
return IsSmi()
? static_cast<double>(reinterpret_cast<const Smi*>(this)->value())
: reinterpret_cast<const HeapNumber*>(this)->value();
}
bool Object::IsNaN() const {
return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value());
}
// Utf8StringKey carries a vector of chars as key.
class Utf8StringKey : public HashTableKey {
public:
explicit Utf8StringKey(Vector<const char> string, uint32_t seed)
: string_(string), hash_field_(0), seed_(seed) { }
bool Object::IsMinusZero() const {
return this->IsHeapNumber() &&
i::IsMinusZero(HeapNumber::cast(this)->value());
}
bool IsMatch(Object* string) override {
return String::cast(string)->IsUtf8EqualTo(string_);
}
// ------------------------------------
// Cast operations
uint32_t Hash() override {
if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
hash_field_ = StringHasher::ComputeUtf8Hash(string_, seed_, &chars_);
uint32_t result = hash_field_ >> String::kHashShift;
DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
return result;
#define CAST_ACCESSOR(type) \
type* type::cast(Object* object) { \
SLOW_DCHECK(object->Is##type()); \
return reinterpret_cast<type*>(object); \
} \
const type* type::cast(const Object* object) { \
SLOW_DCHECK(object->Is##type()); \
return reinterpret_cast<const type*>(object); \
}
uint32_t HashForObject(Object* other) override {
return String::cast(other)->Hash();
}
Handle<Object> AsHandle(Isolate* isolate) override {
if (hash_field_ == 0) Hash();
return isolate->factory()->NewInternalizedStringFromUtf8(
string_, chars_, hash_field_);
}
Vector<const char> string_;
uint32_t hash_field_;
int chars_; // Caches the number of characters when computing the hash code.
uint32_t seed_;
};
bool Object::IsNumber() const {
return IsSmi() || HeapObject::cast(this)->IsHeapNumber();
}
TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
TYPE_CHECKER(BytecodeArray, BYTECODE_ARRAY_TYPE)
TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
bool HeapObject::IsFiller() const {
InstanceType instance_type = map()->instance_type();
return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
}
CAST_ACCESSOR(AbstractCode)
CAST_ACCESSOR(ArrayList)
CAST_ACCESSOR(Bool16x8)
CAST_ACCESSOR(Bool32x4)
CAST_ACCESSOR(Bool8x16)
CAST_ACCESSOR(ByteArray)
CAST_ACCESSOR(BytecodeArray)
CAST_ACCESSOR(Cell)
CAST_ACCESSOR(Code)
CAST_ACCESSOR(CodeCacheHashTable)
CAST_ACCESSOR(CompilationCacheTable)
CAST_ACCESSOR(ConsString)
CAST_ACCESSOR(DeoptimizationInputData)
CAST_ACCESSOR(DeoptimizationOutputData)
CAST_ACCESSOR(DependentCode)
CAST_ACCESSOR(DescriptorArray)
CAST_ACCESSOR(ExternalOneByteString)
CAST_ACCESSOR(ExternalString)
CAST_ACCESSOR(ExternalTwoByteString)
CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(FixedArrayBase)
CAST_ACCESSOR(FixedDoubleArray)
CAST_ACCESSOR(FixedTypedArrayBase)
CAST_ACCESSOR(Float32x4)
CAST_ACCESSOR(Foreign)
CAST_ACCESSOR(FrameArray)
CAST_ACCESSOR(GlobalDictionary)
CAST_ACCESSOR(HandlerTable)
CAST_ACCESSOR(HeapObject)
CAST_ACCESSOR(Int16x8)
CAST_ACCESSOR(Int32x4)
CAST_ACCESSOR(Int8x16)
CAST_ACCESSOR(JSArray)
CAST_ACCESSOR(JSArrayBuffer)
CAST_ACCESSOR(JSArrayBufferView)
CAST_ACCESSOR(JSBoundFunction)
CAST_ACCESSOR(JSDataView)
CAST_ACCESSOR(JSDate)
CAST_ACCESSOR(JSFunction)
CAST_ACCESSOR(JSGeneratorObject)
CAST_ACCESSOR(JSGlobalObject)
CAST_ACCESSOR(JSGlobalProxy)
CAST_ACCESSOR(JSMap)
CAST_ACCESSOR(JSMapIterator)
CAST_ACCESSOR(JSMessageObject)
CAST_ACCESSOR(JSModuleNamespace)
CAST_ACCESSOR(JSObject)
CAST_ACCESSOR(JSProxy)
CAST_ACCESSOR(JSReceiver)
CAST_ACCESSOR(JSRegExp)
CAST_ACCESSOR(JSPromise)
CAST_ACCESSOR(JSSet)
CAST_ACCESSOR(JSSetIterator)
CAST_ACCESSOR(JSStringIterator)
CAST_ACCESSOR(JSArrayIterator)
CAST_ACCESSOR(JSTypedArray)
CAST_ACCESSOR(JSValue)
CAST_ACCESSOR(JSWeakCollection)
CAST_ACCESSOR(JSWeakMap)
CAST_ACCESSOR(JSWeakSet)
CAST_ACCESSOR(LayoutDescriptor)
CAST_ACCESSOR(Map)
CAST_ACCESSOR(ModuleInfo)
CAST_ACCESSOR(Name)
CAST_ACCESSOR(NameDictionary)
CAST_ACCESSOR(NormalizedMapCache)
CAST_ACCESSOR(Object)
CAST_ACCESSOR(ObjectHashTable)
CAST_ACCESSOR(ObjectHashSet)
CAST_ACCESSOR(Oddball)
CAST_ACCESSOR(OrderedHashMap)
CAST_ACCESSOR(OrderedHashSet)
CAST_ACCESSOR(PropertyCell)
CAST_ACCESSOR(TemplateList)
CAST_ACCESSOR(RegExpMatchInfo)
CAST_ACCESSOR(ScopeInfo)
CAST_ACCESSOR(SeededNumberDictionary)
CAST_ACCESSOR(SeqOneByteString)
CAST_ACCESSOR(SeqString)
CAST_ACCESSOR(SeqTwoByteString)
CAST_ACCESSOR(SharedFunctionInfo)
CAST_ACCESSOR(Simd128Value)
CAST_ACCESSOR(SlicedString)
CAST_ACCESSOR(Smi)
CAST_ACCESSOR(String)
CAST_ACCESSOR(StringSet)
CAST_ACCESSOR(StringTable)
CAST_ACCESSOR(Struct)
CAST_ACCESSOR(Symbol)
CAST_ACCESSOR(TemplateInfo)
CAST_ACCESSOR(Uint16x8)
CAST_ACCESSOR(Uint32x4)
CAST_ACCESSOR(Uint8x16)
CAST_ACCESSOR(UnseededNumberDictionary)
CAST_ACCESSOR(WeakCell)
CAST_ACCESSOR(WeakFixedArray)
CAST_ACCESSOR(WeakHashTable)
#define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype, size) \
TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE)
#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
STRUCT_LIST(MAKE_STRUCT_CAST)
#undef MAKE_STRUCT_CAST
TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER)
#undef TYPED_ARRAY_TYPE_CHECKER
#undef CAST_ACCESSOR
bool HeapObject::IsFixedTypedArrayBase() const {
InstanceType instance_type = map()->instance_type();
return (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE);
bool Object::HasValidElements() {
// Dictionary is covered under FixedArray.
return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase();
}
bool HeapObject::IsJSReceiver() const {
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
return map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
bool Object::KeyEquals(Object* second) {
Object* first = this;
if (second->IsNumber()) {
if (first->IsNumber()) return first->Number() == second->Number();
Object* temp = first;
first = second;
second = temp;
}
if (first->IsNumber()) {
DCHECK_LE(0, first->Number());
uint32_t expected = static_cast<uint32_t>(first->Number());
uint32_t index;
return Name::cast(second)->AsArrayIndex(&index) && index == expected;
}
return Name::cast(first)->Equals(Name::cast(second));
}
bool HeapObject::IsJSObject() const {
STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
return map()->IsJSObjectMap();
bool Object::FilterKey(PropertyFilter filter) {
if (IsSymbol()) {
if (filter & SKIP_SYMBOLS) return true;
if (Symbol::cast(this)->is_private()) return true;
} else {
if (filter & SKIP_STRINGS) return true;
}
return false;
}
bool HeapObject::IsJSProxy() const { return map()->IsJSProxyMap(); }
bool HeapObject::IsJSArrayIterator() const {
InstanceType instance_type = map()->instance_type();
return (instance_type >= FIRST_ARRAY_ITERATOR_TYPE &&
instance_type <= LAST_ARRAY_ITERATOR_TYPE);
Handle<Object> Object::NewStorageFor(Isolate* isolate, Handle<Object> object,
Representation representation) {
if (representation.IsSmi() && object->IsUninitialized(isolate)) {
return handle(Smi::kZero, isolate);
}
if (!representation.IsDouble()) return object;
double value;
if (object->IsUninitialized(isolate)) {
value = 0;
} else if (object->IsMutableHeapNumber()) {
value = HeapNumber::cast(*object)->value();
} else {
value = object->Number();
}
return isolate->factory()->NewHeapNumber(value, MUTABLE);
}
TYPE_CHECKER(JSSet, JS_SET_TYPE)
TYPE_CHECKER(JSMap, JS_MAP_TYPE)
TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE)
TYPE_CHECKER(JSMapIterator, JS_MAP_ITERATOR_TYPE)
TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE)
TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
TYPE_CHECKER(Map, MAP_TYPE)
TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
TYPE_CHECKER(WeakFixedArray, FIXED_ARRAY_TYPE)
TYPE_CHECKER(TransitionArray, TRANSITION_ARRAY_TYPE)
TYPE_CHECKER(JSStringIterator, JS_STRING_ITERATOR_TYPE)
bool HeapObject::IsJSWeakCollection() const {
return IsJSWeakMap() || IsJSWeakSet();
Handle<Object> Object::WrapForRead(Isolate* isolate, Handle<Object> object,
Representation representation) {
DCHECK(!object->IsUninitialized(isolate));
if (!representation.IsDouble()) {
DCHECK(object->FitsRepresentation(representation));
return object;
}
return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value());
}
bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); }
bool HeapObject::IsDescriptorArray() const { return IsFixedArray(); }
bool HeapObject::IsFrameArray() const { return IsFixedArray(); }
bool HeapObject::IsArrayList() const { return IsFixedArray(); }
bool HeapObject::IsRegExpMatchInfo() const { return IsFixedArray(); }
bool Object::IsLayoutDescriptor() const {
return IsSmi() || IsFixedTypedArrayBase();
StringShape::StringShape(const String* str)
: type_(str->map()->instance_type()) {
set_valid();
DCHECK((type_ & kIsNotStringMask) == kStringTag);
}
bool HeapObject::IsTypeFeedbackVector() const { return IsFixedArray(); }
bool HeapObject::IsTypeFeedbackMetadata() const { return IsFixedArray(); }
bool HeapObject::IsLiteralsArray() const { return IsFixedArray(); }
bool HeapObject::IsDeoptimizationInputData() const {
// Must be a fixed array.
if (!IsFixedArray()) 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
// check that the length is zero or else the fixed size plus a multiple of
// the entry size.
int length = FixedArray::cast(this)->length();
if (length == 0) return true;
length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
return length >= 0 && length % DeoptimizationInputData::kDeoptEntrySize == 0;
StringShape::StringShape(Map* map) : type_(map->instance_type()) {
set_valid();
DCHECK((type_ & kIsNotStringMask) == kStringTag);
}
bool HeapObject::IsDeoptimizationOutputData() const {
if (!IsFixedArray()) return false;
// There's actually no way to see the difference between a fixed array and
// a deoptimization data array. Since this is used for asserts we can check
// that the length is plausible though.
if (FixedArray::cast(this)->length() % 2 != 0) return false;
return true;
StringShape::StringShape(InstanceType t) : type_(static_cast<uint32_t>(t)) {
set_valid();
DCHECK((type_ & kIsNotStringMask) == kStringTag);
}
bool HeapObject::IsHandlerTable() const {
if (!IsFixedArray()) return false;
// There's actually no way to see the difference between a fixed array and
// a handler table array.
return true;
bool StringShape::IsInternalized() {
DCHECK(valid());
STATIC_ASSERT(kNotInternalizedTag != 0);
return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) ==
(kStringTag | kInternalizedTag);
}
bool HeapObject::IsTemplateList() const {
if (!IsFixedArray()) 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 String::IsOneByteRepresentation() const {
uint32_t type = map()->instance_type();
return (type & kStringEncodingMask) == kOneByteStringTag;
}
bool HeapObject::IsDependentCode() const {
if (!IsFixedArray()) return false;
// There's actually no way to see the difference between a fixed array and
// a dependent codes array.
return true;
bool String::IsTwoByteRepresentation() const {
uint32_t type = map()->instance_type();
return (type & kStringEncodingMask) == kTwoByteStringTag;
}
bool HeapObject::IsContext() const {
Map* map = this->map();
Heap* heap = GetHeap();
return (
map == heap->function_context_map() || map == heap->catch_context_map() ||
map == heap->with_context_map() || map == heap->native_context_map() ||
map == heap->block_context_map() || map == heap->module_context_map() ||
map == heap->script_context_map() ||
map == heap->debug_evaluate_context_map());
bool String::IsOneByteRepresentationUnderneath() {
uint32_t type = map()->instance_type();
STATIC_ASSERT(kIsIndirectStringTag != 0);
STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
DCHECK(IsFlat());
switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
case kOneByteStringTag:
return true;
case kTwoByteStringTag:
return false;
default: // Cons or sliced string. Need to go deeper.
return GetUnderlying()->IsOneByteRepresentation();
}
}
bool HeapObject::IsNativeContext() const {
return map() == GetHeap()->native_context_map();
bool String::IsTwoByteRepresentationUnderneath() {
uint32_t type = map()->instance_type();
STATIC_ASSERT(kIsIndirectStringTag != 0);
STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
DCHECK(IsFlat());
switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
case kOneByteStringTag:
return false;
case kTwoByteStringTag:
return true;
default: // Cons or sliced string. Need to go deeper.
return GetUnderlying()->IsTwoByteRepresentation();
}
}
bool HeapObject::IsScriptContextTable() const {
return map() == GetHeap()->script_context_table_map();
bool String::HasOnlyOneByteChars() {
uint32_t type = map()->instance_type();
return (type & kOneByteDataHintMask) == kOneByteDataHintTag ||
IsOneByteRepresentation();
}
bool HeapObject::IsScopeInfo() const {
return map() == GetHeap()->scope_info_map();
bool StringShape::IsCons() {
return (type_ & kStringRepresentationMask) == kConsStringTag;
}
bool HeapObject::IsModuleInfo() const {
return map() == GetHeap()->module_info_map();
bool StringShape::IsSliced() {
return (type_ & kStringRepresentationMask) == kSlicedStringTag;
}
TYPE_CHECKER(JSBoundFunction, JS_BOUND_FUNCTION_TYPE)
TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
template <> inline bool Is<JSFunction>(Object* obj) {
return obj->IsJSFunction();
bool StringShape::IsIndirect() {
return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
}
TYPE_CHECKER(Code, CODE_TYPE)
TYPE_CHECKER(Oddball, ODDBALL_TYPE)
TYPE_CHECKER(Cell, CELL_TYPE)
TYPE_CHECKER(PropertyCell, PROPERTY_CELL_TYPE)
TYPE_CHECKER(WeakCell, WEAK_CELL_TYPE)
TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
TYPE_CHECKER(JSDate, JS_DATE_TYPE)
TYPE_CHECKER(JSError, JS_ERROR_TYPE)
TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE)
TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
TYPE_CHECKER(JSPromise, JS_PROMISE_TYPE)
TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
bool HeapObject::IsAbstractCode() const {
return IsBytecodeArray() || IsCode();
bool StringShape::IsExternal() {
return (type_ & kStringRepresentationMask) == kExternalStringTag;
}
bool HeapObject::IsStringWrapper() const {
return IsJSValue() && JSValue::cast(this)->value()->IsString();
bool StringShape::IsSequential() {
return (type_ & kStringRepresentationMask) == kSeqStringTag;
}
TYPE_CHECKER(Foreign, FOREIGN_TYPE)
bool HeapObject::IsBoolean() const {
return IsOddball() &&
((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
StringRepresentationTag StringShape::representation_tag() {
uint32_t tag = (type_ & kStringRepresentationMask);
return static_cast<StringRepresentationTag>(tag);
}
uint32_t StringShape::encoding_tag() { return type_ & kStringEncodingMask; }
TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE)
TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE)
TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE)
bool HeapObject::IsJSArrayBufferView() const {
return IsJSDataView() || IsJSTypedArray();
uint32_t StringShape::full_representation_tag() {
return (type_ & (kStringRepresentationMask | kStringEncodingMask));
}
STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) ==
Internals::kFullStringRepresentationMask);
TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
template <> inline bool Is<JSArray>(Object* obj) {
return obj->IsJSArray();
}
STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) ==
Internals::kStringEncodingMask);
bool HeapObject::IsHashTable() const {
return map() == GetHeap()->hash_table_map();
bool StringShape::IsSequentialOneByte() {
return full_representation_tag() == (kSeqStringTag | kOneByteStringTag);
}
bool HeapObject::IsWeakHashTable() const { return IsHashTable(); }
bool HeapObject::IsDictionary() const {
return IsHashTable() && this != GetHeap()->string_table();
bool StringShape::IsSequentialTwoByte() {
return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
}
bool Object::IsNameDictionary() const {
return IsDictionary();
bool StringShape::IsExternalOneByte() {
return full_representation_tag() == (kExternalStringTag | kOneByteStringTag);
}
STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) ==
Internals::kExternalOneByteRepresentationTag);
bool Object::IsGlobalDictionary() const { return IsDictionary(); }
bool Object::IsSeededNumberDictionary() const {
return IsDictionary();
}
STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag);
bool HeapObject::IsUnseededNumberDictionary() const {
return map() == GetHeap()->unseeded_number_dictionary_map();
bool StringShape::IsExternalTwoByte() {
return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
}
bool HeapObject::IsStringTable() const { return IsHashTable(); }
bool HeapObject::IsStringSet() const { return IsHashTable(); }
STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) ==
Internals::kExternalTwoByteRepresentationTag);
bool HeapObject::IsObjectHashSet() const { return IsHashTable(); }
STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
bool HeapObject::IsNormalizedMapCache() const {
return NormalizedMapCache::IsNormalizedMapCache(this);
uc32 FlatStringReader::Get(int index) {
if (is_one_byte_) {
return Get<uint8_t>(index);
} else {
return Get<uc16>(index);
}
}
int NormalizedMapCache::GetIndex(Handle<Map> map) {
return map->Hash() % NormalizedMapCache::kEntries;
template <typename Char>
Char FlatStringReader::Get(int index) {
DCHECK_EQ(is_one_byte_, sizeof(Char) == 1);
DCHECK(0 <= index && index <= length_);
if (sizeof(Char) == 1) {
return static_cast<Char>(static_cast<const uint8_t*>(start_)[index]);
} else {
return static_cast<Char>(static_cast<const uc16*>(start_)[index]);
}
}
bool NormalizedMapCache::IsNormalizedMapCache(const HeapObject* obj) {
if (!obj->IsFixedArray()) return false;
if (FixedArray::cast(obj)->length() != NormalizedMapCache::kEntries) {
return false;
}
#ifdef VERIFY_HEAP
if (FLAG_verify_heap) {
reinterpret_cast<NormalizedMapCache*>(const_cast<HeapObject*>(obj))
->NormalizedMapCacheVerify();
}
#endif
return true;
Handle<Object> StringTableShape::AsHandle(Isolate* isolate, HashTableKey* key) {
return key->AsHandle(isolate);
}
bool HeapObject::IsCompilationCacheTable() const { return IsHashTable(); }
Handle<Object> CompilationCacheShape::AsHandle(Isolate* isolate,
HashTableKey* key) {
return key->AsHandle(isolate);
}
bool HeapObject::IsCodeCacheHashTable() const { return IsHashTable(); }
Handle<Object> CodeCacheHashTableShape::AsHandle(Isolate* isolate,
HashTableKey* key) {
return key->AsHandle(isolate);
}
bool HeapObject::IsMapCache() const { return IsHashTable(); }
template <typename Char>
class SequentialStringKey : public HashTableKey {
public:
explicit SequentialStringKey(Vector<const Char> string, uint32_t seed)
: string_(string), hash_field_(0), seed_(seed) {}
bool HeapObject::IsObjectHashTable() const { return IsHashTable(); }
uint32_t Hash() override {
hash_field_ = StringHasher::HashSequentialString<Char>(
string_.start(), string_.length(), seed_);
bool HeapObject::IsOrderedHashTable() const {
return map() == GetHeap()->ordered_hash_table_map();
}
uint32_t result = hash_field_ >> String::kHashShift;
DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
return result;
}
uint32_t HashForObject(Object* other) override {
return String::cast(other)->Hash();
}
bool Object::IsOrderedHashSet() const {
return IsOrderedHashTable();
}
Vector<const Char> string_;
uint32_t hash_field_;
uint32_t seed_;
};
class OneByteStringKey : public SequentialStringKey<uint8_t> {
public:
OneByteStringKey(Vector<const uint8_t> str, uint32_t seed)
: SequentialStringKey<uint8_t>(str, seed) {}
bool Object::IsOrderedHashMap() const {
return IsOrderedHashTable();
}
bool IsMatch(Object* string) override {
return String::cast(string)->IsOneByteEqualTo(string_);
}
Handle<Object> AsHandle(Isolate* isolate) override;
};
bool Object::IsPrimitive() const {
return IsSmi() || HeapObject::cast(this)->map()->IsPrimitiveMap();
}
class SeqOneByteSubStringKey : public HashTableKey {
public:
SeqOneByteSubStringKey(Handle<SeqOneByteString> string, int from, int length)
: string_(string), from_(from), length_(length) {
DCHECK(string_->IsSeqOneByteString());
}
bool HeapObject::IsJSGlobalProxy() const {
bool result = map()->instance_type() == JS_GLOBAL_PROXY_TYPE;
DCHECK(!result || map()->is_access_check_needed());
return result;
}
uint32_t Hash() override {
DCHECK(length_ >= 0);
DCHECK(from_ + length_ <= string_->length());
const uint8_t* chars = string_->GetChars() + from_;
hash_field_ = StringHasher::HashSequentialString(
chars, length_, string_->GetHeap()->HashSeed());
uint32_t result = hash_field_ >> String::kHashShift;
DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
return result;
}
uint32_t HashForObject(Object* other) override {
return String::cast(other)->Hash();
}
TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
bool IsMatch(Object* string) override;
Handle<Object> AsHandle(Isolate* isolate) override;
bool HeapObject::IsUndetectable() const { return map()->is_undetectable(); }
private:
Handle<SeqOneByteString> string_;
int from_;
int length_;
uint32_t hash_field_;
};
bool HeapObject::IsAccessCheckNeeded() const {
if (IsJSGlobalProxy()) {
const JSGlobalProxy* proxy = JSGlobalProxy::cast(this);
JSGlobalObject* global = proxy->GetIsolate()->context()->global_object();
return proxy->IsDetachedFrom(global);
}
return map()->is_access_check_needed();
}
class TwoByteStringKey : public SequentialStringKey<uc16> {
public:
explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed)
: SequentialStringKey<uc16>(str, seed) {}
bool HeapObject::IsStruct() const {
switch (map()->instance_type()) {
#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
default: return false;
bool IsMatch(Object* string) override {
return String::cast(string)->IsTwoByteEqualTo(string_);
}
}
#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
bool Object::Is##Name() const { \
return IsHeapObject() && HeapObject::cast(this)->Is##Name(); \
} \
bool HeapObject::Is##Name() const { \
return map()->instance_type() == NAME##_TYPE; \
}
STRUCT_LIST(MAKE_STRUCT_PREDICATE)
#undef MAKE_STRUCT_PREDICATE
Handle<Object> AsHandle(Isolate* isolate) override;
};
double Object::Number() const {
DCHECK(IsNumber());
return IsSmi()
? static_cast<double>(reinterpret_cast<const Smi*>(this)->value())
: reinterpret_cast<const HeapNumber*>(this)->value();
}
// Utf8StringKey carries a vector of chars as key.
class Utf8StringKey : public HashTableKey {
public:
explicit Utf8StringKey(Vector<const char> string, uint32_t seed)
: string_(string), hash_field_(0), seed_(seed) {}
bool IsMatch(Object* string) override {
return String::cast(string)->IsUtf8EqualTo(string_);
}
bool Object::IsNaN() const {
return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value());
}
uint32_t Hash() override {
if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
hash_field_ = StringHasher::ComputeUtf8Hash(string_, seed_, &chars_);
uint32_t result = hash_field_ >> String::kHashShift;
DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
return result;
}
uint32_t HashForObject(Object* other) override {
return String::cast(other)->Hash();
}
bool Object::IsMinusZero() const {
return this->IsHeapNumber() &&
i::IsMinusZero(HeapNumber::cast(this)->value());
}
Handle<Object> AsHandle(Isolate* isolate) override {
if (hash_field_ == 0) Hash();
return isolate->factory()->NewInternalizedStringFromUtf8(string_, chars_,
hash_field_);
}
Vector<const char> string_;
uint32_t hash_field_;
int chars_; // Caches the number of characters when computing the hash code.
uint32_t seed_;
};
Representation Object::OptimalRepresentation() {
if (!FLAG_track_fields) return Representation::Tagged();
......@@ -3296,107 +3324,6 @@ void SeededNumberDictionary::set_requires_slow_elements() {
}
// ------------------------------------
// Cast operations
CAST_ACCESSOR(AbstractCode)
CAST_ACCESSOR(ArrayList)
CAST_ACCESSOR(Bool16x8)
CAST_ACCESSOR(Bool32x4)
CAST_ACCESSOR(Bool8x16)
CAST_ACCESSOR(ByteArray)
CAST_ACCESSOR(BytecodeArray)
CAST_ACCESSOR(Cell)
CAST_ACCESSOR(Code)
CAST_ACCESSOR(CodeCacheHashTable)
CAST_ACCESSOR(CompilationCacheTable)
CAST_ACCESSOR(ConsString)
CAST_ACCESSOR(DeoptimizationInputData)
CAST_ACCESSOR(DeoptimizationOutputData)
CAST_ACCESSOR(DependentCode)
CAST_ACCESSOR(DescriptorArray)
CAST_ACCESSOR(ExternalOneByteString)
CAST_ACCESSOR(ExternalString)
CAST_ACCESSOR(ExternalTwoByteString)
CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(FixedArrayBase)
CAST_ACCESSOR(FixedDoubleArray)
CAST_ACCESSOR(FixedTypedArrayBase)
CAST_ACCESSOR(Float32x4)
CAST_ACCESSOR(Foreign)
CAST_ACCESSOR(FrameArray)
CAST_ACCESSOR(GlobalDictionary)
CAST_ACCESSOR(HandlerTable)
CAST_ACCESSOR(HeapObject)
CAST_ACCESSOR(Int16x8)
CAST_ACCESSOR(Int32x4)
CAST_ACCESSOR(Int8x16)
CAST_ACCESSOR(JSArray)
CAST_ACCESSOR(JSArrayBuffer)
CAST_ACCESSOR(JSArrayBufferView)
CAST_ACCESSOR(JSBoundFunction)
CAST_ACCESSOR(JSDataView)
CAST_ACCESSOR(JSDate)
CAST_ACCESSOR(JSFunction)
CAST_ACCESSOR(JSGeneratorObject)
CAST_ACCESSOR(JSGlobalObject)
CAST_ACCESSOR(JSGlobalProxy)
CAST_ACCESSOR(JSMap)
CAST_ACCESSOR(JSMapIterator)
CAST_ACCESSOR(JSMessageObject)
CAST_ACCESSOR(JSModuleNamespace)
CAST_ACCESSOR(JSObject)
CAST_ACCESSOR(JSProxy)
CAST_ACCESSOR(JSReceiver)
CAST_ACCESSOR(JSRegExp)
CAST_ACCESSOR(JSPromise)
CAST_ACCESSOR(JSSet)
CAST_ACCESSOR(JSSetIterator)
CAST_ACCESSOR(JSStringIterator)
CAST_ACCESSOR(JSArrayIterator)
CAST_ACCESSOR(JSTypedArray)
CAST_ACCESSOR(JSValue)
CAST_ACCESSOR(JSWeakCollection)
CAST_ACCESSOR(JSWeakMap)
CAST_ACCESSOR(JSWeakSet)
CAST_ACCESSOR(LayoutDescriptor)
CAST_ACCESSOR(Map)
CAST_ACCESSOR(ModuleInfo)
CAST_ACCESSOR(Name)
CAST_ACCESSOR(NameDictionary)
CAST_ACCESSOR(NormalizedMapCache)
CAST_ACCESSOR(Object)
CAST_ACCESSOR(ObjectHashTable)
CAST_ACCESSOR(ObjectHashSet)
CAST_ACCESSOR(Oddball)
CAST_ACCESSOR(OrderedHashMap)
CAST_ACCESSOR(OrderedHashSet)
CAST_ACCESSOR(PropertyCell)
CAST_ACCESSOR(TemplateList)
CAST_ACCESSOR(RegExpMatchInfo)
CAST_ACCESSOR(ScopeInfo)
CAST_ACCESSOR(SeededNumberDictionary)
CAST_ACCESSOR(SeqOneByteString)
CAST_ACCESSOR(SeqString)
CAST_ACCESSOR(SeqTwoByteString)
CAST_ACCESSOR(SharedFunctionInfo)
CAST_ACCESSOR(Simd128Value)
CAST_ACCESSOR(SlicedString)
CAST_ACCESSOR(Smi)
CAST_ACCESSOR(String)
CAST_ACCESSOR(StringSet)
CAST_ACCESSOR(StringTable)
CAST_ACCESSOR(Struct)
CAST_ACCESSOR(Symbol)
CAST_ACCESSOR(TemplateInfo)
CAST_ACCESSOR(Uint16x8)
CAST_ACCESSOR(Uint32x4)
CAST_ACCESSOR(Uint8x16)
CAST_ACCESSOR(UnseededNumberDictionary)
CAST_ACCESSOR(WeakCell)
CAST_ACCESSOR(WeakFixedArray)
CAST_ACCESSOR(WeakHashTable)
template <class T>
PodArray<T>* PodArray<T>::cast(Object* object) {
SLOW_DCHECK(object->IsByteArray());
......@@ -3627,11 +3554,6 @@ int HandlerTable::NumberOfRangeEntries() const {
return length() / kRangeEntrySize;
}
#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
STRUCT_LIST(MAKE_STRUCT_CAST)
#undef MAKE_STRUCT_CAST
template <typename Derived, typename Shape, typename Key>
HashTable<Derived, Shape, Key>*
HashTable<Derived, Shape, Key>::cast(Object* obj) {
......@@ -6821,8 +6743,6 @@ bool JSGeneratorObject::is_executing() const {
return continuation() == kGeneratorExecuting;
}
TYPE_CHECKER(JSModuleNamespace, JS_MODULE_NAMESPACE_TYPE)
ACCESSORS(JSValue, value, Object, kValueOffset)
......@@ -8470,8 +8390,6 @@ ACCESSORS(JSArrayIterator, object_map, Object, kIteratedObjectMapOffset)
ACCESSORS(JSStringIterator, string, String, kStringOffset)
SMI_ACCESSORS(JSStringIterator, index, kNextIndexOffset)
#undef TYPE_CHECKER
#undef CAST_ACCESSOR
#undef INT_ACCESSORS
#undef ACCESSORS
#undef SMI_ACCESSORS
......
......@@ -320,38 +320,34 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
// JSObject for GC purposes. The first four entries here have typeof
// 'object', whereas JS_FUNCTION_TYPE has typeof 'function'.
#define INSTANCE_TYPE_LIST(V) \
V(INTERNALIZED_STRING_TYPE) \
V(EXTERNAL_INTERNALIZED_STRING_TYPE) \
V(ONE_BYTE_INTERNALIZED_STRING_TYPE) \
V(EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE) \
V(EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE) \
V(SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE) \
V(SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE) \
V(SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE) \
V(STRING_TYPE) \
V(ONE_BYTE_STRING_TYPE) \
V(CONS_STRING_TYPE) \
V(CONS_ONE_BYTE_STRING_TYPE) \
V(SLICED_STRING_TYPE) \
V(SLICED_ONE_BYTE_STRING_TYPE) \
V(EXTERNAL_STRING_TYPE) \
V(SLICED_STRING_TYPE) \
V(ONE_BYTE_STRING_TYPE) \
V(CONS_ONE_BYTE_STRING_TYPE) \
V(EXTERNAL_ONE_BYTE_STRING_TYPE) \
V(SLICED_ONE_BYTE_STRING_TYPE) \
V(EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE) \
V(SHORT_EXTERNAL_STRING_TYPE) \
V(SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE) \
V(SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE) \
\
V(INTERNALIZED_STRING_TYPE) \
V(ONE_BYTE_INTERNALIZED_STRING_TYPE) \
V(EXTERNAL_INTERNALIZED_STRING_TYPE) \
V(EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE) \
V(EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE) \
V(SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE) \
V(SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE) \
V(SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE) \
\
V(SYMBOL_TYPE) \
V(HEAP_NUMBER_TYPE) \
V(SIMD128_VALUE_TYPE) \
V(ODDBALL_TYPE) \
\
V(MAP_TYPE) \
V(CODE_TYPE) \
V(ODDBALL_TYPE) \
V(CELL_TYPE) \
V(PROPERTY_CELL_TYPE) \
\
V(HEAP_NUMBER_TYPE) \
V(MUTABLE_HEAP_NUMBER_TYPE) \
V(FOREIGN_TYPE) \
V(BYTE_ARRAY_TYPE) \
......@@ -368,6 +364,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(FIXED_FLOAT64_ARRAY_TYPE) \
V(FIXED_UINT8_CLAMPED_ARRAY_TYPE) \
\
V(FIXED_DOUBLE_ARRAY_TYPE) \
V(FILLER_TYPE) \
\
V(ACCESSOR_INFO_TYPE) \
......@@ -377,16 +374,16 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(CALL_HANDLER_INFO_TYPE) \
V(FUNCTION_TEMPLATE_INFO_TYPE) \
V(OBJECT_TEMPLATE_INFO_TYPE) \
V(SIGNATURE_INFO_TYPE) \
V(TYPE_SWITCH_INFO_TYPE) \
V(ALLOCATION_MEMENTO_TYPE) \
V(ALLOCATION_SITE_TYPE) \
V(ALLOCATION_MEMENTO_TYPE) \
V(SCRIPT_TYPE) \
V(TYPE_FEEDBACK_INFO_TYPE) \
V(ALIASED_ARGUMENTS_ENTRY_TYPE) \
V(BOX_TYPE) \
V(PROMISE_RESOLVE_THENABLE_JOB_INFO_TYPE) \
V(PROMISE_REACTION_JOB_INFO_TYPE) \
V(DEBUG_INFO_TYPE) \
V(BREAK_POINT_INFO_TYPE) \
V(PROTOTYPE_INFO_TYPE) \
V(TUPLE2_TYPE) \
V(TUPLE3_TYPE) \
......@@ -394,31 +391,30 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(CONSTANT_ELEMENTS_PAIR_TYPE) \
V(MODULE_TYPE) \
V(MODULE_INFO_ENTRY_TYPE) \
\
V(FIXED_ARRAY_TYPE) \
V(FIXED_DOUBLE_ARRAY_TYPE) \
V(TRANSITION_ARRAY_TYPE) \
V(SHARED_FUNCTION_INFO_TYPE) \
V(CELL_TYPE) \
V(WEAK_CELL_TYPE) \
V(TRANSITION_ARRAY_TYPE) \
\
V(JS_MESSAGE_OBJECT_TYPE) \
V(PROPERTY_CELL_TYPE) \
\
V(JS_PROXY_TYPE) \
V(JS_GLOBAL_OBJECT_TYPE) \
V(JS_GLOBAL_PROXY_TYPE) \
V(JS_SPECIAL_API_OBJECT_TYPE) \
V(JS_VALUE_TYPE) \
V(JS_MESSAGE_OBJECT_TYPE) \
V(JS_DATE_TYPE) \
V(JS_API_OBJECT_TYPE) \
V(JS_OBJECT_TYPE) \
V(JS_ARGUMENTS_TYPE) \
V(JS_CONTEXT_EXTENSION_OBJECT_TYPE) \
V(JS_GENERATOR_OBJECT_TYPE) \
V(JS_MODULE_NAMESPACE_TYPE) \
V(JS_GLOBAL_OBJECT_TYPE) \
V(JS_GLOBAL_PROXY_TYPE) \
V(JS_API_OBJECT_TYPE) \
V(JS_SPECIAL_API_OBJECT_TYPE) \
V(JS_ARRAY_TYPE) \
V(JS_ARRAY_BUFFER_TYPE) \
V(JS_TYPED_ARRAY_TYPE) \
V(JS_DATA_VIEW_TYPE) \
V(JS_PROXY_TYPE) \
V(JS_SET_TYPE) \
V(JS_MAP_TYPE) \
V(JS_SET_ITERATOR_TYPE) \
......@@ -434,12 +430,12 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(JS_FAST_ARRAY_KEY_ITERATOR_TYPE) \
V(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE) \
\
V(JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
......@@ -452,12 +448,12 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
\
V(JS_INT8_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_INT16_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_INT8_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_INT32_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_INT16_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_INT32_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE) \
......@@ -471,9 +467,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE) \
\
V(JS_BOUND_FUNCTION_TYPE) \
V(JS_FUNCTION_TYPE) \
V(DEBUG_INFO_TYPE) \
V(BREAK_POINT_INFO_TYPE)
V(JS_FUNCTION_TYPE)
// Since string types are not consecutive, this macro is used to
// iterate over them.
......@@ -536,11 +530,6 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
// type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST
// manually.
#define STRUCT_LIST(V) \
V(BOX, Box, box) \
V(PROMISE_RESOLVE_THENABLE_JOB_INFO, PromiseResolveThenableJobInfo, \
promise_resolve_thenable_job_info) \
V(PROMISE_REACTION_JOB_INFO, PromiseReactionJobInfo, \
promise_reaction_job_info) \
V(ACCESSOR_INFO, AccessorInfo, accessor_info) \
V(ACCESSOR_PAIR, AccessorPair, accessor_pair) \
V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \
......@@ -548,20 +537,25 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info) \
V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \
V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \
V(SCRIPT, Script, script) \
V(ALLOCATION_SITE, AllocationSite, allocation_site) \
V(ALLOCATION_MEMENTO, AllocationMemento, allocation_memento) \
V(SCRIPT, Script, script) \
V(TYPE_FEEDBACK_INFO, TypeFeedbackInfo, type_feedback_info) \
V(ALIASED_ARGUMENTS_ENTRY, AliasedArgumentsEntry, aliased_arguments_entry) \
V(BOX, Box, box) \
V(PROMISE_RESOLVE_THENABLE_JOB_INFO, PromiseResolveThenableJobInfo, \
promise_resolve_thenable_job_info) \
V(PROMISE_REACTION_JOB_INFO, PromiseReactionJobInfo, \
promise_reaction_job_info) \
V(DEBUG_INFO, DebugInfo, debug_info) \
V(BREAK_POINT_INFO, BreakPointInfo, break_point_info) \
V(PROTOTYPE_INFO, PrototypeInfo, prototype_info) \
V(TUPLE2, Tuple2, tuple2) \
V(TUPLE3, Tuple3, tuple3) \
V(MODULE, Module, module) \
V(MODULE_INFO_ENTRY, ModuleInfoEntry, module_info_entry) \
V(CONTEXT_EXTENSION, ContextExtension, context_extension) \
V(CONSTANT_ELEMENTS_PAIR, ConstantElementsPair, constant_elements_pair)
V(CONSTANT_ELEMENTS_PAIR, ConstantElementsPair, constant_elements_pair) \
V(MODULE, Module, module) \
V(MODULE_INFO_ENTRY, ModuleInfoEntry, module_info_entry)
// We use the full 8 bits of the instance_type field to encode heap object
// instance types. The high-order bit (bit 7) is set if the object is not a
......@@ -718,8 +712,6 @@ enum InstanceType {
CALL_HANDLER_INFO_TYPE,
FUNCTION_TEMPLATE_INFO_TYPE,
OBJECT_TEMPLATE_INFO_TYPE,
SIGNATURE_INFO_TYPE,
TYPE_SWITCH_INFO_TYPE,
ALLOCATION_SITE_TYPE,
ALLOCATION_MEMENTO_TYPE,
SCRIPT_TYPE,
......@@ -730,12 +722,6 @@ enum InstanceType {
PROMISE_REACTION_JOB_INFO_TYPE,
DEBUG_INFO_TYPE,
BREAK_POINT_INFO_TYPE,
FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
CELL_TYPE,
WEAK_CELL_TYPE,
TRANSITION_ARRAY_TYPE,
PROPERTY_CELL_TYPE,
PROTOTYPE_INFO_TYPE,
TUPLE2_TYPE,
TUPLE3_TYPE,
......@@ -743,6 +729,12 @@ enum InstanceType {
CONSTANT_ELEMENTS_PAIR_TYPE,
MODULE_TYPE,
MODULE_INFO_ENTRY_TYPE,
FIXED_ARRAY_TYPE,
TRANSITION_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
CELL_TYPE,
WEAK_CELL_TYPE,
PROPERTY_CELL_TYPE,
// All the following types are subtypes of JSReceiver, which corresponds to
// objects in the JS sense. The first and the last type in this range are
......
......@@ -120,6 +120,7 @@ v8_executable("unittests") {
"libplatform/task-queue-unittest.cc",
"libplatform/worker-thread-unittest.cc",
"locked-queue-unittest.cc",
"object-unittest.cc",
"register-configuration-unittest.cc",
"run-all-unittests.cc",
"source-position-table-unittest.cc",
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <cmath>
#include <iostream>
#include <limits>
#include "src/objects.h"
......
// Copyright 2016 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.
#include <cmath>
#include <iostream>
#include <limits>
#include "src/objects-inl.h"
#include "src/objects.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
TEST(Object, InstanceTypeListOrder) {
int current = 0;
int last = -1;
InstanceType current_type = static_cast<InstanceType>(current);
EXPECT_EQ(current_type, InstanceType::FIRST_TYPE);
EXPECT_EQ(current_type, InstanceType::INTERNALIZED_STRING_TYPE);
#define TEST_INSTANCE_TYPE(type) \
current_type = InstanceType::type; \
current = static_cast<int>(current_type); \
if (current > static_cast<int>(LAST_NAME_TYPE)) { \
EXPECT_EQ(last + 1, current); \
} \
EXPECT_LT(last, current) << " INSTANCE_TYPE_LIST is not ordered: " \
<< "last = " << static_cast<InstanceType>(last) \
<< " vs. current = " << current_type; \
last = current;
INSTANCE_TYPE_LIST(TEST_INSTANCE_TYPE)
#undef TEST_INSTANCE_TYPE
}
TEST(Object, StructListOrder) {
int current = static_cast<int>(InstanceType::ACCESSOR_INFO_TYPE);
int last = current - 1;
ASSERT_LT(0, last);
InstanceType current_type = static_cast<InstanceType>(current);
#define TEST_STRUCT(type, class, name) \
current_type = InstanceType::type##_TYPE; \
current = static_cast<int>(current_type); \
EXPECT_EQ(last + 1, current) \
<< " STRUCT_LIST is not ordered: " \
<< " last = " << static_cast<InstanceType>(last) \
<< " vs. current = " << current_type; \
last = current;
STRUCT_LIST(TEST_STRUCT)
#undef TEST_STRUCT
}
} // namespace internal
} // namespace v8
......@@ -118,6 +118,7 @@
'heap/scavenge-job-unittest.cc',
'heap/slot-set-unittest.cc',
'locked-queue-unittest.cc',
'object-unittest.cc',
'register-configuration-unittest.cc',
'run-all-unittests.cc',
'source-position-table-unittest.cc',
......
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