Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(772)

Unified Diff: src/objects-inl.h

Issue 2578573002: Add unittests to keep InstanceType lists in sync (Closed)
Patch Set: fix merge artifacts Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects.h ('k') | test/unittests/BUILD.gn » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects-inl.h
diff --git a/src/objects-inl.h b/src/objects-inl.h
index bfed673c9d83d1e5fa5ddec7cddde2ba6646aa74..ef5a591e3c7fed665d4b1174175fa6be3de94799 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<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) {
@@ -6815,8 +6737,6 @@ bool JSGeneratorObject::is_executing() const {
return continuation() == kGeneratorExecuting;
}
-TYPE_CHECKER(JSModuleNamespace, JS_MODULE_NAMESPACE_TYPE)
-
ACCESSORS(JSValue, value, Object, kValueOffset)
@@ -8464,8 +8384,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
« no previous file with comments | « src/objects.h ('k') | test/unittests/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698