| Index: src/types.cc
|
| diff --git a/src/types.cc b/src/types.cc
|
| index 17a19b29e4263ac4ef2907c0c9ba45d62baa4cf5..485ba885187364ed2b99098865eec3197b2c47dc 100644
|
| --- a/src/types.cc
|
| +++ b/src/types.cc
|
| @@ -70,23 +70,23 @@ Handle<Type> Type::Iterator<T>::get_type() {
|
| }
|
|
|
| template<>
|
| -Handle<Map> Type::Iterator<Map>::Current() {
|
| +Handle<i::Map> Type::Iterator<i::Map>::Current() {
|
| return get_type()->as_class();
|
| }
|
|
|
| template<>
|
| -Handle<v8::internal::Object> Type::Iterator<v8::internal::Object>::Current() {
|
| +Handle<i::Object> Type::Iterator<i::Object>::Current() {
|
| return get_type()->as_constant();
|
| }
|
|
|
|
|
| template<>
|
| -bool Type::Iterator<Map>::matches(Handle<Type> type) {
|
| +bool Type::Iterator<i::Map>::matches(Handle<Type> type) {
|
| return type->is_class();
|
| }
|
|
|
| template<>
|
| -bool Type::Iterator<v8::internal::Object>::matches(Handle<Type> type) {
|
| +bool Type::Iterator<i::Object>::matches(Handle<Type> type) {
|
| return type->is_constant();
|
| }
|
|
|
| @@ -105,8 +105,8 @@ void Type::Iterator<T>::Advance() {
|
| index_ = -1;
|
| }
|
|
|
| -template class Type::Iterator<Map>;
|
| -template class Type::Iterator<v8::internal::Object>;
|
| +template class Type::Iterator<i::Map>;
|
| +template class Type::Iterator<i::Object>;
|
|
|
|
|
| // 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<v8::internal::Object> 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::OfCurrently(Handle<i::Object> 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.
|
| @@ -279,6 +297,14 @@ bool Type::SlowIs(Type* that) {
|
| }
|
|
|
|
|
| +bool Type::IsCurrently(Type* that) {
|
| + return this->Is(that) ||
|
| + (this->is_constant() && that->is_class() &&
|
| + this->as_constant()->IsHeapObject() &&
|
| + i::HeapObject::cast(*this->as_constant())->map() == *that->as_class());
|
| +}
|
| +
|
| +
|
| // Check this overlaps that.
|
| bool Type::Maybe(Type* that) {
|
| // Fast path for bitsets.
|
| @@ -374,11 +400,11 @@ Type* Type::Union(Handle<Type> type1, Handle<Type> 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 +476,11 @@ Type* Type::Intersect(Handle<Type> type1, Handle<Type> 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));
|
| }
|
| @@ -507,25 +533,35 @@ void Type::TypePrint() {
|
| }
|
|
|
|
|
| +const char* Type::bitset_name(int bitset) {
|
| + switch (bitset) {
|
| + #define PRINT_COMPOSED_TYPE(type, value) case k##type: return #type;
|
| + BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE)
|
| + #undef PRINT_COMPOSED_TYPE
|
| + default:
|
| + return NULL;
|
| + }
|
| +}
|
| +
|
| +
|
| void Type::TypePrint(FILE* out) {
|
| if (is_bitset()) {
|
| - int val = as_bitset();
|
| - const char* composed_name = GetComposedName(val);
|
| - if (composed_name != NULL) {
|
| - PrintF(out, "%s", composed_name);
|
| - return;
|
| - }
|
| - bool first_entry = true;
|
| - PrintF(out, "{");
|
| - for (unsigned i = 0; i < sizeof(val)*8; ++i) {
|
| - int mask = (1 << i);
|
| - if ((val & mask) != 0) {
|
| - if (!first_entry) PrintF(out, ",");
|
| - first_entry = false;
|
| - PrintF(out, "%s", GetPrimitiveName(mask));
|
| + int bitset = as_bitset();
|
| + const char* name = bitset_name(bitset);
|
| + if (name != NULL) {
|
| + PrintF(out, "%s", name);
|
| + } else {
|
| + bool is_first = true;
|
| + PrintF(out, "(");
|
| + for (int mask = 1; mask != 0; mask = mask << 1) {
|
| + if ((bitset & mask) != 0) {
|
| + if (!is_first) PrintF(out, " | ");
|
| + is_first = false;
|
| + PrintF(out, "%s", bitset_name(mask));
|
| + }
|
| }
|
| + PrintF(out, ")");
|
| }
|
| - PrintF(out, "}");
|
| } else if (is_constant()) {
|
| PrintF(out, "Constant(%p : ", static_cast<void*>(*as_constant()));
|
| from_bitset(LubBitset())->TypePrint(out);
|
| @@ -535,14 +571,14 @@ void Type::TypePrint(FILE* out) {
|
| from_bitset(LubBitset())->TypePrint(out);
|
| PrintF(")");
|
| } else if (is_union()) {
|
| - PrintF(out, "{");
|
| + PrintF(out, "(");
|
| Handle<Unioned> unioned = as_union();
|
| for (int i = 0; i < unioned->length(); ++i) {
|
| Handle<Type> type_i = union_get(unioned, i);
|
| - if (i > 0) PrintF(out, ",");
|
| + if (i > 0) PrintF(out, " | ");
|
| type_i->TypePrint(out);
|
| }
|
| - PrintF(out, "}");
|
| + PrintF(out, ")");
|
| }
|
| }
|
| #endif
|
|
|