From edb648277a103c35569bd44b79f2e84b388b0bb3 Mon Sep 17 00:00:00 2001 From: "rossberg@chromium.org" Date: Fri, 15 Nov 2013 15:14:09 +0000 Subject: [PATCH] Provide Type::Of and Type::CurrentOf operators R=verwaest@chromium.org BUG= Review URL: https://codereview.chromium.org/73193004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17796 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/types.cc | 236 ++++++++++++++++++++++++++++++++--------------------------- src/types.h | 49 ++++++++----- 2 files changed, 156 insertions(+), 129 deletions(-) diff --git a/src/types.cc b/src/types.cc index 17a19b2..9c576c0 100644 --- a/src/types.cc +++ b/src/types.cc @@ -70,23 +70,23 @@ Handle Type::Iterator::get_type() { } template<> -Handle Type::Iterator::Current() { +Handle Type::Iterator::Current() { return get_type()->as_class(); } template<> -Handle Type::Iterator::Current() { +Handle Type::Iterator::Current() { return get_type()->as_constant(); } template<> -bool Type::Iterator::matches(Handle type) { +bool Type::Iterator::matches(Handle type) { return type->is_class(); } template<> -bool Type::Iterator::matches(Handle type) { +bool Type::Iterator::matches(Handle type) { return type->is_constant(); } @@ -105,8 +105,8 @@ void Type::Iterator::Advance() { index_ = -1; } -template class Type::Iterator; -template class Type::Iterator; +template class Type::Iterator; +template class Type::Iterator; // Get the smallest bitset subsuming this type. @@ -120,106 +120,112 @@ int Type::LubBitset() { bitset |= union_get(unioned, i)->LubBitset(); } return bitset; + } else if (this->is_class()) { + return LubBitset(*this->as_class()); } else { - Map* map = NULL; - if (this->is_class()) { - map = *this->as_class(); - } else { - Handle value = this->as_constant(); - if (value->IsSmi()) return kSmi; - map = HeapObject::cast(*value)->map(); - if (map->instance_type() == HEAP_NUMBER_TYPE) { - int32_t i; - uint32_t u; - if (value->ToInt32(&i)) return Smi::IsValid(i) ? kSmi : kOtherSigned32; - if (value->ToUint32(&u)) return kUnsigned32; - return kDouble; - } - if (map->instance_type() == ODDBALL_TYPE) { - if (value->IsUndefined()) return kUndefined; - if (value->IsNull()) return kNull; - if (value->IsTrue() || value->IsFalse()) return kBoolean; - if (value->IsTheHole()) return kAny; // TODO(rossberg): kNone? - UNREACHABLE(); - } - } - switch (map->instance_type()) { - case STRING_TYPE: - case ASCII_STRING_TYPE: - case CONS_STRING_TYPE: - case CONS_ASCII_STRING_TYPE: - case SLICED_STRING_TYPE: - case SLICED_ASCII_STRING_TYPE: - case EXTERNAL_STRING_TYPE: - case EXTERNAL_ASCII_STRING_TYPE: - case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: - case SHORT_EXTERNAL_STRING_TYPE: - case SHORT_EXTERNAL_ASCII_STRING_TYPE: - case SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: - case INTERNALIZED_STRING_TYPE: - case ASCII_INTERNALIZED_STRING_TYPE: - case CONS_INTERNALIZED_STRING_TYPE: - case CONS_ASCII_INTERNALIZED_STRING_TYPE: - case EXTERNAL_INTERNALIZED_STRING_TYPE: - case EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE: - case EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE: - case SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE: - case SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE: - case SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE: - return kString; - case SYMBOL_TYPE: - return kSymbol; - case ODDBALL_TYPE: - return kOddball; - case HEAP_NUMBER_TYPE: - return kDouble; - case JS_VALUE_TYPE: - case JS_DATE_TYPE: - case JS_OBJECT_TYPE: - case JS_CONTEXT_EXTENSION_OBJECT_TYPE: - case JS_GENERATOR_OBJECT_TYPE: - case JS_MODULE_TYPE: - case JS_GLOBAL_OBJECT_TYPE: - case JS_BUILTINS_OBJECT_TYPE: - case JS_GLOBAL_PROXY_TYPE: - case JS_ARRAY_BUFFER_TYPE: - case JS_TYPED_ARRAY_TYPE: - case JS_DATA_VIEW_TYPE: - case JS_SET_TYPE: - case JS_MAP_TYPE: - case JS_WEAK_MAP_TYPE: - case JS_WEAK_SET_TYPE: - if (map->is_undetectable()) return kUndetectable; - return kOtherObject; - case JS_ARRAY_TYPE: - return kArray; - case JS_FUNCTION_TYPE: - return kFunction; - case JS_REGEXP_TYPE: - return kRegExp; - case JS_PROXY_TYPE: - case JS_FUNCTION_PROXY_TYPE: - return kProxy; - case MAP_TYPE: - // When compiling stub templates, the meta map is used as a place holder - // for the actual map with which the template is later instantiated. - // We treat it as a kind of type variable whose upper bound is Any. - // TODO(rossberg): for caching of CompareNilIC stubs to work correctly, - // we must exclude Undetectable here. This makes no sense, really, - // because it means that the template isn't actually parametric. - // Also, it doesn't apply elsewhere. 8-( - // We ought to find a cleaner solution for compiling stubs parameterised - // over type or class variables, esp ones with bounds... - return kDetectable; - case DECLARED_ACCESSOR_INFO_TYPE: - case EXECUTABLE_ACCESSOR_INFO_TYPE: - case ACCESSOR_PAIR_TYPE: - case FIXED_ARRAY_TYPE: - return kInternal; - default: - UNREACHABLE(); - return kNone; - } + return LubBitset(*this->as_constant()); + } +} + + +int Type::LubBitset(i::Object* value) { + if (value->IsSmi()) return kSmi; + i::Map* map = i::HeapObject::cast(value)->map(); + if (map->instance_type() == HEAP_NUMBER_TYPE) { + int32_t i; + uint32_t u; + if (value->ToInt32(&i)) return Smi::IsValid(i) ? kSmi : kOtherSigned32; + if (value->ToUint32(&u)) return kUnsigned32; + return kDouble; + } + if (map->instance_type() == ODDBALL_TYPE) { + if (value->IsUndefined()) return kUndefined; + if (value->IsNull()) return kNull; + if (value->IsBoolean()) return kBoolean; + if (value->IsTheHole()) return kAny; // TODO(rossberg): kNone? + UNREACHABLE(); + } + return Type::LubBitset(map); +} + + +int Type::LubBitset(i::Map* map) { + switch (map->instance_type()) { + case STRING_TYPE: + case ASCII_STRING_TYPE: + case CONS_STRING_TYPE: + case CONS_ASCII_STRING_TYPE: + case SLICED_STRING_TYPE: + case SLICED_ASCII_STRING_TYPE: + case EXTERNAL_STRING_TYPE: + case EXTERNAL_ASCII_STRING_TYPE: + case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: + case SHORT_EXTERNAL_STRING_TYPE: + case SHORT_EXTERNAL_ASCII_STRING_TYPE: + case SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: + case INTERNALIZED_STRING_TYPE: + case ASCII_INTERNALIZED_STRING_TYPE: + case CONS_INTERNALIZED_STRING_TYPE: + case CONS_ASCII_INTERNALIZED_STRING_TYPE: + case EXTERNAL_INTERNALIZED_STRING_TYPE: + case EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE: + case EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE: + case SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE: + case SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE: + case SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE: + return kString; + case SYMBOL_TYPE: + return kSymbol; + case ODDBALL_TYPE: + return kOddball; + case HEAP_NUMBER_TYPE: + return kDouble; + case JS_VALUE_TYPE: + case JS_DATE_TYPE: + case JS_OBJECT_TYPE: + case JS_CONTEXT_EXTENSION_OBJECT_TYPE: + case JS_GENERATOR_OBJECT_TYPE: + case JS_MODULE_TYPE: + case JS_GLOBAL_OBJECT_TYPE: + case JS_BUILTINS_OBJECT_TYPE: + case JS_GLOBAL_PROXY_TYPE: + case JS_ARRAY_BUFFER_TYPE: + case JS_TYPED_ARRAY_TYPE: + case JS_DATA_VIEW_TYPE: + case JS_SET_TYPE: + case JS_MAP_TYPE: + case JS_WEAK_MAP_TYPE: + case JS_WEAK_SET_TYPE: + if (map->is_undetectable()) return kUndetectable; + return kOtherObject; + case JS_ARRAY_TYPE: + return kArray; + case JS_FUNCTION_TYPE: + return kFunction; + case JS_REGEXP_TYPE: + return kRegExp; + case JS_PROXY_TYPE: + case JS_FUNCTION_PROXY_TYPE: + return kProxy; + case MAP_TYPE: + // When compiling stub templates, the meta map is used as a place holder + // for the actual map with which the template is later instantiated. + // We treat it as a kind of type variable whose upper bound is Any. + // TODO(rossberg): for caching of CompareNilIC stubs to work correctly, + // we must exclude Undetectable here. This makes no sense, really, + // because it means that the template isn't actually parametric. + // Also, it doesn't apply elsewhere. 8-( + // We ought to find a cleaner solution for compiling stubs parameterised + // over type or class variables, esp ones with bounds... + return kDetectable; + case DECLARED_ACCESSOR_INFO_TYPE: + case EXECUTABLE_ACCESSOR_INFO_TYPE: + case ACCESSOR_PAIR_TYPE: + case FIXED_ARRAY_TYPE: + return kInternal; + default: + UNREACHABLE(); + return kNone; } } @@ -237,6 +243,18 @@ int Type::GlbBitset() { } +// Most precise _current_ type of a value (usually its class). +Type* Type::CurrentOf(Handle value) { + if (value->IsSmi()) return Smi(); + i::Map* map = i::HeapObject::cast(*value)->map(); + if (map->instance_type() == HEAP_NUMBER_TYPE || + map->instance_type() == ODDBALL_TYPE) { + return Type::Of(value); + } + return Class(i::handle(map)); +} + + // Check this <= that. bool Type::SlowIs(Type* that) { // Fast path for bitsets. @@ -374,11 +392,11 @@ Type* Type::Union(Handle type1, Handle type2) { Isolate* isolate = NULL; int size = type1->is_bitset() || type2->is_bitset() ? 1 : 0; if (!type1->is_bitset()) { - isolate = HeapObject::cast(*type1)->GetIsolate(); + isolate = i::HeapObject::cast(*type1)->GetIsolate(); size += (type1->is_union() ? type1->as_union()->length() : 1); } if (!type2->is_bitset()) { - isolate = HeapObject::cast(*type2)->GetIsolate(); + isolate = i::HeapObject::cast(*type2)->GetIsolate(); size += (type2->is_union() ? type2->as_union()->length() : 1); } ASSERT(isolate != NULL); @@ -450,11 +468,11 @@ Type* Type::Intersect(Handle type1, Handle type2) { Isolate* isolate = NULL; int size = 0; if (!type1->is_bitset()) { - isolate = HeapObject::cast(*type1)->GetIsolate(); + isolate = i::HeapObject::cast(*type1)->GetIsolate(); size = (type1->is_union() ? type1->as_union()->length() : 2); } if (!type2->is_bitset()) { - isolate = HeapObject::cast(*type2)->GetIsolate(); + isolate = i::HeapObject::cast(*type2)->GetIsolate(); int size2 = (type2->is_union() ? type2->as_union()->length() : 2); size = (size == 0 ? size2 : Min(size, size2)); } diff --git a/src/types.h b/src/types.h index 5d437e2..2e21a9e 100644 --- a/src/types.h +++ b/src/types.h @@ -144,11 +144,11 @@ class Type : public Object { TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) #undef DEFINE_TYPE_CONSTRUCTOR - static Type* Class(Handle map) { return from_handle(map); } - static Type* Constant(Handle value) { + static Type* Class(Handle map) { return from_handle(map); } + static Type* Constant(Handle value) { return Constant(value, value->GetIsolate()); } - static Type* Constant(Handle value, Isolate* isolate) { + static Type* Constant(Handle value, Isolate* isolate) { return from_handle(isolate->factory()->NewBox(value)); } @@ -156,6 +156,11 @@ class Type : public Object { static Type* Intersect(Handle type1, Handle type2); static Type* Optional(Handle type); // type \/ Undefined + static Type* Of(Handle value) { + return from_bitset(LubBitset(*value)); + } + static Type* CurrentOf(Handle value); + bool Is(Type* that) { return (this == that) ? true : SlowIs(that); } bool Is(Handle that) { return this->Is(*that); } bool Maybe(Type* that); @@ -163,8 +168,8 @@ class Type : public Object { bool IsClass() { return is_class(); } bool IsConstant() { return is_constant(); } - Handle AsClass() { return as_class(); } - Handle AsConstant() { return as_constant(); } + Handle AsClass() { return as_class(); } + Handle AsConstant() { return as_constant(); } int NumClasses(); int NumConstants(); @@ -191,16 +196,16 @@ class Type : public Object { int index_; }; - Iterator Classes() { - if (this->is_bitset()) return Iterator(); - return Iterator(this->handle()); + Iterator Classes() { + if (this->is_bitset()) return Iterator(); + return Iterator(this->handle()); } - Iterator Constants() { - if (this->is_bitset()) return Iterator(); - return Iterator(this->handle()); + Iterator Constants() { + if (this->is_bitset()) return Iterator(); + return Iterator(this->handle()); } - static Type* cast(v8::internal::Object* object) { + static Type* cast(i::Object* object) { Type* t = static_cast(object); ASSERT(t->is_bitset() || t->is_class() || t->is_constant() || t->is_union()); @@ -235,24 +240,24 @@ class Type : public Object { bool SlowIs(Type* that); int as_bitset() { return Smi::cast(this)->value(); } - Handle as_class() { return Handle::cast(handle()); } - Handle as_constant() { - Handle box = Handle::cast(handle()); - return v8::internal::handle(box->value(), box->GetIsolate()); + Handle as_class() { return Handle::cast(handle()); } + Handle as_constant() { + Handle box = Handle::cast(handle()); + return i::handle(box->value(), box->GetIsolate()); } Handle as_union() { return Handle::cast(handle()); } Handle handle() { return handle_via_isolate_of(this); } Handle handle_via_isolate_of(Type* type) { ASSERT(type->IsHeapObject()); - return v8::internal::handle(this, HeapObject::cast(type)->GetIsolate()); + return i::handle(this, i::HeapObject::cast(type)->GetIsolate()); } static Type* from_bitset(int bitset) { - return static_cast(Object::cast(Smi::FromInt(bitset))); + return static_cast(i::Object::cast(i::Smi::FromInt(bitset))); } - static Type* from_handle(Handle handle) { - return static_cast(Object::cast(*handle)); + static Type* from_handle(Handle handle) { + return static_cast(i::Object::cast(*handle)); } static Handle union_get(Handle unioned, int i) { @@ -263,6 +268,10 @@ class Type : public Object { int LubBitset(); // least upper bound that's a bitset int GlbBitset(); // greatest lower bound that's a bitset + + static int LubBitset(i::Object* value); + static int LubBitset(i::Map* map); + bool InUnion(Handle unioned, int current_size); int ExtendUnion(Handle unioned, int current_size); int ExtendIntersection( -- 2.7.4