Commit dbf7d852 authored by rossberg@chromium.org's avatar rossberg@chromium.org

Various extensions to types

R=bmeurer@chromium.org
BUG=

Review URL: https://codereview.chromium.org/296213005

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21494 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 6ed0102b
...@@ -163,6 +163,17 @@ static inline bool IsInt32Double(double value) { ...@@ -163,6 +163,17 @@ static inline bool IsInt32Double(double value) {
} }
// UInteger32 is an integer that can be represented as an unsigned 32-bit
// integer. It has to be in the range [0, 2^32 - 1].
// We also have to check for negative 0 as it is not a UInteger32.
static inline bool IsUint32Double(double value) {
return !IsMinusZero(value) &&
value >= 0 &&
value <= kMaxUInt32 &&
value == FastUI2D(FastD2UI(value));
}
// Convert from Number object to C integer. // Convert from Number object to C integer.
inline int32_t NumberToInt32(Object* number) { inline int32_t NumberToInt32(Object* number) {
if (number->IsSmi()) return Smi::cast(number)->value(); if (number->IsSmi()) return Smi::cast(number)->value();
......
...@@ -9503,7 +9503,7 @@ HValue* HGraphBuilder::TruncateToNumber(HValue* value, Type** expected) { ...@@ -9503,7 +9503,7 @@ HValue* HGraphBuilder::TruncateToNumber(HValue* value, Type** expected) {
if (expected_obj->Is(Type::Undefined(zone()))) { if (expected_obj->Is(Type::Undefined(zone()))) {
// This is already done by HChange. // This is already done by HChange.
*expected = Type::Union(expected_number, Type::Float(zone()), zone()); *expected = Type::Union(expected_number, Type::Number(zone()), zone());
return value; return value;
} }
......
...@@ -20,7 +20,7 @@ template<class Config> ...@@ -20,7 +20,7 @@ template<class Config>
TypeImpl<Config>* TypeImpl<Config>::cast(typename Config::Base* object) { TypeImpl<Config>* TypeImpl<Config>::cast(typename Config::Base* object) {
TypeImpl* t = static_cast<TypeImpl*>(object); TypeImpl* t = static_cast<TypeImpl*>(object);
ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() ||
t->IsUnion() || t->IsArray() || t->IsFunction()); t->IsUnion() || t->IsArray() || t->IsFunction() || t->IsContext());
return t; return t;
} }
......
...@@ -148,6 +148,8 @@ int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { ...@@ -148,6 +148,8 @@ int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) {
return kArray; return kArray;
} else if (type->IsFunction()) { } else if (type->IsFunction()) {
return kFunction; return kFunction;
} else if (type->IsContext()) {
return kInternal & kTaggedPtr;
} else { } else {
UNREACHABLE(); UNREACHABLE();
return kNone; return kNone;
...@@ -158,16 +160,43 @@ int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { ...@@ -158,16 +160,43 @@ int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) {
template<class Config> template<class Config>
int TypeImpl<Config>::BitsetType::Lub(i::Object* value) { int TypeImpl<Config>::BitsetType::Lub(i::Object* value) {
DisallowHeapAllocation no_allocation; DisallowHeapAllocation no_allocation;
if (value->IsSmi()) return kSignedSmall & kTaggedInt; if (value->IsNumber()) {
i::Map* map = i::HeapObject::cast(value)->map(); return Lub(value->Number()) & (value->IsSmi() ? kTaggedInt : kTaggedPtr);
if (map->instance_type() == HEAP_NUMBER_TYPE) { }
int32_t i; return Lub(i::HeapObject::cast(value)->map());
uint32_t u; }
return kTaggedPtr & (
value->ToInt32(&i) ? (Smi::IsValid(i) ? kSignedSmall : kOtherSigned32) :
value->ToUint32(&u) ? kUnsigned32 : kFloat); template<class Config>
} int TypeImpl<Config>::BitsetType::Lub(double value) {
return Lub(map); 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) { ...@@ -211,7 +240,7 @@ int TypeImpl<Config>::BitsetType::Lub(i::Map* map) {
return kInternal & kTaggedPtr; return kInternal & kTaggedPtr;
} }
case HEAP_NUMBER_TYPE: case HEAP_NUMBER_TYPE:
return kFloat & kTaggedPtr; return kNumber & kTaggedPtr;
case JS_VALUE_TYPE: case JS_VALUE_TYPE:
case JS_DATE_TYPE: case JS_DATE_TYPE:
case JS_OBJECT_TYPE: case JS_OBJECT_TYPE:
...@@ -254,6 +283,7 @@ int TypeImpl<Config>::BitsetType::Lub(i::Map* map) { ...@@ -254,6 +283,7 @@ int TypeImpl<Config>::BitsetType::Lub(i::Map* map) {
return kDetectable; return kDetectable;
case DECLARED_ACCESSOR_INFO_TYPE: case DECLARED_ACCESSOR_INFO_TYPE:
case EXECUTABLE_ACCESSOR_INFO_TYPE: case EXECUTABLE_ACCESSOR_INFO_TYPE:
case SHARED_FUNCTION_INFO_TYPE:
case ACCESSOR_PAIR_TYPE: case ACCESSOR_PAIR_TYPE:
case FIXED_ARRAY_TYPE: case FIXED_ARRAY_TYPE:
case FOREIGN_TYPE: case FOREIGN_TYPE:
...@@ -296,6 +326,10 @@ bool TypeImpl<Config>::SlowIs(TypeImpl* that) { ...@@ -296,6 +326,10 @@ bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
return this->IsConstant() return this->IsConstant()
&& *this->AsConstant()->Value() == *that->AsConstant()->Value(); && *this->AsConstant()->Value() == *that->AsConstant()->Value();
} }
if (that->IsContext()) {
return this->IsContext()
&& this->AsContext()->Outer()->Equals(that->AsContext()->Outer());
}
if (that->IsArray()) { if (that->IsArray()) {
return this->IsArray() return this->IsArray()
&& this->AsArray()->Element()->Equals(that->AsArray()->Element()); && this->AsArray()->Element()->Equals(that->AsArray()->Element());
...@@ -411,6 +445,9 @@ bool TypeImpl<Config>::Maybe(TypeImpl* that) { ...@@ -411,6 +445,9 @@ bool TypeImpl<Config>::Maybe(TypeImpl* that) {
return that->IsConstant() return that->IsConstant()
&& *this->AsConstant()->Value() == *that->AsConstant()->Value(); && *this->AsConstant()->Value() == *that->AsConstant()->Value();
} }
if (this->IsContext()) {
return this->Equals(that);
}
if (this->IsArray()) { if (this->IsArray()) {
// There is no variance! // There is no variance!
return this->Equals(that); return this->Equals(that);
...@@ -463,7 +500,8 @@ int TypeImpl<Config>::ExtendUnion( ...@@ -463,7 +500,8 @@ int TypeImpl<Config>::ExtendUnion(
} else if (!type->IsBitset()) { } else if (!type->IsBitset()) {
// For all structural types, subtyping implies equivalence. // For all structural types, subtyping implies equivalence.
ASSERT(type->IsClass() || type->IsConstant() || ASSERT(type->IsClass() || type->IsConstant() ||
type->IsArray() || type->IsFunction()); type->IsArray() || type->IsFunction() ||
type->IsContext());
if (!type->InUnion(result, old_size)) { if (!type->InUnion(result, old_size)) {
result->Set(current_size++, type); result->Set(current_size++, type);
} }
...@@ -539,7 +577,7 @@ int TypeImpl<Config>::ExtendIntersection( ...@@ -539,7 +577,7 @@ int TypeImpl<Config>::ExtendIntersection(
} else if (!type->IsBitset()) { } else if (!type->IsBitset()) {
// For all structural types, subtyping implies equivalence. // For all structural types, subtyping implies equivalence.
ASSERT(type->IsClass() || type->IsConstant() || ASSERT(type->IsClass() || type->IsConstant() ||
type->IsArray() || type->IsFunction()); type->IsArray() || type->IsFunction() || type->IsContext());
if (type->Is(other) && !type->InUnion(result, old_size)) { if (type->Is(other) && !type->InUnion(result, old_size)) {
result->Set(current_size++, type); result->Set(current_size++, type);
} }
...@@ -608,6 +646,9 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert( ...@@ -608,6 +646,9 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert(
return ClassType::New(type->AsClass()->Map(), region); return ClassType::New(type->AsClass()->Map(), region);
} else if (type->IsConstant()) { } else if (type->IsConstant()) {
return ConstantType::New(type->AsConstant()->Value(), region); 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()) { } else if (type->IsUnion()) {
int length = type->AsUnion()->Length(); int length = type->AsUnion()->Length();
UnionHandle unioned = UnionType::New(length, region); UnionHandle unioned = UnionType::New(length, region);
...@@ -646,27 +687,19 @@ Representation Representation::FromType(Type* type) { ...@@ -646,27 +687,19 @@ 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> template<class Config>
const char* TypeImpl<Config>::BitsetType::Name(int bitset) { const char* TypeImpl<Config>::BitsetType::Name(int bitset) {
switch (bitset) { switch (bitset) {
case kAny & kRepresentation: return "Any"; case REPRESENTATION(kAny): return "Any";
#define PRINT_COMPOSED_TYPE(type, value) \ #define RETURN_NAMED_REPRESENTATION_TYPE(type, value) \
case k##type & kRepresentation: return #type; case REPRESENTATION(k##type): return #type;
REPRESENTATION_BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE) REPRESENTATION_BITSET_TYPE_LIST(RETURN_NAMED_REPRESENTATION_TYPE)
#undef PRINT_COMPOSED_TYPE #undef RETURN_NAMED_REPRESENTATION_TYPE
#define PRINT_COMPOSED_TYPE(type, value) \ #define RETURN_NAMED_SEMANTIC_TYPE(type, value) \
case k##type & kSemantic: return #type; case SEMANTIC(k##type): return #type;
SEMANTIC_BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE) SEMANTIC_BITSET_TYPE_LIST(RETURN_NAMED_SEMANTIC_TYPE)
#undef PRINT_COMPOSED_TYPE #undef RETURN_NAMED_SEMANTIC_TYPE
default: default:
return NULL; return NULL;
...@@ -675,97 +708,118 @@ const char* TypeImpl<Config>::BitsetType::Name(int bitset) { ...@@ -675,97 +708,118 @@ const char* TypeImpl<Config>::BitsetType::Name(int bitset) {
template<class Config> template<class Config>
void TypeImpl<Config>::BitsetType::BitsetTypePrint(FILE* out, int bitset) { void TypeImpl<Config>::BitsetType::PrintTo(StringStream* stream, int bitset) {
DisallowHeapAllocation no_allocation; DisallowHeapAllocation no_allocation;
const char* name = Name(bitset); const char* name = Name(bitset);
if (name != NULL) { if (name != NULL) {
PrintF(out, "%s", name); stream->Add("%s", name);
} else { } else {
static const int named_bitsets[] = { 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) REPRESENTATION_BITSET_TYPE_LIST(BITSET_CONSTANT)
#undef 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) SEMANTIC_BITSET_TYPE_LIST(BITSET_CONSTANT)
#undef BITSET_CONSTANT #undef BITSET_CONSTANT
}; };
bool is_first = true; bool is_first = true;
PrintF(out, "("); stream->Add("(");
for (int i(ARRAY_SIZE(named_bitsets) - 1); bitset != 0 && i >= 0; --i) { for (int i(ARRAY_SIZE(named_bitsets) - 1); bitset != 0 && i >= 0; --i) {
int subset = named_bitsets[i]; int subset = named_bitsets[i];
if ((bitset & subset) == subset) { if ((bitset & subset) == subset) {
if (!is_first) PrintF(out, " | "); if (!is_first) stream->Add(" | ");
is_first = false; is_first = false;
PrintF(out, "%s", Name(subset)); stream->Add("%s", Name(subset));
bitset -= subset; bitset -= subset;
} }
} }
ASSERT(bitset == 0); ASSERT(bitset == 0);
PrintF(out, ")"); stream->Add(")");
} }
} }
template<class Config> template<class Config>
void TypeImpl<Config>::TypePrint(FILE* out, PrintDimension dim) { void TypeImpl<Config>::PrintTo(StringStream* stream, PrintDimension dim) {
DisallowHeapAllocation no_allocation; DisallowHeapAllocation no_allocation;
if (this->IsBitset()) { if (this->IsBitset()) {
int bitset = this->AsBitset(); int bitset = this->AsBitset();
switch (dim) { switch (dim) {
case BOTH_DIMS: case BOTH_DIMS:
BitsetType::BitsetTypePrint(out, bitset & BitsetType::kSemantic); BitsetType::PrintTo(stream, SEMANTIC(bitset));
PrintF(out, "/"); stream->Add("/");
BitsetType::BitsetTypePrint(out, bitset & BitsetType::kRepresentation); BitsetType::PrintTo(stream, REPRESENTATION(bitset));
break; break;
case SEMANTIC_DIM: case SEMANTIC_DIM:
BitsetType::BitsetTypePrint(out, bitset & BitsetType::kSemantic); BitsetType::PrintTo(stream, SEMANTIC(bitset));
break; break;
case REPRESENTATION_DIM: case REPRESENTATION_DIM:
BitsetType::BitsetTypePrint(out, bitset & BitsetType::kRepresentation); BitsetType::PrintTo(stream, REPRESENTATION(bitset));
break; break;
} }
} else if (this->IsConstant()) { } else if (this->IsConstant()) {
PrintF(out, "Constant(%p : ", stream->Add("Constant(%p : ",
static_cast<void*>(*this->AsConstant()->Value())); static_cast<void*>(*this->AsConstant()->Value()));
BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim); BitsetType::New(BitsetType::Lub(this))->PrintTo(stream, dim);
PrintF(out, ")"); stream->Add(")");
} else if (this->IsClass()) { } else if (this->IsClass()) {
PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass()->Map())); stream->Add("Class(%p < ", static_cast<void*>(*this->AsClass()->Map()));
BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim); BitsetType::New(BitsetType::Lub(this))->PrintTo(stream, dim);
PrintF(out, ")"); stream->Add(")");
} else if (this->IsContext()) {
stream->Add("Context(");
this->AsContext()->Outer()->PrintTo(stream, dim);
stream->Add(")");
} else if (this->IsUnion()) { } else if (this->IsUnion()) {
PrintF(out, "("); stream->Add("(");
UnionHandle unioned = handle(this->AsUnion()); UnionHandle unioned = handle(this->AsUnion());
for (int i = 0; i < unioned->Length(); ++i) { for (int i = 0; i < unioned->Length(); ++i) {
TypeHandle type_i = unioned->Get(i); TypeHandle type_i = unioned->Get(i);
if (i > 0) PrintF(out, " | "); if (i > 0) stream->Add(" | ");
type_i->TypePrint(out, dim); type_i->PrintTo(stream, dim);
} }
PrintF(out, ")"); stream->Add(")");
} else if (this->IsArray()) { } else if (this->IsArray()) {
PrintF(out, "["); stream->Add("[");
AsArray()->Element()->TypePrint(out, dim); AsArray()->Element()->PrintTo(stream, dim);
PrintF(out, "]"); stream->Add("]");
} else if (this->IsFunction()) { } else if (this->IsFunction()) {
if (!this->AsFunction()->Receiver()->IsAny()) { if (!this->AsFunction()->Receiver()->IsAny()) {
this->AsFunction()->Receiver()->TypePrint(out, dim); this->AsFunction()->Receiver()->PrintTo(stream, dim);
PrintF(out, "."); stream->Add(".");
} }
PrintF(out, "("); stream->Add("(");
for (int i = 0; i < this->AsFunction()->Arity(); ++i) { for (int i = 0; i < this->AsFunction()->Arity(); ++i) {
if (i > 0) PrintF(out, ", "); if (i > 0) stream->Add(", ");
this->AsFunction()->Parameter(i)->TypePrint(out, dim); this->AsFunction()->Parameter(i)->PrintTo(stream, dim);
} }
PrintF(out, ")->"); stream->Add(")->");
this->AsFunction()->Result()->TypePrint(out, dim); this->AsFunction()->Result()->PrintTo(stream, dim);
} else { } else {
UNREACHABLE(); 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>;
template class TypeImpl<ZoneTypeConfig>::Iterator<i::Map>; template class TypeImpl<ZoneTypeConfig>::Iterator<i::Map>;
template class TypeImpl<ZoneTypeConfig>::Iterator<i::Object>; template class TypeImpl<ZoneTypeConfig>::Iterator<i::Object>;
......
...@@ -45,10 +45,14 @@ namespace internal { ...@@ -45,10 +45,14 @@ namespace internal {
// Constant(x) < T iff instance_type(map(x)) < T // Constant(x) < T iff instance_type(map(x)) < T
// Array(T) < Array // Array(T) < Array
// Function(R, S, T0, T1, ...) < Function // Function(R, S, T0, T1, ...) < Function
// Context(T) < Internal
// //
// Both structural Array and Function types are invariant in all parameters. // Both structural Array and Function types are invariant in all parameters;
// Relaxing this would make Union and Intersect operations more involved. // relaxing this would make Union and Intersect operations more involved.
// Note that Constant(x) < Class(map(x)) does _not_ hold, since x's map can // There is no subtyping relation between Array, Function, or Context types
// and respective Constant types, since these types cannot be reconstructed
// for arbitrary heap values.
// Note also that Constant(x) < Class(map(x)) does _not_ hold, since x's map can
// change! (Its instance type cannot, however.) // change! (Its instance type cannot, however.)
// TODO(rossberg): the latter is not currently true for proxies, because of fix, // TODO(rossberg): the latter is not currently true for proxies, because of fix,
// but will hold once we implement direct proxies. // but will hold once we implement direct proxies.
...@@ -129,14 +133,15 @@ namespace internal { ...@@ -129,14 +133,15 @@ namespace internal {
#define MASK_BITSET_TYPE_LIST(V) \ #define MASK_BITSET_TYPE_LIST(V) \
V(Representation, static_cast<int>(0xff800000)) \ V(Representation, static_cast<int>(0xffc00000)) \
V(Semantic, static_cast<int>(0x007fffff)) V(Semantic, static_cast<int>(0x003fffff))
#define REPRESENTATION(k) ((k) & kRepresentation) #define REPRESENTATION(k) ((k) & BitsetType::kRepresentation)
#define SEMANTIC(k) ((k) & kSemantic) #define SEMANTIC(k) ((k) & BitsetType::kSemantic)
#define REPRESENTATION_BITSET_TYPE_LIST(V) \ #define REPRESENTATION_BITSET_TYPE_LIST(V) \
V(None, 0) \ V(None, 0) \
V(UntaggedInt1, 1 << 22 | kSemantic) \
V(UntaggedInt8, 1 << 23 | kSemantic) \ V(UntaggedInt8, 1 << 23 | kSemantic) \
V(UntaggedInt16, 1 << 24 | kSemantic) \ V(UntaggedInt16, 1 << 24 | kSemantic) \
V(UntaggedInt32, 1 << 25 | kSemantic) \ V(UntaggedInt32, 1 << 25 | kSemantic) \
...@@ -146,7 +151,8 @@ namespace internal { ...@@ -146,7 +151,8 @@ namespace internal {
V(TaggedInt, 1 << 29 | kSemantic) \ V(TaggedInt, 1 << 29 | kSemantic) \
V(TaggedPtr, -1 << 30 | kSemantic) /* MSB has to be sign-extended */ \ V(TaggedPtr, -1 << 30 | kSemantic) /* MSB has to be sign-extended */ \
\ \
V(UntaggedInt, kUntaggedInt8 | kUntaggedInt16 | kUntaggedInt32) \ V(UntaggedInt, kUntaggedInt1 | kUntaggedInt8 | \
kUntaggedInt16 | kUntaggedInt32) \
V(UntaggedFloat, kUntaggedFloat32 | kUntaggedFloat64) \ V(UntaggedFloat, kUntaggedFloat32 | kUntaggedFloat64) \
V(UntaggedNumber, kUntaggedInt | kUntaggedFloat) \ V(UntaggedNumber, kUntaggedInt | kUntaggedFloat) \
V(Untagged, kUntaggedNumber | kUntaggedPtr) \ V(Untagged, kUntaggedNumber | kUntaggedPtr) \
...@@ -156,27 +162,36 @@ namespace internal { ...@@ -156,27 +162,36 @@ namespace internal {
V(Null, 1 << 0 | REPRESENTATION(kTaggedPtr)) \ V(Null, 1 << 0 | REPRESENTATION(kTaggedPtr)) \
V(Undefined, 1 << 1 | REPRESENTATION(kTaggedPtr)) \ V(Undefined, 1 << 1 | REPRESENTATION(kTaggedPtr)) \
V(Boolean, 1 << 2 | REPRESENTATION(kTaggedPtr)) \ V(Boolean, 1 << 2 | REPRESENTATION(kTaggedPtr)) \
V(SignedSmall, 1 << 3 | REPRESENTATION(kTagged | kUntaggedNumber)) \ V(UnsignedSmall, 1 << 3 | REPRESENTATION(kTagged | kUntaggedNumber)) \
V(OtherSigned32, 1 << 4 | REPRESENTATION(kTagged | kUntaggedNumber)) \ V(OtherSignedSmall, 1 << 4 | REPRESENTATION(kTagged | kUntaggedNumber)) \
V(Unsigned32, 1 << 5 | REPRESENTATION(kTagged | kUntaggedNumber)) \ V(OtherUnsigned31, 1 << 5 | REPRESENTATION(kTagged | kUntaggedNumber)) \
V(Float, 1 << 6 | REPRESENTATION(kTagged | kUntaggedNumber)) \ V(OtherUnsigned32, 1 << 6 | REPRESENTATION(kTagged | kUntaggedNumber)) \
V(Symbol, 1 << 7 | REPRESENTATION(kTaggedPtr)) \ V(OtherSigned32, 1 << 7 | REPRESENTATION(kTagged | kUntaggedNumber)) \
V(InternalizedString, 1 << 8 | REPRESENTATION(kTaggedPtr)) \ V(MinusZero, 1 << 8 | REPRESENTATION(kTagged | kUntaggedNumber)) \
V(OtherString, 1 << 9 | REPRESENTATION(kTaggedPtr)) \ V(NaN, 1 << 9 | REPRESENTATION(kTagged | kUntaggedNumber)) \
V(Undetectable, 1 << 10 | REPRESENTATION(kTaggedPtr)) \ V(OtherNumber, 1 << 10 | REPRESENTATION(kTagged | kUntaggedNumber)) \
V(Array, 1 << 11 | REPRESENTATION(kTaggedPtr)) \ V(Symbol, 1 << 11 | REPRESENTATION(kTaggedPtr)) \
V(Function, 1 << 12 | REPRESENTATION(kTaggedPtr)) \ V(InternalizedString, 1 << 12 | REPRESENTATION(kTaggedPtr)) \
V(RegExp, 1 << 13 | REPRESENTATION(kTaggedPtr)) \ V(OtherString, 1 << 13 | REPRESENTATION(kTaggedPtr)) \
V(OtherObject, 1 << 14 | REPRESENTATION(kTaggedPtr)) \ V(Undetectable, 1 << 14 | REPRESENTATION(kTaggedPtr)) \
V(Proxy, 1 << 15 | REPRESENTATION(kTaggedPtr)) \ V(Array, 1 << 15 | REPRESENTATION(kTaggedPtr)) \
V(Internal, 1 << 16 | REPRESENTATION(kTagged | kUntagged)) \ V(Buffer, 1 << 16 | REPRESENTATION(kTaggedPtr)) \
V(Function, 1 << 17 | REPRESENTATION(kTaggedPtr)) \
V(RegExp, 1 << 18 | REPRESENTATION(kTaggedPtr)) \
V(OtherObject, 1 << 19 | REPRESENTATION(kTaggedPtr)) \
V(Proxy, 1 << 20 | REPRESENTATION(kTaggedPtr)) \
V(Internal, 1 << 21 | REPRESENTATION(kTagged | kUntagged)) \
\ \
V(Signed32, kSignedSmall | kOtherSigned32) \ V(SignedSmall, kUnsignedSmall | kOtherSignedSmall) \
V(Number, kSigned32 | kUnsigned32 | kFloat) \ V(Signed32, kSignedSmall | kOtherUnsigned31 | kOtherSigned32) \
V(Unsigned32, kUnsignedSmall | kOtherUnsigned31 | kOtherUnsigned32) \
V(Integral32, kSigned32 | kUnsigned32) \
V(Number, kIntegral32 | kMinusZero | kNaN | kOtherNumber) \
V(String, kInternalizedString | kOtherString) \ V(String, kInternalizedString | kOtherString) \
V(UniqueName, kSymbol | kInternalizedString) \ V(UniqueName, kSymbol | kInternalizedString) \
V(Name, kSymbol | kString) \ V(Name, kSymbol | kString) \
V(NumberOrString, kNumber | kString) \ V(NumberOrString, kNumber | kString) \
V(Primitive, kNumber | kName | kBoolean | kNull | kUndefined) \
V(DetectableObject, kArray | kFunction | kRegExp | kOtherObject) \ V(DetectableObject, kArray | kFunction | kRegExp | kOtherObject) \
V(DetectableReceiver, kDetectableObject | kProxy) \ V(DetectableReceiver, kDetectableObject | kProxy) \
V(Detectable, kDetectableReceiver | kNumber | kName) \ V(Detectable, kDetectableReceiver | kNumber | kName) \
...@@ -230,12 +245,14 @@ class TypeImpl : public Config::Base { ...@@ -230,12 +245,14 @@ class TypeImpl : public Config::Base {
class ClassType; class ClassType;
class ConstantType; class ConstantType;
class ContextType;
class ArrayType; class ArrayType;
class FunctionType; class FunctionType;
typedef typename Config::template Handle<TypeImpl>::type TypeHandle; typedef typename Config::template Handle<TypeImpl>::type TypeHandle;
typedef typename Config::template Handle<ClassType>::type ClassHandle; typedef typename Config::template Handle<ClassType>::type ClassHandle;
typedef typename Config::template Handle<ConstantType>::type ConstantHandle; typedef typename Config::template Handle<ConstantType>::type ConstantHandle;
typedef typename Config::template Handle<ContextType>::type ContextHandle;
typedef typename Config::template Handle<ArrayType>::type ArrayHandle; typedef typename Config::template Handle<ArrayType>::type ArrayHandle;
typedef typename Config::template Handle<FunctionType>::type FunctionHandle; typedef typename Config::template Handle<FunctionType>::type FunctionHandle;
typedef typename Config::template Handle<UnionType>::type UnionHandle; typedef typename Config::template Handle<UnionType>::type UnionHandle;
...@@ -255,6 +272,9 @@ class TypeImpl : public Config::Base { ...@@ -255,6 +272,9 @@ class TypeImpl : public Config::Base {
static TypeHandle Constant(i::Handle<i::Object> value, Region* region) { static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
return ConstantType::New(value, region); return ConstantType::New(value, region);
} }
static TypeHandle Context(TypeHandle outer, Region* region) {
return ContextType::New(outer, region);
}
static TypeHandle Array(TypeHandle element, Region* region) { static TypeHandle Array(TypeHandle element, Region* region) {
return ArrayType::New(element, region); return ArrayType::New(element, region);
} }
...@@ -278,10 +298,22 @@ class TypeImpl : public Config::Base { ...@@ -278,10 +298,22 @@ class TypeImpl : public Config::Base {
function->InitParameter(1, param1); function->InitParameter(1, param1);
return function; return function;
} }
static TypeHandle Function(
TypeHandle result, TypeHandle param0, TypeHandle param1,
TypeHandle param2, Region* region) {
FunctionHandle function = Function(result, Any(region), 3, region);
function->InitParameter(0, param0);
function->InitParameter(1, param1);
function->InitParameter(2, param2);
return function;
}
static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg); static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg);
static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg); static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg);
static TypeHandle Of(double value, Region* region) {
return Config::from_bitset(BitsetType::Lub(value), region);
}
static TypeHandle Of(i::Object* value, Region* region) { static TypeHandle Of(i::Object* value, Region* region) {
return Config::from_bitset(BitsetType::Lub(value), region); return Config::from_bitset(BitsetType::Lub(value), region);
} }
...@@ -325,6 +357,9 @@ class TypeImpl : public Config::Base { ...@@ -325,6 +357,9 @@ class TypeImpl : public Config::Base {
bool IsClass() { return Config::is_class(this); } bool IsClass() { return Config::is_class(this); }
bool IsConstant() { return Config::is_constant(this); } bool IsConstant() { return Config::is_constant(this); }
bool IsContext() {
return Config::is_struct(this, StructuralType::kContextTag);
}
bool IsArray() { return Config::is_struct(this, StructuralType::kArrayTag); } bool IsArray() { return Config::is_struct(this, StructuralType::kArrayTag); }
bool IsFunction() { bool IsFunction() {
return Config::is_struct(this, StructuralType::kFunctionTag); return Config::is_struct(this, StructuralType::kFunctionTag);
...@@ -332,6 +367,7 @@ class TypeImpl : public Config::Base { ...@@ -332,6 +367,7 @@ class TypeImpl : public Config::Base {
ClassType* AsClass() { return ClassType::cast(this); } ClassType* AsClass() { return ClassType::cast(this); }
ConstantType* AsConstant() { return ConstantType::cast(this); } ConstantType* AsConstant() { return ConstantType::cast(this); }
ContextType* AsContext() { return ContextType::cast(this); }
ArrayType* AsArray() { return ArrayType::cast(this); } ArrayType* AsArray() { return ArrayType::cast(this); }
FunctionType* AsFunction() { return FunctionType::cast(this); } FunctionType* AsFunction() { return FunctionType::cast(this); }
...@@ -355,6 +391,7 @@ class TypeImpl : public Config::Base { ...@@ -355,6 +391,7 @@ class TypeImpl : public Config::Base {
typename OtherTypeImpl::TypeHandle type, Region* region); typename OtherTypeImpl::TypeHandle type, Region* region);
enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM }; enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM };
void PrintTo(StringStream* stream, PrintDimension = BOTH_DIMS);
void TypePrint(PrintDimension = BOTH_DIMS); void TypePrint(PrintDimension = BOTH_DIMS);
void TypePrint(FILE* out, PrintDimension = BOTH_DIMS); void TypePrint(FILE* out, PrintDimension = BOTH_DIMS);
...@@ -419,10 +456,14 @@ class TypeImpl<Config>::BitsetType : public TypeImpl<Config> { ...@@ -419,10 +456,14 @@ class TypeImpl<Config>::BitsetType : public TypeImpl<Config> {
static int Glb(TypeImpl* type); // greatest lower bound that's a bitset static int Glb(TypeImpl* type); // greatest lower bound that's a bitset
static int Lub(TypeImpl* type); // least upper bound that's a bitset static int Lub(TypeImpl* type); // least upper bound that's a bitset
static int Lub(i::Object* value); static int Lub(i::Object* value);
static int Lub(double value);
static int Lub(int32_t value);
static int Lub(uint32_t value);
static int Lub(i::Map* map); static int Lub(i::Map* map);
static const char* Name(int bitset); static const char* Name(int bitset);
static void BitsetTypePrint(FILE* out, int bitset); static void PrintTo(StringStream* stream, int bitset);
using TypeImpl::PrintTo;
}; };
...@@ -438,6 +479,7 @@ class TypeImpl<Config>::StructuralType : public TypeImpl<Config> { ...@@ -438,6 +479,7 @@ class TypeImpl<Config>::StructuralType : public TypeImpl<Config> {
enum Tag { enum Tag {
kClassTag, kClassTag,
kConstantTag, kConstantTag,
kContextTag,
kArrayTag, kArrayTag,
kFunctionTag, kFunctionTag,
kUnionTag kUnionTag
...@@ -496,6 +538,25 @@ class TypeImpl<Config>::ConstantType : public TypeImpl<Config> { ...@@ -496,6 +538,25 @@ class TypeImpl<Config>::ConstantType : public TypeImpl<Config> {
}; };
template<class Config>
class TypeImpl<Config>::ContextType : public StructuralType {
public:
TypeHandle Outer() { return this->Get(0); }
static ContextHandle New(TypeHandle outer, Region* region) {
ContextHandle type = Config::template cast<ContextType>(
StructuralType::New(StructuralType::kContextTag, 1, region));
type->Set(0, outer);
return type;
}
static ContextType* cast(TypeImpl* type) {
ASSERT(type->IsContext());
return static_cast<ContextType*>(type);
}
};
// Internal // Internal
// A union is a structured type with the following invariants: // A union is a structured type with the following invariants:
// - its length is at least 2 // - its length is at least 2
......
...@@ -43,9 +43,10 @@ struct ZoneRep { ...@@ -43,9 +43,10 @@ struct ZoneRep {
static bool IsBitset(Type* t) { return reinterpret_cast<intptr_t>(t) & 1; } static bool IsBitset(Type* t) { return reinterpret_cast<intptr_t>(t) & 1; }
static bool IsClass(Type* t) { return IsStruct(t, 0); } static bool IsClass(Type* t) { return IsStruct(t, 0); }
static bool IsConstant(Type* t) { return IsStruct(t, 1); } static bool IsConstant(Type* t) { return IsStruct(t, 1); }
static bool IsArray(Type* t) { return IsStruct(t, 2); } static bool IsContext(Type* t) { return IsStruct(t, 2); }
static bool IsFunction(Type* t) { return IsStruct(t, 3); } static bool IsArray(Type* t) { return IsStruct(t, 3); }
static bool IsUnion(Type* t) { return IsStruct(t, 4); } static bool IsFunction(Type* t) { return IsStruct(t, 4); }
static bool IsUnion(Type* t) { return IsStruct(t, 5); }
static Struct* AsStruct(Type* t) { static Struct* AsStruct(Type* t) {
return reinterpret_cast<Struct*>(t); return reinterpret_cast<Struct*>(t);
...@@ -59,6 +60,9 @@ struct ZoneRep { ...@@ -59,6 +60,9 @@ struct ZoneRep {
static Object* AsConstant(Type* t) { static Object* AsConstant(Type* t) {
return *static_cast<Object**>(AsStruct(t)[3]); return *static_cast<Object**>(AsStruct(t)[3]);
} }
static Type* AsContext(Type* t) {
return *static_cast<Type**>(AsStruct(t)[2]);
}
static Struct* AsUnion(Type* t) { static Struct* AsUnion(Type* t) {
return AsStruct(t); return AsStruct(t);
} }
...@@ -79,9 +83,10 @@ struct HeapRep { ...@@ -79,9 +83,10 @@ struct HeapRep {
static bool IsBitset(Handle<HeapType> t) { return t->IsSmi(); } static bool IsBitset(Handle<HeapType> t) { return t->IsSmi(); }
static bool IsClass(Handle<HeapType> t) { return t->IsMap(); } static bool IsClass(Handle<HeapType> t) { return t->IsMap(); }
static bool IsConstant(Handle<HeapType> t) { return t->IsBox(); } static bool IsConstant(Handle<HeapType> t) { return t->IsBox(); }
static bool IsArray(Handle<HeapType> t) { return IsStruct(t, 2); } static bool IsContext(Handle<HeapType> t) { return IsStruct(t, 2); }
static bool IsFunction(Handle<HeapType> t) { return IsStruct(t, 3); } static bool IsArray(Handle<HeapType> t) { return IsStruct(t, 3); }
static bool IsUnion(Handle<HeapType> t) { return IsStruct(t, 4); } static bool IsFunction(Handle<HeapType> t) { return IsStruct(t, 4); }
static bool IsUnion(Handle<HeapType> t) { return IsStruct(t, 5); }
static Struct* AsStruct(Handle<HeapType> t) { return FixedArray::cast(*t); } static Struct* AsStruct(Handle<HeapType> t) { return FixedArray::cast(*t); }
static int AsBitset(Handle<HeapType> t) { return Smi::cast(*t)->value(); } static int AsBitset(Handle<HeapType> t) { return Smi::cast(*t)->value(); }
...@@ -89,6 +94,9 @@ struct HeapRep { ...@@ -89,6 +94,9 @@ struct HeapRep {
static Object* AsConstant(Handle<HeapType> t) { static Object* AsConstant(Handle<HeapType> t) {
return Box::cast(*t)->value(); return Box::cast(*t)->value();
} }
static HeapType* AsContext(Handle<HeapType> t) {
return HeapType::cast(AsStruct(t)->get(1));
}
static Struct* AsUnion(Handle<HeapType> t) { return AsStruct(t); } static Struct* AsUnion(Handle<HeapType> t) { return AsStruct(t); }
static int Length(Struct* structured) { return structured->length() - 1; } static int Length(Struct* structured) { return structured->length() - 1; }
...@@ -143,7 +151,7 @@ class Types { ...@@ -143,7 +151,7 @@ class Types {
types.push_back(Type::Constant(*it, region)); types.push_back(Type::Constant(*it, region));
} }
FloatArray = Type::Array(Float, region); NumberArray = Type::Array(Number, region);
StringArray = Type::Array(String, region); StringArray = Type::Array(String, region);
AnyArray = Type::Array(Any, region); AnyArray = Type::Array(Any, region);
...@@ -183,7 +191,7 @@ class Types { ...@@ -183,7 +191,7 @@ class Types {
TypeHandle ArrayConstant; TypeHandle ArrayConstant;
TypeHandle UninitializedConstant; TypeHandle UninitializedConstant;
TypeHandle FloatArray; TypeHandle NumberArray;
TypeHandle StringArray; TypeHandle StringArray;
TypeHandle AnyArray; TypeHandle AnyArray;
...@@ -272,13 +280,19 @@ class Types { ...@@ -272,13 +280,19 @@ class Types {
int i = rng_.NextInt(static_cast<int>(values.size())); int i = rng_.NextInt(static_cast<int>(values.size()));
return Type::Constant(values[i], region_); return Type::Constant(values[i], region_);
} }
case 3: { // array case 3: { // context
int depth = rng_.NextInt(3);
TypeHandle type = Type::Internal(region_);
for (int i = 0; i < depth; ++i) type = Type::Context(type, region_);
return type;
}
case 4: { // array
TypeHandle element = Fuzz(depth / 2); TypeHandle element = Fuzz(depth / 2);
return Type::Array(element, region_); return Type::Array(element, region_);
} }
case 4:
case 5: case 5:
case 6: { // function case 6:
case 7: { // function
TypeHandle result = Fuzz(depth / 2); TypeHandle result = Fuzz(depth / 2);
TypeHandle receiver = Fuzz(depth / 2); TypeHandle receiver = Fuzz(depth / 2);
int arity = rng_.NextInt(3); int arity = rng_.NextInt(3);
...@@ -332,6 +346,7 @@ struct Tests : Rep { ...@@ -332,6 +346,7 @@ struct Tests : Rep {
Rep::IsBitset(type1) == Rep::IsBitset(type2) && Rep::IsBitset(type1) == Rep::IsBitset(type2) &&
Rep::IsClass(type1) == Rep::IsClass(type2) && Rep::IsClass(type1) == Rep::IsClass(type2) &&
Rep::IsConstant(type1) == Rep::IsConstant(type2) && Rep::IsConstant(type1) == Rep::IsConstant(type2) &&
Rep::IsContext(type1) == Rep::IsContext(type2) &&
Rep::IsUnion(type1) == Rep::IsUnion(type2) && Rep::IsUnion(type1) == Rep::IsUnion(type2) &&
type1->NumClasses() == type2->NumClasses() && type1->NumClasses() == type2->NumClasses() &&
type1->NumConstants() == type2->NumConstants() && type1->NumConstants() == type2->NumConstants() &&
...@@ -507,6 +522,45 @@ struct Tests : Rep { ...@@ -507,6 +522,45 @@ struct Tests : Rep {
CHECK(Equal(type1, type2) == (*value1 == *value2)); CHECK(Equal(type1, type2) == (*value1 == *value2));
} }
} }
// Typing of numbers
Factory* fac = isolate->factory();
CHECK(T.Constant(fac->NewNumber(0))->Is(T.UnsignedSmall));
CHECK(T.Constant(fac->NewNumber(1))->Is(T.UnsignedSmall));
CHECK(T.Constant(fac->NewNumber(0x3fffffff))->Is(T.UnsignedSmall));
CHECK(T.Constant(fac->NewNumber(-1))->Is(T.OtherSignedSmall));
CHECK(T.Constant(fac->NewNumber(-0x3fffffff))->Is(T.OtherSignedSmall));
CHECK(T.Constant(fac->NewNumber(-0x40000000))->Is(T.OtherSignedSmall));
if (SmiValuesAre31Bits()) {
CHECK(T.Constant(fac->NewNumber(0x40000000))->Is(T.OtherUnsigned31));
CHECK(T.Constant(fac->NewNumber(0x7fffffff))->Is(T.OtherUnsigned31));
CHECK(T.Constant(fac->NewNumber(-0x40000001))->Is(T.OtherSigned32));
CHECK(T.Constant(fac->NewNumber(-0x7fffffff))->Is(T.OtherSigned32));
CHECK(T.Constant(fac->NewNumber(-0x7fffffff-1))->Is(T.OtherSigned32));
} else {
CHECK(SmiValuesAre32Bits());
CHECK(T.Constant(fac->NewNumber(0x40000000))->Is(T.UnsignedSmall));
CHECK(T.Constant(fac->NewNumber(0x7fffffff))->Is(T.UnsignedSmall));
CHECK(!T.Constant(fac->NewNumber(0x40000000))->Is(T.OtherUnsigned31));
CHECK(!T.Constant(fac->NewNumber(0x7fffffff))->Is(T.OtherUnsigned31));
CHECK(T.Constant(fac->NewNumber(-0x40000001))->Is(T.OtherSignedSmall));
CHECK(T.Constant(fac->NewNumber(-0x7fffffff))->Is(T.OtherSignedSmall));
CHECK(T.Constant(fac->NewNumber(-0x7fffffff-1))->Is(T.OtherSignedSmall));
CHECK(!T.Constant(fac->NewNumber(-0x40000001))->Is(T.OtherSigned32));
CHECK(!T.Constant(fac->NewNumber(-0x7fffffff))->Is(T.OtherSigned32));
CHECK(!T.Constant(fac->NewNumber(-0x7fffffff-1))->Is(T.OtherSigned32));
}
CHECK(T.Constant(fac->NewNumber(0x80000000u))->Is(T.OtherUnsigned32));
CHECK(T.Constant(fac->NewNumber(0xffffffffu))->Is(T.OtherUnsigned32));
CHECK(T.Constant(fac->NewNumber(0xffffffffu+1.0))->Is(T.OtherNumber));
CHECK(T.Constant(fac->NewNumber(-0x7fffffff-2.0))->Is(T.OtherNumber));
CHECK(T.Constant(fac->NewNumber(0.1))->Is(T.OtherNumber));
CHECK(T.Constant(fac->NewNumber(-10.1))->Is(T.OtherNumber));
CHECK(T.Constant(fac->NewNumber(10e60))->Is(T.OtherNumber));
CHECK(T.Constant(fac->NewNumber(-1.0*0.0))->Is(T.MinusZero));
CHECK(T.Constant(fac->NewNumber(0.0/0.0))->Is(T.NaN));
CHECK(T.Constant(fac->NewNumber(1.0/0.0))->Is(T.OtherNumber));
CHECK(T.Constant(fac->NewNumber(-1.0/0.0))->Is(T.OtherNumber));
} }
void Array() { void Array() {
...@@ -772,10 +826,9 @@ struct Tests : Rep { ...@@ -772,10 +826,9 @@ struct Tests : Rep {
CheckSub(T.SignedSmall, T.Number); CheckSub(T.SignedSmall, T.Number);
CheckSub(T.Signed32, T.Number); CheckSub(T.Signed32, T.Number);
CheckSub(T.Float, T.Number);
CheckSub(T.SignedSmall, T.Signed32); CheckSub(T.SignedSmall, T.Signed32);
CheckUnordered(T.SignedSmall, T.Float); CheckUnordered(T.SignedSmall, T.MinusZero);
CheckUnordered(T.Signed32, T.Float); CheckUnordered(T.Signed32, T.Unsigned32);
CheckSub(T.UniqueName, T.Name); CheckSub(T.UniqueName, T.Name);
CheckSub(T.String, T.Name); CheckSub(T.String, T.Name);
...@@ -823,8 +876,8 @@ struct Tests : Rep { ...@@ -823,8 +876,8 @@ struct Tests : Rep {
CheckUnordered(T.ObjectConstant2, T.ArrayClass); CheckUnordered(T.ObjectConstant2, T.ArrayClass);
CheckUnordered(T.ArrayConstant, T.ObjectClass); CheckUnordered(T.ArrayConstant, T.ObjectClass);
CheckSub(T.FloatArray, T.Array); CheckSub(T.NumberArray, T.Array);
CheckSub(T.FloatArray, T.Object); CheckSub(T.NumberArray, T.Object);
CheckUnordered(T.StringArray, T.AnyArray); CheckUnordered(T.StringArray, T.AnyArray);
CheckSub(T.MethodFunction, T.Function); CheckSub(T.MethodFunction, T.Function);
...@@ -1114,8 +1167,8 @@ struct Tests : Rep { ...@@ -1114,8 +1167,8 @@ struct Tests : Rep {
CheckDisjoint(T.Boolean, T.Undefined, T.Semantic); CheckDisjoint(T.Boolean, T.Undefined, T.Semantic);
CheckOverlap(T.SignedSmall, T.Number, T.Semantic); CheckOverlap(T.SignedSmall, T.Number, T.Semantic);
CheckOverlap(T.Float, T.Number, T.Semantic); CheckOverlap(T.NaN, T.Number, T.Semantic);
CheckDisjoint(T.Signed32, T.Float, T.Semantic); CheckDisjoint(T.Signed32, T.NaN, T.Semantic);
CheckOverlap(T.UniqueName, T.Name, T.Semantic); CheckOverlap(T.UniqueName, T.Name, T.Semantic);
CheckOverlap(T.String, T.Name, T.Semantic); CheckOverlap(T.String, T.Name, T.Semantic);
...@@ -1145,7 +1198,6 @@ struct Tests : Rep { ...@@ -1145,7 +1198,6 @@ struct Tests : Rep {
CheckOverlap(T.SmiConstant, T.SignedSmall, T.Semantic); CheckOverlap(T.SmiConstant, T.SignedSmall, T.Semantic);
CheckOverlap(T.SmiConstant, T.Signed32, T.Semantic); CheckOverlap(T.SmiConstant, T.Signed32, T.Semantic);
CheckOverlap(T.SmiConstant, T.Number, T.Semantic); CheckOverlap(T.SmiConstant, T.Number, T.Semantic);
CheckDisjoint(T.SmiConstant, T.Float, T.Semantic);
CheckOverlap(T.ObjectConstant1, T.Object, T.Semantic); CheckOverlap(T.ObjectConstant1, T.Object, T.Semantic);
CheckOverlap(T.ObjectConstant2, T.Object, T.Semantic); CheckOverlap(T.ObjectConstant2, T.Object, T.Semantic);
CheckOverlap(T.ArrayConstant, T.Object, T.Semantic); CheckOverlap(T.ArrayConstant, T.Object, T.Semantic);
...@@ -1160,9 +1212,9 @@ struct Tests : Rep { ...@@ -1160,9 +1212,9 @@ struct Tests : Rep {
CheckDisjoint(T.ObjectConstant2, T.ArrayClass, T.Semantic); CheckDisjoint(T.ObjectConstant2, T.ArrayClass, T.Semantic);
CheckDisjoint(T.ArrayConstant, T.ObjectClass, T.Semantic); CheckDisjoint(T.ArrayConstant, T.ObjectClass, T.Semantic);
CheckOverlap(T.FloatArray, T.Array, T.Semantic); CheckOverlap(T.NumberArray, T.Array, T.Semantic);
CheckDisjoint(T.FloatArray, T.AnyArray, T.Semantic); CheckDisjoint(T.NumberArray, T.AnyArray, T.Semantic);
CheckDisjoint(T.FloatArray, T.StringArray, T.Semantic); CheckDisjoint(T.NumberArray, T.StringArray, T.Semantic);
CheckOverlap(T.MethodFunction, T.Function, T.Semantic); CheckOverlap(T.MethodFunction, T.Function, T.Semantic);
CheckDisjoint(T.SignedFunction1, T.NumberFunction1, T.Semantic); CheckDisjoint(T.SignedFunction1, T.NumberFunction1, T.Semantic);
...@@ -1303,22 +1355,18 @@ struct Tests : Rep { ...@@ -1303,22 +1355,18 @@ struct Tests : Rep {
// Bitset-array // Bitset-array
CHECK(this->IsBitset(T.Union(T.AnyArray, T.Array))); CHECK(this->IsBitset(T.Union(T.AnyArray, T.Array)));
CHECK(this->IsUnion(T.Union(T.FloatArray, T.Number))); CHECK(this->IsUnion(T.Union(T.NumberArray, T.Number)));
CheckEqual(T.Union(T.AnyArray, T.Array), T.Array); CheckEqual(T.Union(T.AnyArray, T.Array), T.Array);
CheckSub(T.None, T.Union(T.FloatArray, T.Number));
CheckSub(T.Union(T.FloatArray, T.Number), T.Any);
CheckUnordered(T.Union(T.AnyArray, T.String), T.Array); CheckUnordered(T.Union(T.AnyArray, T.String), T.Array);
CheckOverlap(T.Union(T.FloatArray, T.String), T.Object, T.Semantic); CheckOverlap(T.Union(T.NumberArray, T.String), T.Object, T.Semantic);
CheckDisjoint(T.Union(T.FloatArray, T.String), T.Number, T.Semantic); CheckDisjoint(T.Union(T.NumberArray, T.String), T.Number, T.Semantic);
// Bitset-function // Bitset-function
CHECK(this->IsBitset(T.Union(T.MethodFunction, T.Function))); CHECK(this->IsBitset(T.Union(T.MethodFunction, T.Function)));
CHECK(this->IsUnion(T.Union(T.NumberFunction1, T.Number))); CHECK(this->IsUnion(T.Union(T.NumberFunction1, T.Number)));
CheckEqual(T.Union(T.MethodFunction, T.Function), T.Function); CheckEqual(T.Union(T.MethodFunction, T.Function), T.Function);
CheckSub(T.None, T.Union(T.MethodFunction, T.Number));
CheckSub(T.Union(T.MethodFunction, T.Number), T.Any);
CheckUnordered(T.Union(T.NumberFunction1, T.String), T.Function); CheckUnordered(T.Union(T.NumberFunction1, T.String), T.Function);
CheckOverlap(T.Union(T.NumberFunction2, T.String), T.Object, T.Semantic); CheckOverlap(T.Union(T.NumberFunction2, T.String), T.Object, T.Semantic);
CheckDisjoint(T.Union(T.NumberFunction1, T.String), T.Number, T.Semantic); CheckDisjoint(T.Union(T.NumberFunction1, T.String), T.Number, T.Semantic);
...@@ -1353,10 +1401,10 @@ struct Tests : Rep { ...@@ -1353,10 +1401,10 @@ struct Tests : Rep {
// Bitset-union // Bitset-union
CheckSub( CheckSub(
T.Float, T.NaN,
T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number)); T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number));
CheckSub( CheckSub(
T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Float), T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Signed32),
T.Union(T.ObjectConstant1, T.Union(T.Number, T.ArrayClass))); T.Union(T.ObjectConstant1, T.Union(T.Number, T.ArrayClass)));
// Class-union // Class-union
...@@ -1380,9 +1428,9 @@ struct Tests : Rep { ...@@ -1380,9 +1428,9 @@ struct Tests : Rep {
// Array-union // Array-union
CheckEqual( CheckEqual(
T.Union(T.AnyArray, T.Union(T.FloatArray, T.AnyArray)), T.Union(T.AnyArray, T.Union(T.NumberArray, T.AnyArray)),
T.Union(T.AnyArray, T.FloatArray)); T.Union(T.AnyArray, T.NumberArray));
CheckSub(T.Union(T.AnyArray, T.FloatArray), T.Array); CheckSub(T.Union(T.AnyArray, T.NumberArray), T.Array);
// Function-union // Function-union
CheckEqual( CheckEqual(
...@@ -1524,7 +1572,7 @@ struct Tests : Rep { ...@@ -1524,7 +1572,7 @@ struct Tests : Rep {
CheckSub(T.Intersect(T.ObjectClass, T.Number), T.Representation); CheckSub(T.Intersect(T.ObjectClass, T.Number), T.Representation);
// Bitset-array // Bitset-array
CheckEqual(T.Intersect(T.FloatArray, T.Object), T.FloatArray); CheckEqual(T.Intersect(T.NumberArray, T.Object), T.NumberArray);
CheckSub(T.Intersect(T.AnyArray, T.Function), T.Representation); CheckSub(T.Intersect(T.AnyArray, T.Function), T.Representation);
// Bitset-function // Bitset-function
...@@ -1545,13 +1593,13 @@ struct Tests : Rep { ...@@ -1545,13 +1593,13 @@ struct Tests : Rep {
// Array-union // Array-union
CheckEqual( CheckEqual(
T.Intersect(T.FloatArray, T.Union(T.FloatArray, T.ArrayClass)), T.Intersect(T.NumberArray, T.Union(T.NumberArray, T.ArrayClass)),
T.FloatArray); T.NumberArray);
CheckEqual( CheckEqual(
T.Intersect(T.AnyArray, T.Union(T.Object, T.SmiConstant)), T.Intersect(T.AnyArray, T.Union(T.Object, T.SmiConstant)),
T.AnyArray); T.AnyArray);
CheckEqual( CheckEqual(
T.Intersect(T.Union(T.AnyArray, T.ArrayConstant), T.FloatArray), T.Intersect(T.Union(T.AnyArray, T.ArrayConstant), T.NumberArray),
T.None); T.None);
// Function-union // Function-union
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment