| Index: src/types.cc
|
| diff --git a/src/types.cc b/src/types.cc
|
| index 5270c0ea6de09f4f4825f79f7cd3ebc08d14116c..d7a631d4ae18bc00e5b6a62380833baf9358cb5c 100644
|
| --- a/src/types.cc
|
| +++ b/src/types.cc
|
| @@ -148,6 +148,8 @@ int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) {
|
| return kArray;
|
| } else if (type->IsFunction()) {
|
| return kFunction;
|
| + } else if (type->IsContext()) {
|
| + return kInternal & kTaggedPtr;
|
| } else {
|
| UNREACHABLE();
|
| return kNone;
|
| @@ -158,16 +160,43 @@ int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) {
|
| template<class Config>
|
| int TypeImpl<Config>::BitsetType::Lub(i::Object* value) {
|
| DisallowHeapAllocation no_allocation;
|
| - if (value->IsSmi()) return kSignedSmall & kTaggedInt;
|
| - i::Map* map = i::HeapObject::cast(value)->map();
|
| - if (map->instance_type() == HEAP_NUMBER_TYPE) {
|
| - int32_t i;
|
| - uint32_t u;
|
| - return kTaggedPtr & (
|
| - value->ToInt32(&i) ? (Smi::IsValid(i) ? kSignedSmall : kOtherSigned32) :
|
| - value->ToUint32(&u) ? kUnsigned32 : kFloat);
|
| - }
|
| - return Lub(map);
|
| + if (value->IsNumber()) {
|
| + return Lub(value->Number()) & (value->IsSmi() ? kTaggedInt : kTaggedPtr);
|
| + }
|
| + return Lub(i::HeapObject::cast(value)->map());
|
| +}
|
| +
|
| +
|
| +template<class Config>
|
| +int TypeImpl<Config>::BitsetType::Lub(double value) {
|
| + DisallowHeapAllocation no_allocation;
|
| + if (i::IsMinusZero(value)) return kMinusZero;
|
| + if (std::isnan(value)) return kNaN;
|
| + if (IsUint32Double(value)) return Lub(FastD2UI(value));
|
| + if (IsInt32Double(value)) return Lub(FastD2I(value));
|
| + return kOtherNumber;
|
| +}
|
| +
|
| +
|
| +template<class Config>
|
| +int TypeImpl<Config>::BitsetType::Lub(int32_t value) {
|
| + if (value >= 0x40000000) {
|
| + return i::SmiValuesAre31Bits() ? kOtherUnsigned31 : kUnsignedSmall;
|
| + }
|
| + if (value >= 0) return kUnsignedSmall;
|
| + if (value >= -0x40000000) return kOtherSignedSmall;
|
| + return i::SmiValuesAre31Bits() ? kOtherSigned32 : kOtherSignedSmall;
|
| +}
|
| +
|
| +
|
| +template<class Config>
|
| +int TypeImpl<Config>::BitsetType::Lub(uint32_t value) {
|
| + DisallowHeapAllocation no_allocation;
|
| + if (value >= 0x80000000u) return kOtherUnsigned32;
|
| + if (value >= 0x40000000u) {
|
| + return i::SmiValuesAre31Bits() ? kOtherUnsigned31 : kUnsignedSmall;
|
| + }
|
| + return kUnsignedSmall;
|
| }
|
|
|
|
|
| @@ -211,7 +240,7 @@ int TypeImpl<Config>::BitsetType::Lub(i::Map* map) {
|
| return kInternal & kTaggedPtr;
|
| }
|
| case HEAP_NUMBER_TYPE:
|
| - return kFloat & kTaggedPtr;
|
| + return kNumber & kTaggedPtr;
|
| case JS_VALUE_TYPE:
|
| case JS_DATE_TYPE:
|
| case JS_OBJECT_TYPE:
|
| @@ -254,6 +283,7 @@ int TypeImpl<Config>::BitsetType::Lub(i::Map* map) {
|
| return kDetectable;
|
| case DECLARED_ACCESSOR_INFO_TYPE:
|
| case EXECUTABLE_ACCESSOR_INFO_TYPE:
|
| + case SHARED_FUNCTION_INFO_TYPE:
|
| case ACCESSOR_PAIR_TYPE:
|
| case FIXED_ARRAY_TYPE:
|
| case FOREIGN_TYPE:
|
| @@ -296,6 +326,10 @@ bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
|
| return this->IsConstant()
|
| && *this->AsConstant()->Value() == *that->AsConstant()->Value();
|
| }
|
| + if (that->IsContext()) {
|
| + return this->IsContext()
|
| + && this->AsContext()->Outer()->Equals(that->AsContext()->Outer());
|
| + }
|
| if (that->IsArray()) {
|
| return this->IsArray()
|
| && this->AsArray()->Element()->Equals(that->AsArray()->Element());
|
| @@ -411,6 +445,9 @@ bool TypeImpl<Config>::Maybe(TypeImpl* that) {
|
| return that->IsConstant()
|
| && *this->AsConstant()->Value() == *that->AsConstant()->Value();
|
| }
|
| + if (this->IsContext()) {
|
| + return this->Equals(that);
|
| + }
|
| if (this->IsArray()) {
|
| // There is no variance!
|
| return this->Equals(that);
|
| @@ -463,7 +500,8 @@ int TypeImpl<Config>::ExtendUnion(
|
| } else if (!type->IsBitset()) {
|
| // For all structural types, subtyping implies equivalence.
|
| ASSERT(type->IsClass() || type->IsConstant() ||
|
| - type->IsArray() || type->IsFunction());
|
| + type->IsArray() || type->IsFunction() ||
|
| + type->IsContext());
|
| if (!type->InUnion(result, old_size)) {
|
| result->Set(current_size++, type);
|
| }
|
| @@ -539,7 +577,7 @@ int TypeImpl<Config>::ExtendIntersection(
|
| } else if (!type->IsBitset()) {
|
| // For all structural types, subtyping implies equivalence.
|
| ASSERT(type->IsClass() || type->IsConstant() ||
|
| - type->IsArray() || type->IsFunction());
|
| + type->IsArray() || type->IsFunction() || type->IsContext());
|
| if (type->Is(other) && !type->InUnion(result, old_size)) {
|
| result->Set(current_size++, type);
|
| }
|
| @@ -608,6 +646,9 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert(
|
| return ClassType::New(type->AsClass()->Map(), region);
|
| } else if (type->IsConstant()) {
|
| return ConstantType::New(type->AsConstant()->Value(), region);
|
| + } else if (type->IsContext()) {
|
| + TypeHandle outer = Convert<OtherType>(type->AsContext()->Outer(), region);
|
| + return ContextType::New(outer, region);
|
| } else if (type->IsUnion()) {
|
| int length = type->AsUnion()->Length();
|
| UnionHandle unioned = UnionType::New(length, region);
|
| @@ -647,26 +688,18 @@ Representation Representation::FromType(Type* type) {
|
|
|
|
|
| template<class Config>
|
| -void TypeImpl<Config>::TypePrint(PrintDimension dim) {
|
| - TypePrint(stdout, dim);
|
| - PrintF(stdout, "\n");
|
| - Flush(stdout);
|
| -}
|
| -
|
| -
|
| -template<class Config>
|
| const char* TypeImpl<Config>::BitsetType::Name(int bitset) {
|
| switch (bitset) {
|
| - case kAny & kRepresentation: return "Any";
|
| - #define PRINT_COMPOSED_TYPE(type, value) \
|
| - case k##type & kRepresentation: return #type;
|
| - REPRESENTATION_BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE)
|
| - #undef PRINT_COMPOSED_TYPE
|
| + case REPRESENTATION(kAny): return "Any";
|
| + #define RETURN_NAMED_REPRESENTATION_TYPE(type, value) \
|
| + case REPRESENTATION(k##type): return #type;
|
| + REPRESENTATION_BITSET_TYPE_LIST(RETURN_NAMED_REPRESENTATION_TYPE)
|
| + #undef RETURN_NAMED_REPRESENTATION_TYPE
|
|
|
| - #define PRINT_COMPOSED_TYPE(type, value) \
|
| - case k##type & kSemantic: return #type;
|
| - SEMANTIC_BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE)
|
| - #undef PRINT_COMPOSED_TYPE
|
| + #define RETURN_NAMED_SEMANTIC_TYPE(type, value) \
|
| + case SEMANTIC(k##type): return #type;
|
| + SEMANTIC_BITSET_TYPE_LIST(RETURN_NAMED_SEMANTIC_TYPE)
|
| + #undef RETURN_NAMED_SEMANTIC_TYPE
|
|
|
| default:
|
| return NULL;
|
| @@ -675,97 +708,118 @@ const char* TypeImpl<Config>::BitsetType::Name(int bitset) {
|
|
|
|
|
| template<class Config>
|
| -void TypeImpl<Config>::BitsetType::BitsetTypePrint(FILE* out, int bitset) {
|
| +void TypeImpl<Config>::BitsetType::PrintTo(StringStream* stream, int bitset) {
|
| DisallowHeapAllocation no_allocation;
|
| const char* name = Name(bitset);
|
| if (name != NULL) {
|
| - PrintF(out, "%s", name);
|
| + stream->Add("%s", name);
|
| } else {
|
| static const int named_bitsets[] = {
|
| - #define BITSET_CONSTANT(type, value) k##type & kRepresentation,
|
| + #define BITSET_CONSTANT(type, value) REPRESENTATION(k##type),
|
| REPRESENTATION_BITSET_TYPE_LIST(BITSET_CONSTANT)
|
| #undef BITSET_CONSTANT
|
|
|
| - #define BITSET_CONSTANT(type, value) k##type & kSemantic,
|
| + #define BITSET_CONSTANT(type, value) SEMANTIC(k##type),
|
| SEMANTIC_BITSET_TYPE_LIST(BITSET_CONSTANT)
|
| #undef BITSET_CONSTANT
|
| };
|
|
|
| bool is_first = true;
|
| - PrintF(out, "(");
|
| + stream->Add("(");
|
| for (int i(ARRAY_SIZE(named_bitsets) - 1); bitset != 0 && i >= 0; --i) {
|
| int subset = named_bitsets[i];
|
| if ((bitset & subset) == subset) {
|
| - if (!is_first) PrintF(out, " | ");
|
| + if (!is_first) stream->Add(" | ");
|
| is_first = false;
|
| - PrintF(out, "%s", Name(subset));
|
| + stream->Add("%s", Name(subset));
|
| bitset -= subset;
|
| }
|
| }
|
| ASSERT(bitset == 0);
|
| - PrintF(out, ")");
|
| + stream->Add(")");
|
| }
|
| }
|
|
|
|
|
| template<class Config>
|
| -void TypeImpl<Config>::TypePrint(FILE* out, PrintDimension dim) {
|
| +void TypeImpl<Config>::PrintTo(StringStream* stream, PrintDimension dim) {
|
| DisallowHeapAllocation no_allocation;
|
| if (this->IsBitset()) {
|
| int bitset = this->AsBitset();
|
| switch (dim) {
|
| case BOTH_DIMS:
|
| - BitsetType::BitsetTypePrint(out, bitset & BitsetType::kSemantic);
|
| - PrintF(out, "/");
|
| - BitsetType::BitsetTypePrint(out, bitset & BitsetType::kRepresentation);
|
| + BitsetType::PrintTo(stream, SEMANTIC(bitset));
|
| + stream->Add("/");
|
| + BitsetType::PrintTo(stream, REPRESENTATION(bitset));
|
| break;
|
| case SEMANTIC_DIM:
|
| - BitsetType::BitsetTypePrint(out, bitset & BitsetType::kSemantic);
|
| + BitsetType::PrintTo(stream, SEMANTIC(bitset));
|
| break;
|
| case REPRESENTATION_DIM:
|
| - BitsetType::BitsetTypePrint(out, bitset & BitsetType::kRepresentation);
|
| + BitsetType::PrintTo(stream, REPRESENTATION(bitset));
|
| break;
|
| }
|
| } else if (this->IsConstant()) {
|
| - PrintF(out, "Constant(%p : ",
|
| + stream->Add("Constant(%p : ",
|
| static_cast<void*>(*this->AsConstant()->Value()));
|
| - BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim);
|
| - PrintF(out, ")");
|
| + BitsetType::New(BitsetType::Lub(this))->PrintTo(stream, dim);
|
| + stream->Add(")");
|
| } else if (this->IsClass()) {
|
| - PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass()->Map()));
|
| - BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim);
|
| - PrintF(out, ")");
|
| + stream->Add("Class(%p < ", static_cast<void*>(*this->AsClass()->Map()));
|
| + BitsetType::New(BitsetType::Lub(this))->PrintTo(stream, dim);
|
| + stream->Add(")");
|
| + } else if (this->IsContext()) {
|
| + stream->Add("Context(");
|
| + this->AsContext()->Outer()->PrintTo(stream, dim);
|
| + stream->Add(")");
|
| } else if (this->IsUnion()) {
|
| - PrintF(out, "(");
|
| + stream->Add("(");
|
| UnionHandle unioned = handle(this->AsUnion());
|
| for (int i = 0; i < unioned->Length(); ++i) {
|
| TypeHandle type_i = unioned->Get(i);
|
| - if (i > 0) PrintF(out, " | ");
|
| - type_i->TypePrint(out, dim);
|
| + if (i > 0) stream->Add(" | ");
|
| + type_i->PrintTo(stream, dim);
|
| }
|
| - PrintF(out, ")");
|
| + stream->Add(")");
|
| } else if (this->IsArray()) {
|
| - PrintF(out, "[");
|
| - AsArray()->Element()->TypePrint(out, dim);
|
| - PrintF(out, "]");
|
| + stream->Add("[");
|
| + AsArray()->Element()->PrintTo(stream, dim);
|
| + stream->Add("]");
|
| } else if (this->IsFunction()) {
|
| if (!this->AsFunction()->Receiver()->IsAny()) {
|
| - this->AsFunction()->Receiver()->TypePrint(out, dim);
|
| - PrintF(out, ".");
|
| + this->AsFunction()->Receiver()->PrintTo(stream, dim);
|
| + stream->Add(".");
|
| }
|
| - PrintF(out, "(");
|
| + stream->Add("(");
|
| for (int i = 0; i < this->AsFunction()->Arity(); ++i) {
|
| - if (i > 0) PrintF(out, ", ");
|
| - this->AsFunction()->Parameter(i)->TypePrint(out, dim);
|
| + if (i > 0) stream->Add(", ");
|
| + this->AsFunction()->Parameter(i)->PrintTo(stream, dim);
|
| }
|
| - PrintF(out, ")->");
|
| - this->AsFunction()->Result()->TypePrint(out, dim);
|
| + stream->Add(")->");
|
| + this->AsFunction()->Result()->PrintTo(stream, dim);
|
| } else {
|
| UNREACHABLE();
|
| }
|
| }
|
|
|
|
|
| +template<class Config>
|
| +void TypeImpl<Config>::TypePrint(FILE* out, PrintDimension dim) {
|
| + HeapStringAllocator allocator;
|
| + StringStream stream(&allocator);
|
| + PrintTo(&stream, dim);
|
| + stream.OutputToFile(out);
|
| +}
|
| +
|
| +
|
| +template<class Config>
|
| +void TypeImpl<Config>::TypePrint(PrintDimension dim) {
|
| + TypePrint(stdout, dim);
|
| + PrintF(stdout, "\n");
|
| + Flush(stdout);
|
| +}
|
| +
|
| +
|
| template class TypeImpl<ZoneTypeConfig>;
|
| template class TypeImpl<ZoneTypeConfig>::Iterator<i::Map>;
|
| template class TypeImpl<ZoneTypeConfig>::Iterator<i::Object>;
|
|
|