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
This commit is contained in:
parent
6ed0102b1d
commit
dbf7d8528c
@ -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.
|
||||
inline int32_t NumberToInt32(Object* number) {
|
||||
if (number->IsSmi()) return Smi::cast(number)->value();
|
||||
|
@ -9503,7 +9503,7 @@ HValue* HGraphBuilder::TruncateToNumber(HValue* value, Type** expected) {
|
||||
|
||||
if (expected_obj->Is(Type::Undefined(zone()))) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ template<class Config>
|
||||
TypeImpl<Config>* TypeImpl<Config>::cast(typename Config::Base* object) {
|
||||
TypeImpl* t = static_cast<TypeImpl*>(object);
|
||||
ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() ||
|
||||
t->IsUnion() || t->IsArray() || t->IsFunction());
|
||||
t->IsUnion() || t->IsArray() || t->IsFunction() || t->IsContext());
|
||||
return t;
|
||||
}
|
||||
|
||||
|
234
src/types.cc
234
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);
|
||||
if (value->IsNumber()) {
|
||||
return Lub(value->Number()) & (value->IsSmi() ? kTaggedInt : kTaggedPtr);
|
||||
}
|
||||
return Lub(map);
|
||||
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);
|
||||
@ -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>
|
||||
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,94 +708,115 @@ 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>::PrintTo(StringStream* stream, PrintDimension dim) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
if (this->IsBitset()) {
|
||||
int bitset = this->AsBitset();
|
||||
switch (dim) {
|
||||
case BOTH_DIMS:
|
||||
BitsetType::PrintTo(stream, SEMANTIC(bitset));
|
||||
stream->Add("/");
|
||||
BitsetType::PrintTo(stream, REPRESENTATION(bitset));
|
||||
break;
|
||||
case SEMANTIC_DIM:
|
||||
BitsetType::PrintTo(stream, SEMANTIC(bitset));
|
||||
break;
|
||||
case REPRESENTATION_DIM:
|
||||
BitsetType::PrintTo(stream, REPRESENTATION(bitset));
|
||||
break;
|
||||
}
|
||||
} else if (this->IsConstant()) {
|
||||
stream->Add("Constant(%p : ",
|
||||
static_cast<void*>(*this->AsConstant()->Value()));
|
||||
BitsetType::New(BitsetType::Lub(this))->PrintTo(stream, dim);
|
||||
stream->Add(")");
|
||||
} else if (this->IsClass()) {
|
||||
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()) {
|
||||
stream->Add("(");
|
||||
UnionHandle unioned = handle(this->AsUnion());
|
||||
for (int i = 0; i < unioned->Length(); ++i) {
|
||||
TypeHandle type_i = unioned->Get(i);
|
||||
if (i > 0) stream->Add(" | ");
|
||||
type_i->PrintTo(stream, dim);
|
||||
}
|
||||
stream->Add(")");
|
||||
} else if (this->IsArray()) {
|
||||
stream->Add("[");
|
||||
AsArray()->Element()->PrintTo(stream, dim);
|
||||
stream->Add("]");
|
||||
} else if (this->IsFunction()) {
|
||||
if (!this->AsFunction()->Receiver()->IsAny()) {
|
||||
this->AsFunction()->Receiver()->PrintTo(stream, dim);
|
||||
stream->Add(".");
|
||||
}
|
||||
stream->Add("(");
|
||||
for (int i = 0; i < this->AsFunction()->Arity(); ++i) {
|
||||
if (i > 0) stream->Add(", ");
|
||||
this->AsFunction()->Parameter(i)->PrintTo(stream, dim);
|
||||
}
|
||||
stream->Add(")->");
|
||||
this->AsFunction()->Result()->PrintTo(stream, dim);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Config>
|
||||
void TypeImpl<Config>::TypePrint(FILE* out, 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);
|
||||
break;
|
||||
case SEMANTIC_DIM:
|
||||
BitsetType::BitsetTypePrint(out, bitset & BitsetType::kSemantic);
|
||||
break;
|
||||
case REPRESENTATION_DIM:
|
||||
BitsetType::BitsetTypePrint(out, bitset & BitsetType::kRepresentation);
|
||||
break;
|
||||
}
|
||||
} else if (this->IsConstant()) {
|
||||
PrintF(out, "Constant(%p : ",
|
||||
static_cast<void*>(*this->AsConstant()->Value()));
|
||||
BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim);
|
||||
PrintF(out, ")");
|
||||
} else if (this->IsClass()) {
|
||||
PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass()->Map()));
|
||||
BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim);
|
||||
PrintF(out, ")");
|
||||
} else if (this->IsUnion()) {
|
||||
PrintF(out, "(");
|
||||
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);
|
||||
}
|
||||
PrintF(out, ")");
|
||||
} else if (this->IsArray()) {
|
||||
PrintF(out, "[");
|
||||
AsArray()->Element()->TypePrint(out, dim);
|
||||
PrintF(out, "]");
|
||||
} else if (this->IsFunction()) {
|
||||
if (!this->AsFunction()->Receiver()->IsAny()) {
|
||||
this->AsFunction()->Receiver()->TypePrint(out, dim);
|
||||
PrintF(out, ".");
|
||||
}
|
||||
PrintF(out, "(");
|
||||
for (int i = 0; i < this->AsFunction()->Arity(); ++i) {
|
||||
if (i > 0) PrintF(out, ", ");
|
||||
this->AsFunction()->Parameter(i)->TypePrint(out, dim);
|
||||
}
|
||||
PrintF(out, ")->");
|
||||
this->AsFunction()->Result()->TypePrint(out, dim);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
139
src/types.h
139
src/types.h
@ -45,10 +45,14 @@ namespace internal {
|
||||
// Constant(x) < T iff instance_type(map(x)) < T
|
||||
// Array(T) < Array
|
||||
// Function(R, S, T0, T1, ...) < Function
|
||||
// Context(T) < Internal
|
||||
//
|
||||
// Both structural Array and Function types are invariant in all parameters.
|
||||
// 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
|
||||
// Both structural Array and Function types are invariant in all parameters;
|
||||
// relaxing this would make Union and Intersect operations more involved.
|
||||
// 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.)
|
||||
// TODO(rossberg): the latter is not currently true for proxies, because of fix,
|
||||
// but will hold once we implement direct proxies.
|
||||
@ -129,14 +133,15 @@ namespace internal {
|
||||
|
||||
|
||||
#define MASK_BITSET_TYPE_LIST(V) \
|
||||
V(Representation, static_cast<int>(0xff800000)) \
|
||||
V(Semantic, static_cast<int>(0x007fffff))
|
||||
V(Representation, static_cast<int>(0xffc00000)) \
|
||||
V(Semantic, static_cast<int>(0x003fffff))
|
||||
|
||||
#define REPRESENTATION(k) ((k) & kRepresentation)
|
||||
#define SEMANTIC(k) ((k) & kSemantic)
|
||||
#define REPRESENTATION(k) ((k) & BitsetType::kRepresentation)
|
||||
#define SEMANTIC(k) ((k) & BitsetType::kSemantic)
|
||||
|
||||
#define REPRESENTATION_BITSET_TYPE_LIST(V) \
|
||||
V(None, 0) \
|
||||
V(UntaggedInt1, 1 << 22 | kSemantic) \
|
||||
V(UntaggedInt8, 1 << 23 | kSemantic) \
|
||||
V(UntaggedInt16, 1 << 24 | kSemantic) \
|
||||
V(UntaggedInt32, 1 << 25 | kSemantic) \
|
||||
@ -146,44 +151,54 @@ namespace internal {
|
||||
V(TaggedInt, 1 << 29 | kSemantic) \
|
||||
V(TaggedPtr, -1 << 30 | kSemantic) /* MSB has to be sign-extended */ \
|
||||
\
|
||||
V(UntaggedInt, kUntaggedInt8 | kUntaggedInt16 | kUntaggedInt32) \
|
||||
V(UntaggedFloat, kUntaggedFloat32 | kUntaggedFloat64) \
|
||||
V(UntaggedNumber, kUntaggedInt | kUntaggedFloat) \
|
||||
V(Untagged, kUntaggedNumber | kUntaggedPtr) \
|
||||
V(UntaggedInt, kUntaggedInt1 | kUntaggedInt8 | \
|
||||
kUntaggedInt16 | kUntaggedInt32) \
|
||||
V(UntaggedFloat, kUntaggedFloat32 | kUntaggedFloat64) \
|
||||
V(UntaggedNumber, kUntaggedInt | kUntaggedFloat) \
|
||||
V(Untagged, kUntaggedNumber | kUntaggedPtr) \
|
||||
V(Tagged, kTaggedInt | kTaggedPtr)
|
||||
|
||||
#define SEMANTIC_BITSET_TYPE_LIST(V) \
|
||||
V(Null, 1 << 0 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Undefined, 1 << 1 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Boolean, 1 << 2 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(SignedSmall, 1 << 3 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherSigned32, 1 << 4 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(Unsigned32, 1 << 5 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(Float, 1 << 6 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(Symbol, 1 << 7 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(InternalizedString, 1 << 8 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(OtherString, 1 << 9 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Undetectable, 1 << 10 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Array, 1 << 11 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Function, 1 << 12 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(RegExp, 1 << 13 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(OtherObject, 1 << 14 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Proxy, 1 << 15 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Internal, 1 << 16 | REPRESENTATION(kTagged | kUntagged)) \
|
||||
V(UnsignedSmall, 1 << 3 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherSignedSmall, 1 << 4 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherUnsigned31, 1 << 5 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherUnsigned32, 1 << 6 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherSigned32, 1 << 7 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(MinusZero, 1 << 8 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(NaN, 1 << 9 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherNumber, 1 << 10 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(Symbol, 1 << 11 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(InternalizedString, 1 << 12 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(OtherString, 1 << 13 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Undetectable, 1 << 14 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Array, 1 << 15 | REPRESENTATION(kTaggedPtr)) \
|
||||
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(Number, kSigned32 | kUnsigned32 | kFloat) \
|
||||
V(String, kInternalizedString | kOtherString) \
|
||||
V(UniqueName, kSymbol | kInternalizedString) \
|
||||
V(Name, kSymbol | kString) \
|
||||
V(NumberOrString, kNumber | kString) \
|
||||
V(DetectableObject, kArray | kFunction | kRegExp | kOtherObject) \
|
||||
V(DetectableReceiver, kDetectableObject | kProxy) \
|
||||
V(Detectable, kDetectableReceiver | kNumber | kName) \
|
||||
V(Object, kDetectableObject | kUndetectable) \
|
||||
V(Receiver, kObject | kProxy) \
|
||||
V(NonNumber, kBoolean | kName | kNull | kReceiver | \
|
||||
kUndefined | kInternal) \
|
||||
V(SignedSmall, kUnsignedSmall | kOtherSignedSmall) \
|
||||
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(UniqueName, kSymbol | kInternalizedString) \
|
||||
V(Name, kSymbol | kString) \
|
||||
V(NumberOrString, kNumber | kString) \
|
||||
V(Primitive, kNumber | kName | kBoolean | kNull | kUndefined) \
|
||||
V(DetectableObject, kArray | kFunction | kRegExp | kOtherObject) \
|
||||
V(DetectableReceiver, kDetectableObject | kProxy) \
|
||||
V(Detectable, kDetectableReceiver | kNumber | kName) \
|
||||
V(Object, kDetectableObject | kUndetectable) \
|
||||
V(Receiver, kObject | kProxy) \
|
||||
V(NonNumber, kBoolean | kName | kNull | kReceiver | \
|
||||
kUndefined | kInternal) \
|
||||
V(Any, -1)
|
||||
|
||||
#define BITSET_TYPE_LIST(V) \
|
||||
@ -230,12 +245,14 @@ class TypeImpl : public Config::Base {
|
||||
|
||||
class ClassType;
|
||||
class ConstantType;
|
||||
class ContextType;
|
||||
class ArrayType;
|
||||
class FunctionType;
|
||||
|
||||
typedef typename Config::template Handle<TypeImpl>::type TypeHandle;
|
||||
typedef typename Config::template Handle<ClassType>::type ClassHandle;
|
||||
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<FunctionType>::type FunctionHandle;
|
||||
typedef typename Config::template Handle<UnionType>::type UnionHandle;
|
||||
@ -255,6 +272,9 @@ class TypeImpl : public Config::Base {
|
||||
static TypeHandle Constant(i::Handle<i::Object> value, Region* 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) {
|
||||
return ArrayType::New(element, region);
|
||||
}
|
||||
@ -278,10 +298,22 @@ class TypeImpl : public Config::Base {
|
||||
function->InitParameter(1, param1);
|
||||
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 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) {
|
||||
return Config::from_bitset(BitsetType::Lub(value), region);
|
||||
}
|
||||
@ -325,6 +357,9 @@ class TypeImpl : public Config::Base {
|
||||
|
||||
bool IsClass() { return Config::is_class(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 IsFunction() {
|
||||
return Config::is_struct(this, StructuralType::kFunctionTag);
|
||||
@ -332,6 +367,7 @@ class TypeImpl : public Config::Base {
|
||||
|
||||
ClassType* AsClass() { return ClassType::cast(this); }
|
||||
ConstantType* AsConstant() { return ConstantType::cast(this); }
|
||||
ContextType* AsContext() { return ContextType::cast(this); }
|
||||
ArrayType* AsArray() { return ArrayType::cast(this); }
|
||||
FunctionType* AsFunction() { return FunctionType::cast(this); }
|
||||
|
||||
@ -355,6 +391,7 @@ class TypeImpl : public Config::Base {
|
||||
typename OtherTypeImpl::TypeHandle type, Region* region);
|
||||
|
||||
enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM };
|
||||
void PrintTo(StringStream* stream, PrintDimension = BOTH_DIMS);
|
||||
void TypePrint(PrintDimension = BOTH_DIMS);
|
||||
void TypePrint(FILE* out, PrintDimension = BOTH_DIMS);
|
||||
|
||||
@ -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 Lub(TypeImpl* type); // least upper bound that's a bitset
|
||||
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 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> {
|
||||
enum Tag {
|
||||
kClassTag,
|
||||
kConstantTag,
|
||||
kContextTag,
|
||||
kArrayTag,
|
||||
kFunctionTag,
|
||||
kUnionTag
|
||||
@ -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
|
||||
// A union is a structured type with the following invariants:
|
||||
// - its length is at least 2
|
||||
|
@ -43,9 +43,10 @@ struct ZoneRep {
|
||||
static bool IsBitset(Type* t) { return reinterpret_cast<intptr_t>(t) & 1; }
|
||||
static bool IsClass(Type* t) { return IsStruct(t, 0); }
|
||||
static bool IsConstant(Type* t) { return IsStruct(t, 1); }
|
||||
static bool IsArray(Type* t) { return IsStruct(t, 2); }
|
||||
static bool IsFunction(Type* t) { return IsStruct(t, 3); }
|
||||
static bool IsUnion(Type* t) { return IsStruct(t, 4); }
|
||||
static bool IsContext(Type* t) { return IsStruct(t, 2); }
|
||||
static bool IsArray(Type* t) { return IsStruct(t, 3); }
|
||||
static bool IsFunction(Type* t) { return IsStruct(t, 4); }
|
||||
static bool IsUnion(Type* t) { return IsStruct(t, 5); }
|
||||
|
||||
static Struct* AsStruct(Type* t) {
|
||||
return reinterpret_cast<Struct*>(t);
|
||||
@ -59,6 +60,9 @@ struct ZoneRep {
|
||||
static Object* AsConstant(Type* t) {
|
||||
return *static_cast<Object**>(AsStruct(t)[3]);
|
||||
}
|
||||
static Type* AsContext(Type* t) {
|
||||
return *static_cast<Type**>(AsStruct(t)[2]);
|
||||
}
|
||||
static Struct* AsUnion(Type* t) {
|
||||
return AsStruct(t);
|
||||
}
|
||||
@ -79,9 +83,10 @@ struct HeapRep {
|
||||
static bool IsBitset(Handle<HeapType> t) { return t->IsSmi(); }
|
||||
static bool IsClass(Handle<HeapType> t) { return t->IsMap(); }
|
||||
static bool IsConstant(Handle<HeapType> t) { return t->IsBox(); }
|
||||
static bool IsArray(Handle<HeapType> t) { return IsStruct(t, 2); }
|
||||
static bool IsFunction(Handle<HeapType> t) { return IsStruct(t, 3); }
|
||||
static bool IsUnion(Handle<HeapType> t) { return IsStruct(t, 4); }
|
||||
static bool IsContext(Handle<HeapType> t) { return IsStruct(t, 2); }
|
||||
static bool IsArray(Handle<HeapType> t) { return IsStruct(t, 3); }
|
||||
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 int AsBitset(Handle<HeapType> t) { return Smi::cast(*t)->value(); }
|
||||
@ -89,6 +94,9 @@ struct HeapRep {
|
||||
static Object* AsConstant(Handle<HeapType> t) {
|
||||
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 int Length(Struct* structured) { return structured->length() - 1; }
|
||||
|
||||
@ -143,7 +151,7 @@ class Types {
|
||||
types.push_back(Type::Constant(*it, region));
|
||||
}
|
||||
|
||||
FloatArray = Type::Array(Float, region);
|
||||
NumberArray = Type::Array(Number, region);
|
||||
StringArray = Type::Array(String, region);
|
||||
AnyArray = Type::Array(Any, region);
|
||||
|
||||
@ -183,7 +191,7 @@ class Types {
|
||||
TypeHandle ArrayConstant;
|
||||
TypeHandle UninitializedConstant;
|
||||
|
||||
TypeHandle FloatArray;
|
||||
TypeHandle NumberArray;
|
||||
TypeHandle StringArray;
|
||||
TypeHandle AnyArray;
|
||||
|
||||
@ -272,13 +280,19 @@ class Types {
|
||||
int i = rng_.NextInt(static_cast<int>(values.size()));
|
||||
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);
|
||||
return Type::Array(element, region_);
|
||||
}
|
||||
case 4:
|
||||
case 5:
|
||||
case 6: { // function
|
||||
case 6:
|
||||
case 7: { // function
|
||||
TypeHandle result = Fuzz(depth / 2);
|
||||
TypeHandle receiver = Fuzz(depth / 2);
|
||||
int arity = rng_.NextInt(3);
|
||||
@ -332,6 +346,7 @@ struct Tests : Rep {
|
||||
Rep::IsBitset(type1) == Rep::IsBitset(type2) &&
|
||||
Rep::IsClass(type1) == Rep::IsClass(type2) &&
|
||||
Rep::IsConstant(type1) == Rep::IsConstant(type2) &&
|
||||
Rep::IsContext(type1) == Rep::IsContext(type2) &&
|
||||
Rep::IsUnion(type1) == Rep::IsUnion(type2) &&
|
||||
type1->NumClasses() == type2->NumClasses() &&
|
||||
type1->NumConstants() == type2->NumConstants() &&
|
||||
@ -507,6 +522,45 @@ struct Tests : Rep {
|
||||
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() {
|
||||
@ -772,10 +826,9 @@ struct Tests : Rep {
|
||||
|
||||
CheckSub(T.SignedSmall, T.Number);
|
||||
CheckSub(T.Signed32, T.Number);
|
||||
CheckSub(T.Float, T.Number);
|
||||
CheckSub(T.SignedSmall, T.Signed32);
|
||||
CheckUnordered(T.SignedSmall, T.Float);
|
||||
CheckUnordered(T.Signed32, T.Float);
|
||||
CheckUnordered(T.SignedSmall, T.MinusZero);
|
||||
CheckUnordered(T.Signed32, T.Unsigned32);
|
||||
|
||||
CheckSub(T.UniqueName, T.Name);
|
||||
CheckSub(T.String, T.Name);
|
||||
@ -823,8 +876,8 @@ struct Tests : Rep {
|
||||
CheckUnordered(T.ObjectConstant2, T.ArrayClass);
|
||||
CheckUnordered(T.ArrayConstant, T.ObjectClass);
|
||||
|
||||
CheckSub(T.FloatArray, T.Array);
|
||||
CheckSub(T.FloatArray, T.Object);
|
||||
CheckSub(T.NumberArray, T.Array);
|
||||
CheckSub(T.NumberArray, T.Object);
|
||||
CheckUnordered(T.StringArray, T.AnyArray);
|
||||
|
||||
CheckSub(T.MethodFunction, T.Function);
|
||||
@ -1114,8 +1167,8 @@ struct Tests : Rep {
|
||||
CheckDisjoint(T.Boolean, T.Undefined, T.Semantic);
|
||||
|
||||
CheckOverlap(T.SignedSmall, T.Number, T.Semantic);
|
||||
CheckOverlap(T.Float, T.Number, T.Semantic);
|
||||
CheckDisjoint(T.Signed32, T.Float, T.Semantic);
|
||||
CheckOverlap(T.NaN, T.Number, T.Semantic);
|
||||
CheckDisjoint(T.Signed32, T.NaN, T.Semantic);
|
||||
|
||||
CheckOverlap(T.UniqueName, T.Name, T.Semantic);
|
||||
CheckOverlap(T.String, T.Name, T.Semantic);
|
||||
@ -1145,7 +1198,6 @@ struct Tests : Rep {
|
||||
CheckOverlap(T.SmiConstant, T.SignedSmall, T.Semantic);
|
||||
CheckOverlap(T.SmiConstant, T.Signed32, 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.ObjectConstant2, T.Object, T.Semantic);
|
||||
CheckOverlap(T.ArrayConstant, T.Object, T.Semantic);
|
||||
@ -1160,9 +1212,9 @@ struct Tests : Rep {
|
||||
CheckDisjoint(T.ObjectConstant2, T.ArrayClass, T.Semantic);
|
||||
CheckDisjoint(T.ArrayConstant, T.ObjectClass, T.Semantic);
|
||||
|
||||
CheckOverlap(T.FloatArray, T.Array, T.Semantic);
|
||||
CheckDisjoint(T.FloatArray, T.AnyArray, T.Semantic);
|
||||
CheckDisjoint(T.FloatArray, T.StringArray, T.Semantic);
|
||||
CheckOverlap(T.NumberArray, T.Array, T.Semantic);
|
||||
CheckDisjoint(T.NumberArray, T.AnyArray, T.Semantic);
|
||||
CheckDisjoint(T.NumberArray, T.StringArray, T.Semantic);
|
||||
|
||||
CheckOverlap(T.MethodFunction, T.Function, T.Semantic);
|
||||
CheckDisjoint(T.SignedFunction1, T.NumberFunction1, T.Semantic);
|
||||
@ -1303,22 +1355,18 @@ struct Tests : Rep {
|
||||
|
||||
// Bitset-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);
|
||||
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);
|
||||
CheckOverlap(T.Union(T.FloatArray, T.String), T.Object, T.Semantic);
|
||||
CheckDisjoint(T.Union(T.FloatArray, T.String), T.Number, T.Semantic);
|
||||
CheckOverlap(T.Union(T.NumberArray, T.String), T.Object, T.Semantic);
|
||||
CheckDisjoint(T.Union(T.NumberArray, T.String), T.Number, T.Semantic);
|
||||
|
||||
// Bitset-function
|
||||
CHECK(this->IsBitset(T.Union(T.MethodFunction, T.Function)));
|
||||
CHECK(this->IsUnion(T.Union(T.NumberFunction1, T.Number)));
|
||||
|
||||
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);
|
||||
CheckOverlap(T.Union(T.NumberFunction2, T.String), T.Object, T.Semantic);
|
||||
CheckDisjoint(T.Union(T.NumberFunction1, T.String), T.Number, T.Semantic);
|
||||
@ -1353,10 +1401,10 @@ struct Tests : Rep {
|
||||
|
||||
// Bitset-union
|
||||
CheckSub(
|
||||
T.Float,
|
||||
T.NaN,
|
||||
T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number));
|
||||
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)));
|
||||
|
||||
// Class-union
|
||||
@ -1380,9 +1428,9 @@ struct Tests : Rep {
|
||||
|
||||
// Array-union
|
||||
CheckEqual(
|
||||
T.Union(T.AnyArray, T.Union(T.FloatArray, T.AnyArray)),
|
||||
T.Union(T.AnyArray, T.FloatArray));
|
||||
CheckSub(T.Union(T.AnyArray, T.FloatArray), T.Array);
|
||||
T.Union(T.AnyArray, T.Union(T.NumberArray, T.AnyArray)),
|
||||
T.Union(T.AnyArray, T.NumberArray));
|
||||
CheckSub(T.Union(T.AnyArray, T.NumberArray), T.Array);
|
||||
|
||||
// Function-union
|
||||
CheckEqual(
|
||||
@ -1524,7 +1572,7 @@ struct Tests : Rep {
|
||||
CheckSub(T.Intersect(T.ObjectClass, T.Number), T.Representation);
|
||||
|
||||
// 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);
|
||||
|
||||
// Bitset-function
|
||||
@ -1545,13 +1593,13 @@ struct Tests : Rep {
|
||||
|
||||
// Array-union
|
||||
CheckEqual(
|
||||
T.Intersect(T.FloatArray, T.Union(T.FloatArray, T.ArrayClass)),
|
||||
T.FloatArray);
|
||||
T.Intersect(T.NumberArray, T.Union(T.NumberArray, T.ArrayClass)),
|
||||
T.NumberArray);
|
||||
CheckEqual(
|
||||
T.Intersect(T.AnyArray, T.Union(T.Object, T.SmiConstant)),
|
||||
T.AnyArray);
|
||||
CheckEqual(
|
||||
T.Intersect(T.Union(T.AnyArray, T.ArrayConstant), T.FloatArray),
|
||||
T.Intersect(T.Union(T.AnyArray, T.ArrayConstant), T.NumberArray),
|
||||
T.None);
|
||||
|
||||
// Function-union
|
||||
|
Loading…
Reference in New Issue
Block a user