From c0282f608c381152ce5d3614ebd83ca3263e2de9 Mon Sep 17 00:00:00 2001 From: cbruni Date: Mon, 19 Dec 2016 04:50:30 -0800 Subject: [PATCH] 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} --- include/v8.h | 4 +- src/ast/ast-types.cc | 2 - src/compiler/types.cc | 2 - src/objects-inl.h | 1130 ++++++++++++-------------- src/objects.h | 110 ++- test/unittests/BUILD.gn | 1 + test/unittests/heap/heap-unittest.cc | 1 + test/unittests/object-unittest.cc | 57 ++ test/unittests/unittests.gyp | 1 + 9 files changed, 637 insertions(+), 671 deletions(-) create mode 100644 test/unittests/object-unittest.cc diff --git a/include/v8.h b/include/v8.h index 12b3b808a1..b57a9ca9ac 100644 --- a/include/v8.h +++ b/include/v8.h @@ -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; diff --git a/src/ast/ast-types.cc b/src/ast/ast-types.cc index 8e1cca2030..55354a6019 100644 --- a/src/ast/ast-types.cc +++ b/src/ast/ast-types.cc @@ -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: diff --git a/src/compiler/types.cc b/src/compiler/types.cc index b052927b81..c9563c492a 100644 --- a/src/compiler/types.cc +++ b/src/compiler/types.cc @@ -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: diff --git a/src/objects-inl.h b/src/objects-inl.h index 54a40c2117..e3b47427e3 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -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(object); \ - } \ - const type* type::cast(const Object* object) { \ - SLOW_DCHECK(object->Is##type()); \ - return reinterpret_cast(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,412 +297,13 @@ bool HeapObject::IsExternalTwoByteString() const { String::cast(this)->IsTwoByteRepresentation(); } -bool Object::HasValidElements() { - // Dictionary is covered under FixedArray. - return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase(); -} - - -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(first->Number()); - uint32_t index; - return Name::cast(second)->AsArrayIndex(&index) && index == expected; - } - return Name::cast(first)->Equals(Name::cast(second)); -} - - -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; -} - - -Handle Object::NewStorageFor(Isolate* isolate, - Handle 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); -} - - -Handle Object::WrapForRead(Isolate* isolate, - Handle object, - Representation representation) { - DCHECK(!object->IsUninitialized(isolate)); - if (!representation.IsDouble()) { - DCHECK(object->FitsRepresentation(representation)); - return object; - } - return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value()); -} - - -StringShape::StringShape(const String* str) - : type_(str->map()->instance_type()) { - set_valid(); - DCHECK((type_ & kIsNotStringMask) == kStringTag); -} - - -StringShape::StringShape(Map* map) - : type_(map->instance_type()) { - set_valid(); - DCHECK((type_ & kIsNotStringMask) == kStringTag); -} - - -StringShape::StringShape(InstanceType t) - : type_(static_cast(t)) { - set_valid(); - DCHECK((type_ & kIsNotStringMask) == kStringTag); -} - - -bool StringShape::IsInternalized() { - DCHECK(valid()); - STATIC_ASSERT(kNotInternalizedTag != 0); - return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) == - (kStringTag | kInternalizedTag); -} - - -bool String::IsOneByteRepresentation() const { - uint32_t type = map()->instance_type(); - return (type & kStringEncodingMask) == kOneByteStringTag; -} - - -bool String::IsTwoByteRepresentation() const { - uint32_t type = map()->instance_type(); - return (type & kStringEncodingMask) == kTwoByteStringTag; -} - - -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 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 String::HasOnlyOneByteChars() { - uint32_t type = map()->instance_type(); - return (type & kOneByteDataHintMask) == kOneByteDataHintTag || - IsOneByteRepresentation(); -} - - -bool StringShape::IsCons() { - return (type_ & kStringRepresentationMask) == kConsStringTag; -} - - -bool StringShape::IsSliced() { - return (type_ & kStringRepresentationMask) == kSlicedStringTag; -} - - -bool StringShape::IsIndirect() { - return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag; -} - - -bool StringShape::IsExternal() { - return (type_ & kStringRepresentationMask) == kExternalStringTag; -} - - -bool StringShape::IsSequential() { - return (type_ & kStringRepresentationMask) == kSeqStringTag; -} - - -StringRepresentationTag StringShape::representation_tag() { - uint32_t tag = (type_ & kStringRepresentationMask); - return static_cast(tag); -} - - -uint32_t StringShape::encoding_tag() { - return type_ & kStringEncodingMask; -} - - -uint32_t StringShape::full_representation_tag() { - return (type_ & (kStringRepresentationMask | kStringEncodingMask)); -} - - -STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) == - Internals::kFullStringRepresentationMask); - -STATIC_ASSERT(static_cast(kStringEncodingMask) == - Internals::kStringEncodingMask); - - -bool StringShape::IsSequentialOneByte() { - return full_representation_tag() == (kSeqStringTag | kOneByteStringTag); -} - - -bool StringShape::IsSequentialTwoByte() { - return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag); -} - - -bool StringShape::IsExternalOneByte() { - return full_representation_tag() == (kExternalStringTag | kOneByteStringTag); -} - - -STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) == - Internals::kExternalOneByteRepresentationTag); - -STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag); - - -bool StringShape::IsExternalTwoByte() { - return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag); -} - - -STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) == - Internals::kExternalTwoByteRepresentationTag); - -STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag); - - -uc32 FlatStringReader::Get(int index) { - if (is_one_byte_) { - return Get(index); - } else { - return Get(index); - } -} - - -template -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(static_cast(start_)[index]); - } else { - return static_cast(static_cast(start_)[index]); - } -} - - -Handle StringTableShape::AsHandle(Isolate* isolate, HashTableKey* key) { - return key->AsHandle(isolate); -} - - -Handle CompilationCacheShape::AsHandle(Isolate* isolate, - HashTableKey* key) { - return key->AsHandle(isolate); -} - - -Handle CodeCacheHashTableShape::AsHandle(Isolate* isolate, - HashTableKey* key) { - return key->AsHandle(isolate); -} - -template -class SequentialStringKey : public HashTableKey { - public: - explicit SequentialStringKey(Vector string, uint32_t seed) - : string_(string), hash_field_(0), seed_(seed) { } - - uint32_t Hash() override { - hash_field_ = StringHasher::HashSequentialString(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; - } - - - uint32_t HashForObject(Object* other) override { - return String::cast(other)->Hash(); - } - - Vector string_; - uint32_t hash_field_; - uint32_t seed_; -}; - - -class OneByteStringKey : public SequentialStringKey { - public: - OneByteStringKey(Vector str, uint32_t seed) - : SequentialStringKey(str, seed) { } - - bool IsMatch(Object* string) override { - return String::cast(string)->IsOneByteEqualTo(string_); - } - - Handle AsHandle(Isolate* isolate) override; -}; - - -class SeqOneByteSubStringKey : public HashTableKey { - public: - SeqOneByteSubStringKey(Handle string, int from, int length) - : string_(string), from_(from), length_(length) { - DCHECK(string_->IsSeqOneByteString()); - } - - 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(); - } - - bool IsMatch(Object* string) override; - Handle AsHandle(Isolate* isolate) override; - - private: - Handle string_; - int from_; - int length_; - uint32_t hash_field_; -}; - - -class TwoByteStringKey : public SequentialStringKey { - public: - explicit TwoByteStringKey(Vector str, uint32_t seed) - : SequentialStringKey(str, seed) { } - - bool IsMatch(Object* string) override { - return String::cast(string)->IsTwoByteEqualTo(string_); - } - - Handle AsHandle(Isolate* isolate) override; -}; - - -// Utf8StringKey carries a vector of chars as key. -class Utf8StringKey : public HashTableKey { - public: - explicit Utf8StringKey(Vector string, uint32_t seed) - : string_(string), hash_field_(0), seed_(seed) { } - - bool IsMatch(Object* string) override { - return String::cast(string)->IsUtf8EqualTo(string_); - } - - 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(); - } - - Handle AsHandle(Isolate* isolate) override { - if (hash_field_ == 0) Hash(); - return isolate->factory()->NewInternalizedStringFromUtf8( - string_, chars_, hash_field_); - } - - Vector 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 Object::IsNumber() const { return IsSmi() || IsHeapNumber(); } bool HeapObject::IsFiller() const { InstanceType instance_type = map()->instance_type(); return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_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 - bool HeapObject::IsFixedTypedArrayBase() const { InstanceType instance_type = map()->instance_type(); return (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE && @@ -696,19 +328,6 @@ bool HeapObject::IsJSArrayIterator() const { instance_type <= LAST_ARRAY_ITERATOR_TYPE); } -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(); } @@ -806,28 +425,11 @@ bool HeapObject::IsModuleInfo() const { return map() == GetHeap()->module_info_map(); } -TYPE_CHECKER(JSBoundFunction, JS_BOUND_FUNCTION_TYPE) -TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE) - - -template <> inline bool Is(Object* obj) { +template <> +inline bool Is(Object* obj) { return obj->IsJSFunction(); } - -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(); } @@ -836,28 +438,17 @@ bool HeapObject::IsStringWrapper() const { return IsJSValue() && JSValue::cast(this)->value()->IsString(); } - -TYPE_CHECKER(Foreign, FOREIGN_TYPE) - bool HeapObject::IsBoolean() const { return IsOddball() && - ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0); + ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0); } - -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(); } - -TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE) - -template <> inline bool Is(Object* obj) { +template <> +inline bool Is(Object* obj) { return obj->IsJSArray(); } @@ -871,18 +462,11 @@ bool HeapObject::IsDictionary() const { return IsHashTable() && this != GetHeap()->string_table(); } - -bool Object::IsNameDictionary() const { - return IsDictionary(); -} - +bool Object::IsNameDictionary() const { return IsDictionary(); } bool Object::IsGlobalDictionary() const { return IsDictionary(); } - -bool Object::IsSeededNumberDictionary() const { - return IsDictionary(); -} +bool Object::IsSeededNumberDictionary() const { return IsDictionary(); } bool HeapObject::IsUnseededNumberDictionary() const { return map() == GetHeap()->unseeded_number_dictionary_map(); @@ -898,7 +482,6 @@ bool HeapObject::IsNormalizedMapCache() const { return NormalizedMapCache::IsNormalizedMapCache(this); } - int NormalizedMapCache::GetIndex(Handle map) { return map->Hash() % NormalizedMapCache::kEntries; } @@ -929,16 +512,9 @@ bool HeapObject::IsOrderedHashTable() const { return map() == GetHeap()->ordered_hash_table_map(); } +bool Object::IsOrderedHashSet() const { return IsOrderedHashTable(); } -bool Object::IsOrderedHashSet() const { - return IsOrderedHashTable(); -} - - -bool Object::IsOrderedHashMap() const { - return IsOrderedHashTable(); -} - +bool Object::IsOrderedHashMap() const { return IsOrderedHashTable(); } bool Object::IsPrimitive() const { return IsSmi() || HeapObject::cast(this)->map()->IsPrimitiveMap(); @@ -950,9 +526,6 @@ bool HeapObject::IsJSGlobalProxy() const { return result; } - -TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE) - bool HeapObject::IsUndetectable() const { return map()->is_undetectable(); } bool HeapObject::IsAccessCheckNeeded() const { @@ -966,10 +539,13 @@ bool HeapObject::IsAccessCheckNeeded() const { 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) +#define MAKE_STRUCT_CASE(NAME, Name, name) \ + case NAME##_TYPE: \ + return true; + STRUCT_LIST(MAKE_STRUCT_CASE) #undef MAKE_STRUCT_CASE - default: return false; + default: + return false; } } @@ -990,17 +566,469 @@ double Object::Number() const { : reinterpret_cast(this)->value(); } - bool Object::IsNaN() const { return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value()); } - bool Object::IsMinusZero() const { return this->IsHeapNumber() && i::IsMinusZero(HeapNumber::cast(this)->value()); } +// ------------------------------------ +// Cast operations + +#define CAST_ACCESSOR(type) \ + type* type::cast(Object* object) { \ + SLOW_DCHECK(object->Is##type()); \ + return reinterpret_cast(object); \ + } \ + const type* type::cast(const Object* object) { \ + SLOW_DCHECK(object->Is##type()); \ + return reinterpret_cast(object); \ + } + +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 MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name) +STRUCT_LIST(MAKE_STRUCT_CAST) +#undef MAKE_STRUCT_CAST + +#undef CAST_ACCESSOR + +bool Object::HasValidElements() { + // Dictionary is covered under FixedArray. + return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase(); +} + +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(first->Number()); + uint32_t index; + return Name::cast(second)->AsArrayIndex(&index) && index == expected; + } + return Name::cast(first)->Equals(Name::cast(second)); +} + +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; +} + +Handle Object::NewStorageFor(Isolate* isolate, Handle 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); +} + +Handle Object::WrapForRead(Isolate* isolate, Handle object, + Representation representation) { + DCHECK(!object->IsUninitialized(isolate)); + if (!representation.IsDouble()) { + DCHECK(object->FitsRepresentation(representation)); + return object; + } + return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value()); +} + +StringShape::StringShape(const String* str) + : type_(str->map()->instance_type()) { + set_valid(); + DCHECK((type_ & kIsNotStringMask) == kStringTag); +} + +StringShape::StringShape(Map* map) : type_(map->instance_type()) { + set_valid(); + DCHECK((type_ & kIsNotStringMask) == kStringTag); +} + +StringShape::StringShape(InstanceType t) : type_(static_cast(t)) { + set_valid(); + DCHECK((type_ & kIsNotStringMask) == kStringTag); +} + +bool StringShape::IsInternalized() { + DCHECK(valid()); + STATIC_ASSERT(kNotInternalizedTag != 0); + return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) == + (kStringTag | kInternalizedTag); +} + +bool String::IsOneByteRepresentation() const { + uint32_t type = map()->instance_type(); + return (type & kStringEncodingMask) == kOneByteStringTag; +} + +bool String::IsTwoByteRepresentation() const { + uint32_t type = map()->instance_type(); + return (type & kStringEncodingMask) == kTwoByteStringTag; +} + +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 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 String::HasOnlyOneByteChars() { + uint32_t type = map()->instance_type(); + return (type & kOneByteDataHintMask) == kOneByteDataHintTag || + IsOneByteRepresentation(); +} + +bool StringShape::IsCons() { + return (type_ & kStringRepresentationMask) == kConsStringTag; +} + +bool StringShape::IsSliced() { + return (type_ & kStringRepresentationMask) == kSlicedStringTag; +} + +bool StringShape::IsIndirect() { + return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag; +} + +bool StringShape::IsExternal() { + return (type_ & kStringRepresentationMask) == kExternalStringTag; +} + +bool StringShape::IsSequential() { + return (type_ & kStringRepresentationMask) == kSeqStringTag; +} + +StringRepresentationTag StringShape::representation_tag() { + uint32_t tag = (type_ & kStringRepresentationMask); + return static_cast(tag); +} + +uint32_t StringShape::encoding_tag() { return type_ & kStringEncodingMask; } + +uint32_t StringShape::full_representation_tag() { + return (type_ & (kStringRepresentationMask | kStringEncodingMask)); +} + +STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) == + Internals::kFullStringRepresentationMask); + +STATIC_ASSERT(static_cast(kStringEncodingMask) == + Internals::kStringEncodingMask); + +bool StringShape::IsSequentialOneByte() { + return full_representation_tag() == (kSeqStringTag | kOneByteStringTag); +} + +bool StringShape::IsSequentialTwoByte() { + return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag); +} + +bool StringShape::IsExternalOneByte() { + return full_representation_tag() == (kExternalStringTag | kOneByteStringTag); +} + +STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) == + Internals::kExternalOneByteRepresentationTag); + +STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag); + +bool StringShape::IsExternalTwoByte() { + return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag); +} + +STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) == + Internals::kExternalTwoByteRepresentationTag); + +STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag); + +uc32 FlatStringReader::Get(int index) { + if (is_one_byte_) { + return Get(index); + } else { + return Get(index); + } +} + +template +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(static_cast(start_)[index]); + } else { + return static_cast(static_cast(start_)[index]); + } +} + +Handle StringTableShape::AsHandle(Isolate* isolate, HashTableKey* key) { + return key->AsHandle(isolate); +} + +Handle CompilationCacheShape::AsHandle(Isolate* isolate, + HashTableKey* key) { + return key->AsHandle(isolate); +} + +Handle CodeCacheHashTableShape::AsHandle(Isolate* isolate, + HashTableKey* key) { + return key->AsHandle(isolate); +} + +template +class SequentialStringKey : public HashTableKey { + public: + explicit SequentialStringKey(Vector string, uint32_t seed) + : string_(string), hash_field_(0), seed_(seed) {} + + uint32_t Hash() override { + hash_field_ = StringHasher::HashSequentialString( + 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; + } + + uint32_t HashForObject(Object* other) override { + return String::cast(other)->Hash(); + } + + Vector string_; + uint32_t hash_field_; + uint32_t seed_; +}; + +class OneByteStringKey : public SequentialStringKey { + public: + OneByteStringKey(Vector str, uint32_t seed) + : SequentialStringKey(str, seed) {} + + bool IsMatch(Object* string) override { + return String::cast(string)->IsOneByteEqualTo(string_); + } + + Handle AsHandle(Isolate* isolate) override; +}; + +class SeqOneByteSubStringKey : public HashTableKey { + public: + SeqOneByteSubStringKey(Handle string, int from, int length) + : string_(string), from_(from), length_(length) { + DCHECK(string_->IsSeqOneByteString()); + } + + 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(); + } + + bool IsMatch(Object* string) override; + Handle AsHandle(Isolate* isolate) override; + + private: + Handle string_; + int from_; + int length_; + uint32_t hash_field_; +}; + +class TwoByteStringKey : public SequentialStringKey { + public: + explicit TwoByteStringKey(Vector str, uint32_t seed) + : SequentialStringKey(str, seed) {} + + bool IsMatch(Object* string) override { + return String::cast(string)->IsTwoByteEqualTo(string_); + } + + Handle AsHandle(Isolate* isolate) override; +}; + +// Utf8StringKey carries a vector of chars as key. +class Utf8StringKey : public HashTableKey { + public: + explicit Utf8StringKey(Vector string, uint32_t seed) + : string_(string), hash_field_(0), seed_(seed) {} + + bool IsMatch(Object* string) override { + return String::cast(string)->IsUtf8EqualTo(string_); + } + + 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(); + } + + Handle AsHandle(Isolate* isolate) override { + if (hash_field_ == 0) Hash(); + return isolate->factory()->NewInternalizedStringFromUtf8(string_, chars_, + hash_field_); + } + + Vector 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 PodArray* PodArray::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 HashTable* HashTable::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 diff --git a/src/objects.h b/src/objects.h index 7f62eb569f..5be6657e26 100644 --- a/src/objects.h +++ b/src/objects.h @@ -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(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(EXTERNAL_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(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(CONS_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(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(SHARED_FUNCTION_INFO_TYPE) \ - V(WEAK_CELL_TYPE) \ V(TRANSITION_ARRAY_TYPE) \ + V(SHARED_FUNCTION_INFO_TYPE) \ + V(CELL_TYPE) \ + V(WEAK_CELL_TYPE) \ + V(PROPERTY_CELL_TYPE) \ \ - V(JS_MESSAGE_OBJECT_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 diff --git a/test/unittests/BUILD.gn b/test/unittests/BUILD.gn index 0b0d7defc1..6cdbe7dbeb 100644 --- a/test/unittests/BUILD.gn +++ b/test/unittests/BUILD.gn @@ -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", diff --git a/test/unittests/heap/heap-unittest.cc b/test/unittests/heap/heap-unittest.cc index 9492faf9f3..b738b44e83 100644 --- a/test/unittests/heap/heap-unittest.cc +++ b/test/unittests/heap/heap-unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include +#include #include #include "src/objects.h" diff --git a/test/unittests/object-unittest.cc b/test/unittests/object-unittest.cc new file mode 100644 index 0000000000..b09b97dea6 --- /dev/null +++ b/test/unittests/object-unittest.cc @@ -0,0 +1,57 @@ +// 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 +#include +#include + +#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(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(current_type); \ + if (current > static_cast(LAST_NAME_TYPE)) { \ + EXPECT_EQ(last + 1, current); \ + } \ + EXPECT_LT(last, current) << " INSTANCE_TYPE_LIST is not ordered: " \ + << "last = " << static_cast(last) \ + << " vs. current = " << current_type; \ + last = current; + + INSTANCE_TYPE_LIST(TEST_INSTANCE_TYPE) +#undef TEST_INSTANCE_TYPE +} + +TEST(Object, StructListOrder) { + int current = static_cast(InstanceType::ACCESSOR_INFO_TYPE); + int last = current - 1; + ASSERT_LT(0, last); + InstanceType current_type = static_cast(current); +#define TEST_STRUCT(type, class, name) \ + current_type = InstanceType::type##_TYPE; \ + current = static_cast(current_type); \ + EXPECT_EQ(last + 1, current) \ + << " STRUCT_LIST is not ordered: " \ + << " last = " << static_cast(last) \ + << " vs. current = " << current_type; \ + last = current; + + STRUCT_LIST(TEST_STRUCT) +#undef TEST_STRUCT +} + +} // namespace internal +} // namespace v8 diff --git a/test/unittests/unittests.gyp b/test/unittests/unittests.gyp index 571e207f84..2f23bca209 100644 --- a/test/unittests/unittests.gyp +++ b/test/unittests/unittests.gyp @@ -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',