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