Commit 549a3143 authored by Jaroslav Sevcik's avatar Jaroslav Sevcik Committed by Commit Bot

[turbofan] Prepare the Type class for UB treatment.

This is just code reshuffling to enable changing Type* to Type.

Bug: v8:3770
Change-Id: I8ed4ff41b480cab377d115c57c49d6f6c0c46d6d
Reviewed-on: https://chromium-review.googlesource.com/1025897Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52772}
parent 2aa995bf
......@@ -106,43 +106,43 @@ double Type::Max() {
// Glb and lub computation.
// The largest bitset subsumed by this type.
Type::bitset BitsetType::Glb(Type* type) {
Type::bitset Type::BitsetGlb() {
DisallowHeapAllocation no_allocation;
// Fast case.
if (IsBitset(type)) {
return type->AsBitset();
} else if (type->IsUnion()) {
SLOW_DCHECK(type->AsUnion()->Wellformed());
return type->AsUnion()->Get(0)->BitsetGlb() |
type->AsUnion()->Get(1)->BitsetGlb(); // Shortcut.
} else if (type->IsRange()) {
bitset glb =
BitsetType::Glb(type->AsRange()->Min(), type->AsRange()->Max());
if (IsBitset()) {
return AsBitset();
} else if (IsUnion()) {
SLOW_DCHECK(AsUnion()->Wellformed());
return AsUnion()->Get(0)->BitsetGlb() |
AsUnion()->Get(1)->BitsetGlb(); // Shortcut.
} else if (IsRange()) {
bitset glb = BitsetType::Glb(AsRange()->Min(), AsRange()->Max());
return glb;
} else {
return kNone;
return BitsetType::kNone;
}
}
// The smallest bitset subsuming this type, possibly not a proper one.
Type::bitset BitsetType::Lub(Type* type) {
Type::bitset Type::BitsetLub() {
DisallowHeapAllocation no_allocation;
if (IsBitset(type)) return type->AsBitset();
if (type->IsUnion()) {
if (IsBitset()) return AsBitset();
if (IsUnion()) {
// Take the representation from the first element, which is always
// a bitset.
int bitset = type->AsUnion()->Get(0)->BitsetLub();
for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) {
int bitset = AsUnion()->Get(0)->BitsetLub();
for (int i = 0, n = AsUnion()->Length(); i < n; ++i) {
// Other elements only contribute their semantic part.
bitset |= type->AsUnion()->Get(i)->BitsetLub();
bitset |= AsUnion()->Get(i)->BitsetLub();
}
return bitset;
}
if (type->IsHeapConstant()) return type->AsHeapConstant()->Lub();
if (type->IsOtherNumberConstant())
return type->AsOtherNumberConstant()->Lub();
if (type->IsRange()) return type->AsRange()->Lub();
if (type->IsTuple()) return kOtherInternal;
if (IsHeapConstant()) return AsHeapConstant()->Lub();
if (IsOtherNumberConstant()) {
return AsOtherNumberConstant()->Lub();
}
if (IsRange()) return AsRange()->Lub();
if (IsTuple()) return BitsetType::kOtherInternal;
UNREACHABLE();
}
......@@ -635,7 +635,7 @@ bool UnionType::Wellformed() {
Type* Type::Intersect(Type* type1, Type* type2, Zone* zone) {
// Fast case: bit sets.
if (type1->IsBitset() && type2->IsBitset()) {
return BitsetType::New(type1->AsBitset() & type2->AsBitset());
return NewBitset(type1->AsBitset() & type2->AsBitset());
}
// Fast case: top or bottom types.
......@@ -662,12 +662,12 @@ Type* Type::Intersect(Type* type1, Type* type2, Zone* zone) {
int size;
if (base::bits::SignedAddOverflow32(size1, size2, &size)) return Any();
if (base::bits::SignedAddOverflow32(size, 2, &size)) return Any();
Type* result_type = UnionType::New(size, zone);
Type* result_type = Type::Union(size, zone);
UnionType* result = result_type->AsUnion();
size = 0;
// Deal with bitsets.
result->Set(size++, BitsetType::New(bits));
result->Set(size++, NewBitset(bits));
RangeType::Limits lims = RangeType::Limits::Empty();
size = IntersectAux(type1, type2, result, size, &lims, zone);
......@@ -675,12 +675,12 @@ Type* Type::Intersect(Type* type1, Type* type2, Zone* zone) {
// If the range is not empty, then insert it into the union and
// remove the number bits from the bitset.
if (!lims.IsEmpty()) {
size = UpdateRange(RangeType::New(lims, zone), result, size, zone);
size = UpdateRange(Type::Range(lims, zone), result, size, zone);
// Remove the number bits.
bitset number_bits = BitsetType::NumberBits(bits);
bits &= ~number_bits;
result->Set(0, BitsetType::New(bits));
result->Set(0, NewBitset(bits));
}
return NormalizeUnion(result_type, size, zone);
}
......@@ -815,7 +815,7 @@ Type* Type::NormalizeRangeAndBitset(Type* range, bitset* bits, Zone* zone) {
if (bitset_max > range_max) {
range_max = bitset_max;
}
return RangeType::New(range_min, range_max, zone);
return Type::Range(range_min, range_max, zone);
}
Type* Type::NewConstant(double value, Zone* zone) {
......@@ -846,7 +846,7 @@ Type* Type::NewConstant(i::Handle<i::Object> value, Zone* zone) {
Type* Type::Union(Type* type1, Type* type2, Zone* zone) {
// Fast case: bit sets.
if (type1->IsBitset() && type2->IsBitset()) {
return BitsetType::New(type1->AsBitset() | type2->AsBitset());
return NewBitset(type1->AsBitset() | type2->AsBitset());
}
// Fast case: top or bottom types.
......@@ -863,7 +863,7 @@ Type* Type::Union(Type* type1, Type* type2, Zone* zone) {
int size;
if (base::bits::SignedAddOverflow32(size1, size2, &size)) return Any();
if (base::bits::SignedAddOverflow32(size, 2, &size)) return Any();
Type* result_type = UnionType::New(size, zone);
Type* result_type = Type::Union(size, zone);
UnionType* result = result_type->AsUnion();
size = 0;
......@@ -878,14 +878,14 @@ Type* Type::Union(Type* type1, Type* type2, Zone* zone) {
RangeType::Limits lims =
RangeType::Limits::Union(RangeType::Limits(range1->AsRange()),
RangeType::Limits(range2->AsRange()));
Type* union_range = RangeType::New(lims, zone);
Type* union_range = Type::Range(lims, zone);
range = NormalizeRangeAndBitset(union_range, &new_bitset, zone);
} else if (range1 != nullptr) {
range = NormalizeRangeAndBitset(range1, &new_bitset, zone);
} else if (range2 != nullptr) {
range = NormalizeRangeAndBitset(range2, &new_bitset, zone);
}
Type* bits = BitsetType::New(new_bitset);
Type* bits = NewBitset(new_bitset);
result->Set(size++, bits);
if (!range->IsNone()) result->Set(size++, range);
......@@ -923,7 +923,7 @@ Type* Type::NormalizeUnion(Type* union_type, int size, Zone* zone) {
// If the union only consists of a range, we can get rid of the union.
if (size == 2 && bits == BitsetType::kNone) {
if (unioned->Get(1)->IsRange()) {
return RangeType::New(unioned->Get(1)->AsRange()->Min(),
return Type::Range(unioned->Get(1)->AsRange()->Min(),
unioned->Get(1)->AsRange()->Max(), zone);
}
}
......@@ -1055,6 +1055,65 @@ BitsetType::bitset BitsetType::UnsignedSmall() {
return i::SmiValuesAre31Bits() ? kUnsigned30 : kUnsigned31;
}
// static
Type* Type::Tuple(Type* first, Type* second, Type* third, Zone* zone) {
TupleType* tuple = TupleType::New(3, zone);
tuple->InitElement(0, first);
tuple->InitElement(1, second);
tuple->InitElement(2, third);
return FromTypeBase(tuple);
}
// static
Type* Type::OtherNumberConstant(double value, Zone* zone) {
return FromTypeBase(OtherNumberConstantType::New(value, zone));
}
// static
Type* Type::HeapConstant(i::Handle<i::HeapObject> value, Zone* zone) {
return FromTypeBase(HeapConstantType::New(value, zone));
}
// static
Type* Type::Range(double min, double max, Zone* zone) {
return FromTypeBase(RangeType::New(min, max, zone));
}
// static
Type* Type::Range(RangeType::Limits lims, Zone* zone) {
return FromTypeBase(RangeType::New(lims, zone));
}
// static
Type* Type::Union(int length, Zone* zone) {
return FromTypeBase(UnionType::New(length, zone));
}
HeapConstantType* Type::AsHeapConstant() {
DCHECK(IsKind(TypeBase::kHeapConstant));
return static_cast<HeapConstantType*>(ToTypeBase());
}
OtherNumberConstantType* Type::AsOtherNumberConstant() {
DCHECK(IsKind(TypeBase::kOtherNumberConstant));
return static_cast<OtherNumberConstantType*>(ToTypeBase());
}
RangeType* Type::AsRange() {
DCHECK(IsKind(TypeBase::kRange));
return static_cast<RangeType*>(ToTypeBase());
}
TupleType* Type::AsTuple() {
DCHECK(IsKind(TypeBase::kTuple));
return static_cast<TupleType*>(ToTypeBase());
}
UnionType* Type::AsUnion() {
DCHECK(IsKind(TypeBase::kUnion));
return static_cast<UnionType*>(ToTypeBase());
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -217,7 +217,11 @@ namespace compiler {
INTERNAL_BITSET_TYPE_LIST(V) \
PROPER_BITSET_TYPE_LIST(V)
class HeapConstantType;
class OtherNumberConstantType;
class TupleType;
class Type;
class UnionType;
// -----------------------------------------------------------------------------
// Bitset types (internal).
......@@ -249,9 +253,7 @@ class V8_EXPORT_PRIVATE BitsetType {
static double Min(bitset);
static double Max(bitset);
static bitset Glb(Type* type); // greatest lower bound that's a bitset
static bitset Glb(double min, double max);
static bitset Lub(Type* type); // least upper bound that's a bitset
static bitset Lub(i::Map* map);
static bitset Lub(i::Object* value);
static bitset Lub(double value);
......@@ -266,19 +268,7 @@ class V8_EXPORT_PRIVATE BitsetType {
static bitset NumberBits(bitset bits);
static bool IsBitset(Type* type) {
return reinterpret_cast<uintptr_t>(type) & 1;
}
static Type* NewForTesting(bitset bits) { return New(bits); }
private:
friend class Type;
static Type* New(bitset bits) {
return reinterpret_cast<Type*>(static_cast<uintptr_t>(bits | 1u));
}
struct Boundary {
bitset internal;
bitset external;
......@@ -300,83 +290,12 @@ class TypeBase {
Kind kind() const { return kind_; }
explicit TypeBase(Kind kind) : kind_(kind) {}
static bool IsKind(Type* type, Kind kind) {
if (BitsetType::IsBitset(type)) return false;
TypeBase* base = reinterpret_cast<TypeBase*>(type);
return base->kind() == kind;
}
// The hacky conversion to/from Type*.
static Type* AsType(TypeBase* type) { return reinterpret_cast<Type*>(type); }
static TypeBase* FromType(Type* type) {
return reinterpret_cast<TypeBase*>(type);
}
static bool IsKind(Type* type, Kind kind);
private:
Kind kind_;
};
// -----------------------------------------------------------------------------
// Constant types.
class OtherNumberConstantType : public TypeBase {
public:
double Value() { return value_; }
static bool IsOtherNumberConstant(double value);
static bool IsOtherNumberConstant(Object* value);
private:
friend class Type;
friend class BitsetType;
static Type* New(double value, Zone* zone) {
return AsType(new (zone->New(sizeof(OtherNumberConstantType)))
OtherNumberConstantType(value)); // NOLINT
}
static OtherNumberConstantType* cast(Type* type) {
DCHECK(IsKind(type, kOtherNumberConstant));
return static_cast<OtherNumberConstantType*>(FromType(type));
}
explicit OtherNumberConstantType(double value)
: TypeBase(kOtherNumberConstant), value_(value) {
CHECK(IsOtherNumberConstant(value));
}
BitsetType::bitset Lub() { return BitsetType::kOtherNumber; }
double value_;
};
class V8_EXPORT_PRIVATE HeapConstantType : public NON_EXPORTED_BASE(TypeBase) {
public:
i::Handle<i::HeapObject> Value() { return object_; }
private:
friend class Type;
friend class BitsetType;
static Type* New(i::Handle<i::HeapObject> value, Zone* zone) {
BitsetType::bitset bitset = BitsetType::Lub(*value);
return AsType(new (zone->New(sizeof(HeapConstantType)))
HeapConstantType(bitset, value));
}
static HeapConstantType* cast(Type* type) {
DCHECK(IsKind(type, kHeapConstant));
return static_cast<HeapConstantType*>(FromType(type));
}
HeapConstantType(BitsetType::bitset bitset, i::Handle<i::HeapObject> object);
BitsetType::bitset Lub() { return bitset_; }
BitsetType::bitset bitset_;
Handle<i::HeapObject> object_;
};
// -----------------------------------------------------------------------------
// Range types.
......@@ -401,7 +320,7 @@ class RangeType : public TypeBase {
friend class BitsetType;
friend class UnionType;
static Type* New(double min, double max, Zone* zone) {
static RangeType* New(double min, double max, Zone* zone) {
return New(Limits(min, max), zone);
}
......@@ -409,17 +328,12 @@ class RangeType : public TypeBase {
return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities.
}
static Type* New(Limits lim, Zone* zone) {
static RangeType* New(Limits lim, Zone* zone) {
DCHECK(IsInteger(lim.min) && IsInteger(lim.max));
DCHECK(lim.min <= lim.max);
BitsetType::bitset bits = BitsetType::Lub(lim.min, lim.max);
return AsType(new (zone->New(sizeof(RangeType))) RangeType(bits, lim));
}
static RangeType* cast(Type* type) {
DCHECK(IsKind(type, kRange));
return static_cast<RangeType*>(FromType(type));
return new (zone->New(sizeof(RangeType))) RangeType(bits, lim);
}
RangeType(BitsetType::bitset bitset, Limits limits)
......@@ -432,91 +346,7 @@ class RangeType : public TypeBase {
};
// -----------------------------------------------------------------------------
// Superclass for types with variable number of type fields.
class StructuralType : public TypeBase {
public:
int LengthForTesting() { return Length(); }
protected:
friend class Type;
int Length() { return length_; }
Type* Get(int i) {
DCHECK(0 <= i && i < this->Length());
return elements_[i];
}
void Set(int i, Type* type) {
DCHECK(0 <= i && i < this->Length());
elements_[i] = type;
}
void Shrink(int length) {
DCHECK(2 <= length && length <= this->Length());
length_ = length;
}
StructuralType(Kind kind, int length, i::Zone* zone)
: TypeBase(kind), length_(length) {
elements_ = reinterpret_cast<Type**>(zone->New(sizeof(Type*) * length));
}
private:
int length_;
Type** elements_;
};
// -----------------------------------------------------------------------------
// Tuple types.
class TupleType : public StructuralType {
public:
int Arity() { return this->Length(); }
Type* Element(int i) { return this->Get(i); }
void InitElement(int i, Type* type) { this->Set(i, type); }
private:
friend class Type;
TupleType(int length, Zone* zone) : StructuralType(kTuple, length, zone) {}
static Type* New(int length, Zone* zone) {
return AsType(new (zone->New(sizeof(TupleType))) TupleType(length, zone));
}
static TupleType* cast(Type* type) {
DCHECK(IsKind(type, kTuple));
return static_cast<TupleType*>(FromType(type));
}
};
// -----------------------------------------------------------------------------
// Union types (internal).
// A union is a structured type with the following invariants:
// - its length is at least 2
// - at most one field is a bitset, and it must go into index 0
// - no field is a union
// - no field is a subtype of any other field
class UnionType : public StructuralType {
private:
friend Type;
friend BitsetType;
UnionType(int length, Zone* zone) : StructuralType(kUnion, length, zone) {}
static Type* New(int length, Zone* zone) {
return AsType(new (zone->New(sizeof(UnionType))) UnionType(length, zone));
}
static UnionType* cast(Type* type) {
DCHECK(IsKind(type, kUnion));
return static_cast<UnionType*>(FromType(type));
}
bool Wellformed();
};
// The actual type.
class V8_EXPORT_PRIVATE Type {
public:
......@@ -524,33 +354,21 @@ class V8_EXPORT_PRIVATE Type {
// Constructors.
#define DEFINE_TYPE_CONSTRUCTOR(type, value) \
static Type* type() { return BitsetType::New(BitsetType::k##type); }
static Type* type() { return NewBitset(BitsetType::k##type); }
PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
#undef DEFINE_TYPE_CONSTRUCTOR
static Type* SignedSmall() {
return BitsetType::New(BitsetType::SignedSmall());
}
static Type* SignedSmall() { return NewBitset(BitsetType::SignedSmall()); }
static Type* UnsignedSmall() {
return BitsetType::New(BitsetType::UnsignedSmall());
return NewBitset(BitsetType::UnsignedSmall());
}
static Type* OtherNumberConstant(double value, Zone* zone) {
return OtherNumberConstantType::New(value, zone);
}
static Type* HeapConstant(i::Handle<i::HeapObject> value, Zone* zone) {
return HeapConstantType::New(value, zone);
}
static Type* Range(double min, double max, Zone* zone) {
return RangeType::New(min, max, zone);
}
static Type* Tuple(Type* first, Type* second, Type* third, Zone* zone) {
Type* tuple = TupleType::New(3, zone);
tuple->AsTuple()->InitElement(0, first);
tuple->AsTuple()->InitElement(1, second);
tuple->AsTuple()->InitElement(2, third);
return tuple;
}
static Type* OtherNumberConstant(double value, Zone* zone);
static Type* HeapConstant(i::Handle<i::HeapObject> value, Zone* zone);
static Type* Range(double min, double max, Zone* zone);
static Type* Range(RangeType::Limits lims, Zone* zone);
static Type* Tuple(Type* first, Type* second, Type* third, Zone* zone);
static Type* Union(int length, Zone* zone);
// NewConstant is a factory that returns Constant, Range or Number.
static Type* NewConstant(i::Handle<i::Object> value, Zone* zone);
......@@ -560,17 +378,17 @@ class V8_EXPORT_PRIVATE Type {
static Type* Intersect(Type* type1, Type* type2, Zone* zone);
static Type* Of(double value, Zone* zone) {
return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(value)));
return NewBitset(BitsetType::ExpandInternals(BitsetType::Lub(value)));
}
static Type* Of(i::Object* value, Zone* zone) {
return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(value)));
return NewBitset(BitsetType::ExpandInternals(BitsetType::Lub(value)));
}
static Type* Of(i::Handle<i::Object> value, Zone* zone) {
return Of(*value, zone);
}
static Type* For(i::Map* map) {
return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(map)));
return NewBitset(BitsetType::ExpandInternals(BitsetType::Lub(map)));
}
static Type* For(i::Handle<i::Map> map) { return For(*map); }
......@@ -582,6 +400,7 @@ class V8_EXPORT_PRIVATE Type {
bool Equals(Type* that) { return this->Is(that) && that->Is(this); }
// Inspection.
bool IsBitset() { return reinterpret_cast<uintptr_t>(this) & 1; }
bool IsRange() { return IsKind(TypeBase::kRange); }
bool IsHeapConstant() { return IsKind(TypeBase::kHeapConstant); }
bool IsOtherNumberConstant() {
......@@ -589,12 +408,10 @@ class V8_EXPORT_PRIVATE Type {
}
bool IsTuple() { return IsKind(TypeBase::kTuple); }
HeapConstantType* AsHeapConstant() { return HeapConstantType::cast(this); }
OtherNumberConstantType* AsOtherNumberConstant() {
return OtherNumberConstantType::cast(this);
}
RangeType* AsRange() { return RangeType::cast(this); }
TupleType* AsTuple() { return TupleType::cast(this); }
HeapConstantType* AsHeapConstant();
OtherNumberConstantType* AsOtherNumberConstant();
RangeType* AsRange();
TupleType* AsTuple();
// Minimum and maximum of a numeric type.
// These functions do not distinguish between -0 and +0. NaN is ignored.
......@@ -623,10 +440,11 @@ class V8_EXPORT_PRIVATE Type {
#endif
// Helpers for testing.
bool IsBitsetForTesting() { return IsBitset(); }
bool IsUnionForTesting() { return IsUnion(); }
bitset AsBitsetForTesting() { return AsBitset(); }
UnionType* AsUnionForTesting() { return AsUnion(); }
Type* BitsetGlbForTesting() { return NewBitset(BitsetGlb()); }
Type* BitsetLubForTesting() { return NewBitset(BitsetLub()); }
private:
// Friends.
......@@ -636,23 +454,36 @@ class V8_EXPORT_PRIVATE Type {
friend UnionType;
// Internal inspection.
bool IsKind(TypeBase::Kind kind) { return TypeBase::IsKind(this, kind); }
bool IsKind(TypeBase::Kind kind) {
if (IsBitset()) return false;
TypeBase* base = reinterpret_cast<TypeBase*>(this);
return base->kind() == kind;
}
TypeBase* ToTypeBase() { return reinterpret_cast<TypeBase*>(this); }
static Type* FromTypeBase(TypeBase* type) {
return reinterpret_cast<Type*>(type);
}
bool IsAny() { return this == Any(); }
bool IsBitset() { return BitsetType::IsBitset(this); }
bool IsUnion() { return IsKind(TypeBase::kUnion); }
bitset AsBitset() {
DCHECK(this->IsBitset());
return reinterpret_cast<BitsetType*>(this)->Bitset();
}
UnionType* AsUnion() { return UnionType::cast(this); }
bitset BitsetGlb() { return BitsetType::Glb(this); }
bitset BitsetLub() { return BitsetType::Lub(this); }
UnionType* AsUnion();
bitset BitsetGlb(); // greatest lower bound that's a bitset
bitset BitsetLub(); // least upper bound that's a bitset
bool SlowIs(Type* that);
static Type* NewBitset(bitset bits) {
return reinterpret_cast<Type*>(static_cast<uintptr_t>(bits | 1u));
}
static bool Overlap(RangeType* lhs, RangeType* rhs);
static bool Contains(RangeType* lhs, RangeType* rhs);
static bool Contains(RangeType* range, i::Object* val);
......@@ -672,6 +503,134 @@ class V8_EXPORT_PRIVATE Type {
static Type* NormalizeRangeAndBitset(Type* range, bitset* bits, Zone* zone);
};
// -----------------------------------------------------------------------------
// Constant types.
class OtherNumberConstantType : public TypeBase {
public:
double Value() { return value_; }
static bool IsOtherNumberConstant(double value);
static bool IsOtherNumberConstant(Object* value);
private:
friend class Type;
friend class BitsetType;
static OtherNumberConstantType* New(double value, Zone* zone) {
return new (zone->New(sizeof(OtherNumberConstantType)))
OtherNumberConstantType(value); // NOLINT
}
explicit OtherNumberConstantType(double value)
: TypeBase(kOtherNumberConstant), value_(value) {
CHECK(IsOtherNumberConstant(value));
}
BitsetType::bitset Lub() { return BitsetType::kOtherNumber; }
double value_;
};
class V8_EXPORT_PRIVATE HeapConstantType : public NON_EXPORTED_BASE(TypeBase) {
public:
i::Handle<i::HeapObject> Value() { return object_; }
private:
friend class Type;
friend class BitsetType;
static HeapConstantType* New(i::Handle<i::HeapObject> value, Zone* zone) {
BitsetType::bitset bitset = BitsetType::Lub(*value);
return new (zone->New(sizeof(HeapConstantType)))
HeapConstantType(bitset, value);
}
HeapConstantType(BitsetType::bitset bitset, i::Handle<i::HeapObject> object);
BitsetType::bitset Lub() { return bitset_; }
BitsetType::bitset bitset_;
Handle<i::HeapObject> object_;
};
// -----------------------------------------------------------------------------
// Superclass for types with variable number of type fields.
class StructuralType : public TypeBase {
public:
int LengthForTesting() { return Length(); }
protected:
friend class Type;
int Length() { return length_; }
Type* Get(int i) {
DCHECK(0 <= i && i < this->Length());
return elements_[i];
}
void Set(int i, Type* type) {
DCHECK(0 <= i && i < this->Length());
elements_[i] = type;
}
void Shrink(int length) {
DCHECK(2 <= length && length <= this->Length());
length_ = length;
}
StructuralType(Kind kind, int length, i::Zone* zone)
: TypeBase(kind), length_(length) {
elements_ = reinterpret_cast<Type**>(zone->New(sizeof(Type*) * length));
}
private:
int length_;
Type** elements_;
};
// -----------------------------------------------------------------------------
// Tuple types.
class TupleType : public StructuralType {
public:
int Arity() { return this->Length(); }
Type* Element(int i) { return this->Get(i); }
void InitElement(int i, Type* type) { this->Set(i, type); }
private:
friend class Type;
TupleType(int length, Zone* zone) : StructuralType(kTuple, length, zone) {}
static TupleType* New(int length, Zone* zone) {
return new (zone->New(sizeof(TupleType))) TupleType(length, zone);
}
};
// -----------------------------------------------------------------------------
// Union types (internal).
// A union is a structured type with the following invariants:
// - its length is at least 2
// - at most one field is a bitset, and it must go into index 0
// - no field is a union
// - no field is a subtype of any other field
class UnionType : public StructuralType {
private:
friend Type;
friend BitsetType;
UnionType(int length, Zone* zone) : StructuralType(kUnion, length, zone) {}
static UnionType* New(int length, Zone* zone) {
return new (zone->New(sizeof(UnionType))) UnionType(length, zone);
}
bool Wellformed();
};
} // namespace compiler
} // namespace internal
} // namespace v8
......
......@@ -42,7 +42,7 @@ struct Tests {
zone(isolate->allocator(), ZONE_NAME),
T(&zone, isolate, isolate->random_number_generator()) {}
bool IsBitset(Type* type) { return type->IsBitsetForTesting(); }
bool IsBitset(Type* type) { return type->IsBitset(); }
bool IsUnion(Type* type) { return type->IsUnionForTesting(); }
BitsetType::bitset AsBitset(Type* type) { return type->AsBitsetForTesting(); }
UnionType* AsUnion(Type* type) { return type->AsUnionForTesting(); }
......@@ -404,7 +404,7 @@ struct Tests {
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Type* type = *it;
if (type->IsRange()) {
Type* lub = BitsetType::NewForTesting(BitsetType::Lub(type));
Type* lub = type->BitsetLubForTesting();
CHECK(lub->Min() <= type->Min() && type->Max() <= lub->Max());
}
}
......@@ -422,7 +422,7 @@ struct Tests {
// Lower: (T->BitsetGlb())->Is(T)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Type* type = *it;
Type* glb = BitsetType::NewForTesting(BitsetType::Glb(type));
Type* glb = type->BitsetGlbForTesting();
CHECK(glb->Is(type));
}
......@@ -431,7 +431,7 @@ struct Tests {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
Type* type1 = *it1;
Type* type2 = *it2;
Type* glb2 = BitsetType::NewForTesting(BitsetType::Glb(type2));
Type* glb2 = type2->BitsetGlbForTesting();
CHECK(!this->IsBitset(type1) || !type1->Is(type2) || type1->Is(glb2));
}
}
......@@ -441,8 +441,8 @@ struct Tests {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
Type* type1 = *it1;
Type* type2 = *it2;
Type* glb1 = BitsetType::NewForTesting(BitsetType::Glb(type1));
Type* glb2 = BitsetType::NewForTesting(BitsetType::Glb(type2));
Type* glb1 = type1->BitsetGlbForTesting();
Type* glb2 = type2->BitsetGlbForTesting();
CHECK(!type1->Is(type2) || glb1->Is(glb2));
}
}
......@@ -452,7 +452,7 @@ struct Tests {
// Upper: T->Is(T->BitsetLub())
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Type* type = *it;
Type* lub = BitsetType::NewForTesting(BitsetType::Lub(type));
Type* lub = type->BitsetLubForTesting();
CHECK(type->Is(lub));
}
......@@ -461,7 +461,7 @@ struct Tests {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
Type* type1 = *it1;
Type* type2 = *it2;
Type* lub1 = BitsetType::NewForTesting(BitsetType::Lub(type1));
Type* lub1 = type1->BitsetLubForTesting();
CHECK(!this->IsBitset(type2) || !type1->Is(type2) || lub1->Is(type2));
}
}
......@@ -471,8 +471,8 @@ struct Tests {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
Type* type1 = *it1;
Type* type2 = *it2;
Type* lub1 = BitsetType::NewForTesting(BitsetType::Lub(type1));
Type* lub2 = BitsetType::NewForTesting(BitsetType::Lub(type2));
Type* lub1 = type1->BitsetLubForTesting();
Type* lub2 = type2->BitsetLubForTesting();
CHECK(!type1->Is(type2) || lub1->Is(lub2));
}
}
......@@ -601,7 +601,7 @@ struct Tests {
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Type* type = *it;
if (type->IsRange()) {
Type* lub = BitsetType::NewForTesting(BitsetType::Lub(type));
Type* lub = type->BitsetLubForTesting();
CHECK(lub->Is(T.PlainNumber));
}
}
......
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