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 |