Commit 7e95e206 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Nuke class types.

There are no users of class types left inside TurboFan, so we can nuke
them and thereby simplify the type system quite a bit.

R=mvstanton@chromium.org
BUG=v8:5267,v8:5270

Review-Url: https://codereview.chromium.org/2309753002
Cr-Commit-Position: refs/heads/master@{#39152}
parent 776a5c10
......@@ -144,7 +144,6 @@ Type::bitset BitsetType::Lub(Type* type) {
}
return bitset;
}
if (type->IsClass()) return type->AsClass()->Lub();
if (type->IsConstant()) return type->AsConstant()->Lub();
if (type->IsRange()) return type->AsRange()->Lub();
if (type->IsContext()) return kOtherInternal & kTaggedPointer;
......@@ -409,10 +408,6 @@ double BitsetType::Max(bitset bits) {
bool Type::SimplyEquals(Type* that) {
DisallowHeapAllocation no_allocation;
if (this->IsClass()) {
return that->IsClass()
&& *this->AsClass()->Map() == *that->AsClass()->Map();
}
if (this->IsConstant()) {
return that->IsConstant()
&& *this->AsConstant()->Value() == *that->AsConstant()->Value();
......@@ -524,52 +519,6 @@ bool Type::SemanticIs(Type* that) {
return this->SimplyEquals(that);
}
// Most precise _current_ type of a value (usually its class).
Type* Type::NowOf(i::Object* value, Zone* zone) {
if (value->IsSmi() ||
i::HeapObject::cast(value)->map()->instance_type() == HEAP_NUMBER_TYPE) {
return Of(value, zone);
}
return Class(i::handle(i::HeapObject::cast(value)->map()), zone);
}
bool Type::NowContains(i::Object* value) {
DisallowHeapAllocation no_allocation;
if (this->IsAny()) return true;
if (value->IsHeapObject()) {
i::Map* map = i::HeapObject::cast(value)->map();
for (Iterator<i::Map> it = this->Classes(); !it.Done(); it.Advance()) {
if (*it.Current() == map) return true;
}
}
return this->Contains(value);
}
bool Type::NowIs(Type* that) {
DisallowHeapAllocation no_allocation;
// TODO(rossberg): this is incorrect for
// Union(Constant(V), T)->NowIs(Class(M))
// but fuzzing does not cover that!
if (this->IsConstant()) {
i::Object* object = *this->AsConstant()->Value();
if (object->IsHeapObject()) {
i::Map* map = i::HeapObject::cast(object)->map();
for (Iterator<i::Map> it = that->Classes(); !it.Done(); it.Advance()) {
if (*it.Current() == map) return true;
}
}
}
return this->Is(that);
}
// Check if [this] contains only (currently) stable classes.
bool Type::NowStable() {
DisallowHeapAllocation no_allocation;
return !this->IsClass() || this->AsClass()->Map()->is_stable();
}
// Check if [this] and [that] overlap.
bool Type::Maybe(Type* that) {
......@@ -607,8 +556,6 @@ bool Type::SemanticMaybe(Type* that) {
if (this->IsBitset() && that->IsBitset()) return true;
if (this->IsClass() != that->IsClass()) return true;
if (this->IsRange()) {
if (that->IsConstant()) {
return Contains(this->AsRange(), that->AsConstant());
......@@ -830,10 +777,6 @@ int Type::IntersectAux(Type* lhs, Type* rhs, UnionType* result, int size,
}
return size;
}
if (rhs->IsClass()) {
*lims =
RangeType::Limits::Union(RangeType::Limits(lhs->AsRange()), *lims);
}
if (rhs->IsConstant() && Contains(lhs->AsRange(), rhs->AsConstant())) {
return AddToUnion(rhs, result, size, zone);
}
......@@ -853,9 +796,6 @@ int Type::IntersectAux(Type* lhs, Type* rhs, UnionType* result, int size,
if (lhs->IsBitset() || rhs->IsBitset()) {
return AddToUnion(lhs->IsBitset() ? rhs : lhs, result, size, zone);
}
if (lhs->IsClass() != rhs->IsClass()) {
return AddToUnion(lhs->IsClass() ? rhs : lhs, result, size, zone);
}
if (lhs->SimplyEquals(rhs)) {
return AddToUnion(lhs, result, size, zone);
}
......@@ -1031,21 +971,6 @@ Type* Type::Semantic(Type* t, Zone* zone) {
// -----------------------------------------------------------------------------
// Iteration.
int Type::NumClasses() {
DisallowHeapAllocation no_allocation;
if (this->IsClass()) {
return 1;
} else if (this->IsUnion()) {
int result = 0;
for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
if (this->AsUnion()->Get(i)->IsClass()) ++result;
}
return result;
} else {
return 0;
}
}
int Type::NumConstants() {
DisallowHeapAllocation no_allocation;
if (this->IsConstant()) {
......@@ -1076,14 +1001,6 @@ struct TypeImplIteratorAux {
static i::Handle<T> current(Type* type);
};
template <>
struct TypeImplIteratorAux<i::Map> {
static bool matches(Type* type) { return type->IsClass(); }
static i::Handle<i::Map> current(Type* type) {
return type->AsClass()->Map();
}
};
template <>
struct TypeImplIteratorAux<i::Object> {
static bool matches(Type* type) { return type->IsConstant(); }
......@@ -1181,10 +1098,6 @@ void Type::PrintTo(std::ostream& os, PrintDimension dim) {
if (dim != REPRESENTATION_DIM) {
if (this->IsBitset()) {
BitsetType::Print(os, SEMANTIC(this->AsBitset()));
} else if (this->IsClass()) {
os << "Class(" << static_cast<void*>(*this->AsClass()->Map()) << " < ";
BitsetType::New(BitsetType::Lub(this))->PrintTo(os, dim);
os << ")";
} else if (this->IsConstant()) {
os << "Constant(" << Brief(*this->AsConstant()->Value()) << ")";
} else if (this->IsRange()) {
......@@ -1262,17 +1175,9 @@ BitsetType::bitset BitsetType::UnsignedSmall() {
return i::SmiValuesAre31Bits() ? kUnsigned30 : kUnsigned31;
}
#define CONSTRUCT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) \
Type* Type::Name(Isolate* isolate, Zone* zone) { \
return Class(i::handle(isolate->heap()->name##_map()), zone); \
}
SIMD128_TYPES(CONSTRUCT_SIMD_TYPE)
#undef CONSTRUCT_SIMD_TYPE
// -----------------------------------------------------------------------------
// Instantiations.
template class Type::Iterator<i::Map>;
template class Type::Iterator<i::Object>;
} // namespace internal
......
......@@ -45,7 +45,6 @@ namespace internal {
// OtherUndetectable < Object
// DetectableReceiver = Receiver - OtherUndetectable
//
// Class(map) < T iff instance_type(map) < T
// Constant(x) < T iff instance_type(map(x)) < T
// Array(T) < Array
// Function(R, S, T0, T1, ...) < Function
......@@ -56,12 +55,6 @@ namespace internal {
// 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.
// However, we also define a 'temporal' variant of the subtyping relation that
// considers the _current_ state only, i.e., Constant(x) <_now Class(map(x)).
//
//
// REPRESENTATIONAL DIMENSION
......@@ -140,11 +133,10 @@ namespace internal {
// IMPLEMENTATION
//
// Internally, all 'primitive' types, and their unions, are represented as
// bitsets. Bit 0 is reserved for tagging. Class is a heap pointer to the
// respective map. Only structured types require allocation.
// bitsets. Bit 0 is reserved for tagging. Only structured types require
// allocation.
// Note that the bitset representation is closed under both Union and Intersect.
// -----------------------------------------------------------------------------
// Values for bitset types
......@@ -356,7 +348,6 @@ class TypeBase {
friend class Type;
enum Kind {
kClass,
kConstant,
kContext,
kArray,
......@@ -385,36 +376,6 @@ class TypeBase {
Kind kind_;
};
// -----------------------------------------------------------------------------
// Class types.
class ClassType : public TypeBase {
public:
i::Handle<i::Map> Map() { return map_; }
private:
friend class Type;
friend class BitsetType;
static Type* New(i::Handle<i::Map> map, Zone* zone) {
return AsType(new (zone->New(sizeof(ClassType)))
ClassType(BitsetType::Lub(*map), map));
}
static ClassType* cast(Type* type) {
DCHECK(IsKind(type, kClass));
return static_cast<ClassType*>(FromType(type));
}
ClassType(BitsetType::bitset bitset, i::Handle<i::Map> map)
: TypeBase(kClass), bitset_(bitset), map_(map) {}
BitsetType::bitset Lub() { return bitset_; }
BitsetType::bitset bitset_;
Handle<i::Map> map_;
};
// -----------------------------------------------------------------------------
// Constant types.
......@@ -689,9 +650,6 @@ class Type {
return BitsetType::New(BitsetType::UnsignedSmall());
}
static Type* Class(i::Handle<i::Map> map, Zone* zone) {
return ClassType::New(map, zone);
}
static Type* Constant(i::Handle<i::Object> value, Zone* zone) {
return ConstantType::New(value, zone);
}
......@@ -746,11 +704,6 @@ class Type {
return tuple;
}
#define CONSTRUCT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) \
static Type* Name(Isolate* isolate, Zone* zone);
SIMD128_TYPES(CONSTRUCT_SIMD_TYPE)
#undef CONSTRUCT_SIMD_TYPE
static Type* Union(Type* type1, Type* type2, Zone* zone);
static Type* Intersect(Type* type1, Type* type2, Zone* zone);
......@@ -784,28 +737,14 @@ class Type {
bool Contains(i::Object* val);
bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); }
// State-dependent versions of the above that consider subtyping between
// a constant and its map class.
static Type* NowOf(i::Object* value, Zone* zone);
static Type* NowOf(i::Handle<i::Object> value, Zone* zone) {
return NowOf(*value, zone);
}
bool NowIs(Type* that);
bool NowContains(i::Object* val);
bool NowContains(i::Handle<i::Object> val) { return this->NowContains(*val); }
bool NowStable();
// Inspection.
bool IsRange() { return IsKind(TypeBase::kRange); }
bool IsClass() { return IsKind(TypeBase::kClass); }
bool IsConstant() { return IsKind(TypeBase::kConstant); }
bool IsContext() { return IsKind(TypeBase::kContext); }
bool IsArray() { return IsKind(TypeBase::kArray); }
bool IsFunction() { return IsKind(TypeBase::kFunction); }
bool IsTuple() { return IsKind(TypeBase::kTuple); }
ClassType* AsClass() { return ClassType::cast(this); }
ConstantType* AsConstant() { return ConstantType::cast(this); }
RangeType* AsRange() { return RangeType::cast(this); }
ContextType* AsContext() { return ContextType::cast(this); }
......@@ -829,7 +768,6 @@ class Type {
return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities.
}
int NumClasses();
int NumConstants();
template <class T>
......@@ -852,10 +790,6 @@ class Type {
int index_;
};
Iterator<i::Map> Classes() {
if (this->IsBitset()) return Iterator<i::Map>();
return Iterator<i::Map>(this);
}
Iterator<i::Object> Constants() {
if (this->IsBitset()) return Iterator<i::Object>();
return Iterator<i::Object>(this);
......
......@@ -36,9 +36,9 @@
namespace v8 {
namespace internal {
class Types {
class AstTypes {
public:
Types(Zone* zone, Isolate* isolate, v8::base::RandomNumberGenerator* rng)
AstTypes(Zone* zone, Isolate* isolate, v8::base::RandomNumberGenerator* rng)
: zone_(zone), isolate_(isolate), rng_(rng) {
#define DECLARE_TYPE(name, value) \
name = AstType::name(); \
......
......@@ -21,6 +21,8 @@
using namespace v8::internal;
namespace {
// Testing auxiliaries (breaking the Type abstraction).
static bool IsInteger(double x) {
......@@ -34,14 +36,14 @@ static bool IsInteger(i::Object* x) {
typedef uint32_t bitset;
struct Tests {
typedef Types::TypeVector::iterator TypeIterator;
typedef Types::MapVector::iterator MapIterator;
typedef Types::ValueVector::iterator ValueIterator;
typedef AstTypes::TypeVector::iterator TypeIterator;
typedef AstTypes::MapVector::iterator MapIterator;
typedef AstTypes::ValueVector::iterator ValueIterator;
Isolate* isolate;
HandleScope scope;
Zone zone;
Types T;
AstTypes T;
Tests()
: isolate(CcTest::InitIsolateOnce()),
......@@ -1845,6 +1847,8 @@ struct Tests {
}
};
} // namespace
TEST(AstIsSomeType_zone) { Tests().IsSomeType(); }
TEST(AstPointwiseRepresentation_zone) { Tests().PointwiseRepresentation(); }
......
......@@ -21,6 +21,7 @@
using namespace v8::internal;
namespace {
// Testing auxiliaries (breaking the Type abstraction).
......@@ -39,7 +40,6 @@ typedef uint32_t bitset;
struct Tests {
typedef Types::TypeVector::iterator TypeIterator;
typedef Types::MapVector::iterator MapIterator;
typedef Types::ValueVector::iterator ValueIterator;
Isolate* isolate;
......@@ -62,7 +62,6 @@ struct Tests {
return type1->Equals(type2) &&
this->IsBitset(type1) == this->IsBitset(type2) &&
this->IsUnion(type1) == this->IsUnion(type2) &&
type1->NumClasses() == type2->NumClasses() &&
type1->NumConstants() == type2->NumConstants() &&
(!this->IsBitset(type1) ||
this->AsBitset(type1) == this->AsBitset(type2)) &&
......@@ -113,8 +112,9 @@ struct Tests {
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Type* t = *it;
CHECK(1 ==
this->IsBitset(t) + t->IsClass() + t->IsConstant() + t->IsRange() +
this->IsUnion(t) + t->IsArray() + t->IsFunction() + t->IsContext());
this->IsBitset(t) + t->IsConstant() + t->IsRange() +
this->IsUnion(t) + t->IsArray() + t->IsFunction() +
t->IsContext());
}
}
......@@ -193,8 +193,6 @@ struct Tests {
int counter = 0;
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
counter++;
printf("Counter: %i\n", counter);
fflush(stdout);
Type* type1 = *it1;
Type* representation = T.Representation(type1);
Type* semantic = T.Semantic(type1);
......@@ -255,33 +253,6 @@ struct Tests {
}
}
void Class() {
// Constructor
for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
Handle<i::Map> map = *mt;
Type* type = T.Class(map);
CHECK(type->IsClass());
}
// Map attribute
for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
Handle<i::Map> map = *mt;
Type* type = T.Class(map);
CHECK(*map == *type->AsClass()->Map());
}
// Functionality & Injectivity: Class(M1) = Class(M2) iff M1 = M2
for (MapIterator mt1 = T.maps.begin(); mt1 != T.maps.end(); ++mt1) {
for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
Handle<i::Map> map1 = *mt1;
Handle<i::Map> map2 = *mt2;
Type* type1 = T.Class(map1);
Type* type2 = T.Class(map2);
CHECK(Equal(type1, type2) == (*map1 == *map2));
}
}
}
void Constant() {
// Constructor
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
......@@ -564,61 +535,6 @@ struct Tests {
}
}
void NowOf() {
// Constant(V)->NowIs(NowOf(V))
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Object> value = *vt;
Type* const_type = T.Constant(value);
Type* nowof_type = T.NowOf(value);
CHECK(const_type->NowIs(nowof_type));
}
// NowOf(V)->Is(Of(V))
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Object> value = *vt;
Type* nowof_type = T.NowOf(value);
Type* of_type = T.Of(value);
CHECK(nowof_type->Is(of_type));
}
// If NowOf(V)->NowIs(T), then Constant(V)->NowIs(T)
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Handle<i::Object> value = *vt;
Type* type = *it;
Type* const_type = T.Constant(value);
Type* nowof_type = T.NowOf(value);
CHECK(!nowof_type->NowIs(type) || const_type->NowIs(type));
}
}
// If Constant(V)->NowIs(T),
// then NowOf(V)->NowIs(T) or T->Maybe(Constant(V))
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Handle<i::Object> value = *vt;
Type* type = *it;
Type* const_type = T.Constant(value);
Type* nowof_type = T.NowOf(value);
CHECK(!const_type->NowIs(type) ||
nowof_type->NowIs(type) || type->Maybe(const_type));
}
}
// If Constant(V)->Is(T),
// then NowOf(V)->Is(T) or T->Maybe(Constant(V))
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Handle<i::Object> value = *vt;
Type* type = *it;
Type* const_type = T.Constant(value);
Type* nowof_type = T.NowOf(value);
CHECK(!const_type->Is(type) ||
nowof_type->Is(type) || type->Maybe(const_type));
}
}
}
void MinMax() {
// If b is regular numeric bitset, then Range(b->Min(), b->Max())->Is(b).
// TODO(neis): Need to ignore representation for this to be true.
......@@ -794,7 +710,6 @@ struct Tests {
Type* type2 = *j;
CHECK(!type1->Is(type2) || this->IsBitset(type2) ||
this->IsUnion(type2) || this->IsUnion(type1) ||
(type1->IsClass() && type2->IsClass()) ||
(type1->IsConstant() && type2->IsConstant()) ||
(type1->IsConstant() && type2->IsRange()) ||
(this->IsBitset(type1) && type2->IsRange()) ||
......@@ -808,17 +723,6 @@ struct Tests {
}
void Is2() {
// Class(M1)->Is(Class(M2)) iff M1 = M2
for (MapIterator mt1 = T.maps.begin(); mt1 != T.maps.end(); ++mt1) {
for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
Handle<i::Map> map1 = *mt1;
Handle<i::Map> map2 = *mt2;
Type* class_type1 = T.Class(map1);
Type* class_type2 = T.Class(map2);
CHECK(class_type1->Is(class_type2) == (*map1 == *map2));
}
}
// Range(X1, Y1)->Is(Range(X2, Y2)) iff X1 >= X2 /\ Y1 <= Y2
for (ValueIterator i1 = T.integers.begin();
i1 != T.integers.end(); ++i1) {
......@@ -959,13 +863,6 @@ struct Tests {
// Subtyping between concrete structural types
CheckSub(T.ObjectClass, T.Object);
CheckSub(T.ArrayClass, T.OtherObject);
CheckSub(T.UninitializedClass, T.Internal);
CheckUnordered(T.ObjectClass, T.ArrayClass);
CheckUnordered(T.UninitializedClass, T.Null);
CheckUnordered(T.UninitializedClass, T.Undefined);
CheckSub(T.SmiConstant, T.SignedSmall);
CheckSub(T.SmiConstant, T.Signed32);
CheckSub(T.SmiConstant, T.Number);
......@@ -980,12 +877,6 @@ struct Tests {
CheckUnordered(T.UninitializedConstant, T.Null);
CheckUnordered(T.UninitializedConstant, T.Undefined);
CheckUnordered(T.ObjectConstant1, T.ObjectClass);
CheckUnordered(T.ObjectConstant2, T.ObjectClass);
CheckUnordered(T.ObjectConstant1, T.ArrayClass);
CheckUnordered(T.ObjectConstant2, T.ArrayClass);
CheckUnordered(T.ArrayConstant, T.ObjectClass);
CheckSub(T.NumberArray, T.OtherObject);
CheckSub(T.NumberArray, T.Receiver);
CheckSub(T.NumberArray, T.Object);
......@@ -997,116 +888,6 @@ struct Tests {
CheckUnordered(T.NumberFunction1, T.NumberFunction2);
}
void NowIs() {
// Least Element (Bottom): None->NowIs(T)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Type* type = *it;
CHECK(T.None->NowIs(type));
}
// Greatest Element (Top): T->NowIs(Any)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Type* type = *it;
CHECK(type->NowIs(T.Any));
}
// Bottom Uniqueness: T->NowIs(None) implies T = None
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Type* type = *it;
if (type->NowIs(T.None)) CheckEqual(type, T.None);
}
// Top Uniqueness: Any->NowIs(T) implies T = Any
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Type* type = *it;
if (T.Any->NowIs(type)) CheckEqual(type, T.Any);
}
// Reflexivity: T->NowIs(T)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Type* type = *it;
CHECK(type->NowIs(type));
}
// Transitivity: T1->NowIs(T2) and T2->NowIs(T3) implies T1->NowIs(T3)
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
Type* type1 = *it1;
Type* type2 = *it2;
Type* type3 = *it3;
CHECK(!(type1->NowIs(type2) && type2->NowIs(type3)) ||
type1->NowIs(type3));
}
}
}
// Antisymmetry: T1->NowIs(T2) and T2->NowIs(T1) iff T1 = T2
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
Type* type1 = *it1;
Type* type2 = *it2;
CHECK((type1->NowIs(type2) && type2->NowIs(type1)) ==
Equal(type1, type2));
}
}
// T1->Is(T2) implies T1->NowIs(T2)
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
Type* type1 = *it1;
Type* type2 = *it2;
CHECK(!type1->Is(type2) || type1->NowIs(type2));
}
}
// Constant(V1)->NowIs(Constant(V2)) iff V1 = V2
for (ValueIterator vt1 = T.values.begin(); vt1 != T.values.end(); ++vt1) {
for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
Handle<i::Object> value1 = *vt1;
Handle<i::Object> value2 = *vt2;
Type* const_type1 = T.Constant(value1);
Type* const_type2 = T.Constant(value2);
CHECK(const_type1->NowIs(const_type2) == (*value1 == *value2));
}
}
// Class(M1)->NowIs(Class(M2)) iff M1 = M2
for (MapIterator mt1 = T.maps.begin(); mt1 != T.maps.end(); ++mt1) {
for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
Handle<i::Map> map1 = *mt1;
Handle<i::Map> map2 = *mt2;
Type* class_type1 = T.Class(map1);
Type* class_type2 = T.Class(map2);
CHECK(class_type1->NowIs(class_type2) == (*map1 == *map2));
}
}
// Constant(V)->NowIs(Class(M)) iff V has map M
for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Map> map = *mt;
Handle<i::Object> value = *vt;
Type* const_type = T.Constant(value);
Type* class_type = T.Class(map);
CHECK((value->IsHeapObject() &&
i::HeapObject::cast(*value)->map() == *map)
== const_type->NowIs(class_type));
}
}
// Class(M)->NowIs(Constant(V)) never
for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Map> map = *mt;
Handle<i::Object> value = *vt;
Type* const_type = T.Constant(value);
Type* class_type = T.Class(map);
CHECK(!class_type->NowIs(const_type));
}
}
}
void Contains() {
// T->Contains(V) iff Constant(V)->Is(T)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
......@@ -1119,37 +900,6 @@ struct Tests {
}
}
void NowContains() {
// T->NowContains(V) iff Constant(V)->NowIs(T)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Type* type = *it;
Handle<i::Object> value = *vt;
Type* const_type = T.Constant(value);
CHECK(type->NowContains(value) == const_type->NowIs(type));
}
}
// T->Contains(V) implies T->NowContains(V)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Type* type = *it;
Handle<i::Object> value = *vt;
CHECK(!type->Contains(value) || type->NowContains(value));
}
}
// NowOf(V)->Is(T) implies T->NowContains(V)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Type* type = *it;
Handle<i::Object> value = *vt;
Type* nowof_type = T.Of(value);
CHECK(!nowof_type->NowIs(type) || type->NowContains(value));
}
}
}
void Maybe() {
// T->Maybe(Any) iff T inhabited
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
......@@ -1219,45 +969,6 @@ struct Tests {
}
}
// Class(M1)->Maybe(Class(M2)) iff M1 = M2
for (MapIterator mt1 = T.maps.begin(); mt1 != T.maps.end(); ++mt1) {
for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
Handle<i::Map> map1 = *mt1;
Handle<i::Map> map2 = *mt2;
Type* class_type1 = T.Class(map1);
Type* class_type2 = T.Class(map2);
CHECK(class_type1->Maybe(class_type2) == (*map1 == *map2));
}
}
// Constant(V)->Maybe(Class(M)) never
// This does NOT hold!
/*
for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Map> map = *mt;
Handle<i::Object> value = *vt;
Type* const_type = T.Constant(value);
Type* class_type = T.Class(map);
CHECK(!const_type->Maybe(class_type));
}
}
*/
// Class(M)->Maybe(Constant(V)) never
// This does NOT hold!
/*
for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Map> map = *mt;
Handle<i::Object> value = *vt;
Type* const_type = T.Constant(value);
Type* class_type = T.Class(map);
CHECK(!class_type->Maybe(const_type));
}
}
*/
// Basic types
CheckDisjoint(T.Boolean, T.Null);
CheckDisjoint(T.Undefined, T.Null);
......@@ -1281,11 +992,6 @@ struct Tests {
CheckDisjoint(T.Object, T.Proxy);
// Structural types
CheckOverlap(T.ObjectClass, T.Object);
CheckOverlap(T.ArrayClass, T.Object);
CheckOverlap(T.ObjectClass, T.ObjectClass);
CheckOverlap(T.ArrayClass, T.ArrayClass);
CheckDisjoint(T.ObjectClass, T.ArrayClass);
CheckOverlap(T.SmiConstant, T.SignedSmall);
CheckOverlap(T.SmiConstant, T.Signed32);
CheckOverlap(T.SmiConstant, T.Number);
......@@ -1296,9 +1002,6 @@ struct Tests {
CheckOverlap(T.ObjectConstant1, T.ObjectConstant1);
CheckDisjoint(T.ObjectConstant1, T.ObjectConstant2);
CheckDisjoint(T.ObjectConstant1, T.ArrayConstant);
CheckOverlap(T.ObjectConstant1, T.ArrayClass);
CheckOverlap(T.ObjectConstant2, T.ArrayClass);
CheckOverlap(T.ArrayConstant, T.ObjectClass);
CheckOverlap(T.NumberArray, T.Receiver);
CheckDisjoint(T.NumberArray, T.AnyArray);
CheckDisjoint(T.NumberArray, T.StringArray);
......@@ -1307,9 +1010,6 @@ struct Tests {
CheckDisjoint(T.SignedFunction1, T.NumberFunction2);
CheckDisjoint(T.NumberFunction1, T.NumberFunction2);
CheckDisjoint(T.SignedFunction1, T.MethodFunction);
CheckOverlap(T.ObjectConstant1, T.ObjectClass); // !!!
CheckOverlap(T.ObjectConstant2, T.ObjectClass); // !!!
CheckOverlap(T.NumberClass, T.Intersect(T.Number, T.Tagged)); // !!!
}
void Union1() {
......@@ -1445,22 +1145,12 @@ struct Tests {
}
void Union4() {
// Class-class
CheckSub(T.Union(T.ObjectClass, T.ArrayClass), T.Object);
CheckOverlap(T.Union(T.ObjectClass, T.ArrayClass), T.OtherObject);
CheckOverlap(T.Union(T.ObjectClass, T.ArrayClass), T.Receiver);
CheckDisjoint(T.Union(T.ObjectClass, T.ArrayClass), T.Number);
// Constant-constant
CheckSub(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.Object);
CheckOverlap(T.Union(T.ObjectConstant1, T.ArrayConstant), T.OtherObject);
CheckUnordered(
T.Union(T.ObjectConstant1, T.ObjectConstant2), T.ObjectClass);
CheckOverlap(T.Union(T.ObjectConstant1, T.ArrayConstant), T.OtherObject);
CheckDisjoint(
T.Union(T.ObjectConstant1, T.ArrayConstant), T.Number);
CheckOverlap(
T.Union(T.ObjectConstant1, T.ArrayConstant), T.ObjectClass); // !!!
// Bitset-array
CHECK(this->IsBitset(T.Union(T.AnyArray, T.Receiver)));
......@@ -1481,14 +1171,6 @@ struct Tests {
CheckOverlap(T.Union(T.NumberFunction2, T.String), T.Object);
CheckDisjoint(T.Union(T.NumberFunction1, T.String), T.Number);
// Bitset-class
CheckSub(T.Union(T.ObjectClass, T.SignedSmall),
T.Union(T.Object, T.Number));
CheckSub(T.Union(T.ObjectClass, T.OtherObject), T.Object);
CheckUnordered(T.Union(T.ObjectClass, T.String), T.OtherObject);
CheckOverlap(T.Union(T.ObjectClass, T.String), T.Object);
CheckDisjoint(T.Union(T.ObjectClass, T.String), T.Number);
// Bitset-constant
CheckSub(
T.Union(T.ObjectConstant1, T.Signed32), T.Union(T.Object, T.Number));
......@@ -1497,32 +1179,6 @@ struct Tests {
CheckOverlap(T.Union(T.ObjectConstant1, T.String), T.Object);
CheckDisjoint(T.Union(T.ObjectConstant1, T.String), T.Number);
// Class-constant
CheckSub(T.Union(T.ObjectConstant1, T.ArrayClass), T.Object);
CheckUnordered(T.ObjectClass, T.Union(T.ObjectConstant1, T.ArrayClass));
CheckSub(T.Union(T.ObjectConstant1, T.ArrayClass),
T.Union(T.Receiver, T.Object));
CheckUnordered(T.Union(T.ObjectConstant1, T.ArrayClass), T.ArrayConstant);
CheckOverlap(T.Union(T.ObjectConstant1, T.ArrayClass), T.ObjectConstant2);
CheckOverlap(
T.Union(T.ObjectConstant1, T.ArrayClass), T.ObjectClass); // !!!
// Bitset-union
CheckSub(
T.NaN,
T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number));
CheckSub(
T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Signed32),
T.Union(T.ObjectConstant1, T.Union(T.Number, T.ArrayClass)));
// Class-union
CheckSub(
T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)),
T.Object);
CheckEqual(
T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass),
T.Union(T.ArrayClass, T.ObjectConstant2));
// Constant-union
CheckEqual(
T.Union(
......@@ -1552,9 +1208,6 @@ struct Tests {
T.Union(T.ObjectConstant2, T.ObjectConstant1),
T.Union(T.ObjectConstant1, T.ObjectConstant2)),
T.Union(T.ObjectConstant2, T.ObjectConstant1));
CheckEqual(T.Union(T.Union(T.Number, T.ArrayClass),
T.Union(T.SignedSmall, T.Receiver)),
T.Union(T.Number, T.Receiver));
}
void Intersect() {
......@@ -1590,48 +1243,6 @@ struct Tests {
}
}
// Associativity:
// Intersect(T1, Intersect(T2, T3)) = Intersect(Intersect(T1, T2), T3)
// This does NOT hold. For example:
// (Class(..stringy1..) /\ Class(..stringy2..)) /\ Constant(..string..) =
// None
// Class(..stringy1..) /\ (Class(..stringy2..) /\ Constant(..string..)) =
// Constant(..string..)
/*
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
Type* type1 = *it1;
Type* type2 = *it2;
Type* type3 = *it3;
Type* intersect12 = T.Intersect(type1, type2);
Type* intersect23 = T.Intersect(type2, type3);
Type* intersect1_23 = T.Intersect(type1, intersect23);
Type* intersect12_3 = T.Intersect(intersect12, type3);
CheckEqual(intersect1_23, intersect12_3);
}
}
}
*/
// Join: Intersect(T1, T2)->Is(T1) and Intersect(T1, T2)->Is(T2)
// This does NOT hold. For example:
// Class(..stringy..) /\ Constant(..string..) = Constant(..string..)
// Currently, not even the disjunction holds:
// Class(Internal/TaggedPtr) /\ (Any/Untagged \/ Context(..)) =
// Class(Internal/TaggedPtr) \/ Context(..)
/*
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
Type* type1 = *it1;
Type* type2 = *it2;
Type* intersect12 = T.Intersect(type1, type2);
CHECK(intersect12->Is(type1));
CHECK(intersect12->Is(type2));
}
}
*/
// Lower Boundedness: T1->Is(T2) implies Intersect(T1, T2) = T1
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
......@@ -1642,46 +1253,6 @@ struct Tests {
}
}
// Monotonicity: T1->Is(T2) implies Intersect(T1, T3)->Is(Intersect(T2, T3))
// This does NOT hold. For example:
// Class(OtherObject/TaggedPtr) <= Any/TaggedPtr
// Class(OtherObject/TaggedPtr) /\ Any/UntaggedInt1 = Class(..)
// Any/TaggedPtr /\ Any/UntaggedInt1 = None
/*
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
Type* type1 = *it1;
Type* type2 = *it2;
Type* type3 = *it3;
Type* intersect13 = T.Intersect(type1, type3);
Type* intersect23 = T.Intersect(type2, type3);
CHECK(!type1->Is(type2) || intersect13->Is(intersect23));
}
}
}
*/
// Monotonicity: T1->Is(T3) or T2->Is(T3) implies Intersect(T1, T2)->Is(T3)
// This does NOT hold. For example:
// Class(..stringy..) <= Class(..stringy..)
// Class(..stringy..) /\ Constant(..string..) = Constant(..string..)
// Constant(..string..) </= Class(..stringy..)
/*
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
Type* type1 = *it1;
Type* type2 = *it2;
Type* type3 = *it3;
Type* intersect12 = T.Intersect(type1, type2);
CHECK(!(type1->Is(type3) || type2->Is(type3)) ||
intersect12->Is(type3));
}
}
}
*/
// Monotonicity: T1->Is(T2) and T1->Is(T3) implies T1->Is(Intersect(T2, T3))
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
HandleScope scope(isolate);
......@@ -1697,10 +1268,6 @@ struct Tests {
}
}
// Bitset-class
CheckEqual(T.Intersect(T.ObjectClass, T.Object), T.ObjectClass);
CheckEqual(T.Semantic(T.Intersect(T.ObjectClass, T.Number)), T.None);
// Bitset-array
CheckEqual(T.Intersect(T.NumberArray, T.Object), T.NumberArray);
CheckEqual(T.Semantic(T.Intersect(T.AnyArray, T.Proxy)), T.None);
......@@ -1709,22 +1276,7 @@ struct Tests {
CheckEqual(T.Intersect(T.MethodFunction, T.Object), T.MethodFunction);
CheckEqual(T.Semantic(T.Intersect(T.NumberFunction1, T.Proxy)), T.None);
// Bitset-union
CheckEqual(
T.Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)),
T.Union(T.ObjectConstant1, T.ObjectClass));
CheckEqual(T.Semantic(T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant1),
T.Number)),
T.None);
// Class-constant
CHECK(T.Intersect(T.ObjectConstant1, T.ObjectClass)->IsInhabited()); // !!!
CHECK(T.Intersect(T.ArrayClass, T.ObjectConstant2)->IsInhabited());
// Array-union
CheckEqual(
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);
......@@ -1743,17 +1295,6 @@ struct Tests {
!T.Intersect(T.Union(T.MethodFunction, T.Name), T.NumberFunction2)
->IsInhabited());
// Class-union
CheckEqual(
T.Intersect(T.ArrayClass, T.Union(T.ObjectConstant2, T.ArrayClass)),
T.ArrayClass);
CheckEqual(
T.Intersect(T.ArrayClass, T.Union(T.Object, T.SmiConstant)),
T.ArrayClass);
CHECK(
T.Intersect(T.Union(T.ObjectClass, T.ArrayConstant), T.ArrayClass)
->IsInhabited()); // !!!
// Constant-union
CheckEqual(
T.Intersect(
......@@ -1762,34 +1303,13 @@ struct Tests {
CheckEqual(
T.Intersect(T.SmiConstant, T.Union(T.Number, T.ObjectConstant2)),
T.SmiConstant);
CHECK(
T.Intersect(
T.Union(T.ArrayConstant, T.ObjectClass), T.ObjectConstant1)
->IsInhabited()); // !!!
// Union-union
CheckEqual(T.Intersect(T.Union(T.Number, T.ArrayClass),
T.Union(T.SignedSmall, T.Receiver)),
T.Union(T.SignedSmall, T.ArrayClass));
CheckEqual(T.Intersect(T.Union(T.Number, T.ObjectClass),
T.Union(T.Signed32, T.OtherObject)),
T.Union(T.Signed32, T.ObjectClass));
CheckEqual(
T.Intersect(
T.Union(T.ObjectConstant2, T.ObjectConstant1),
T.Union(T.ObjectConstant1, T.ObjectConstant2)),
T.Union(T.ObjectConstant2, T.ObjectConstant1));
CheckEqual(
T.Intersect(
T.Union(
T.ArrayClass,
T.Union(T.ObjectConstant2, T.ObjectConstant1)),
T.Union(
T.ObjectConstant1,
T.Union(T.ArrayConstant, T.ObjectConstant2))),
T.Union(
T.ArrayConstant,
T.Union(T.ObjectConstant2, T.ObjectConstant1))); // !!!
}
void Distributivity() {
......@@ -1868,54 +1388,48 @@ struct Tests {
}
};
TEST(IsSomeType_zone) { Tests().IsSomeType(); }
TEST(PointwiseRepresentation_zone) { Tests().PointwiseRepresentation(); }
TEST(BitsetType_zone) { Tests().Bitset(); }
TEST(ClassType_zone) { Tests().Class(); }
} // namespace
TEST(ConstantType_zone) { Tests().Constant(); }
TEST(IsSomeType) { Tests().IsSomeType(); }
TEST(RangeType_zone) { Tests().Range(); }
TEST(PointwiseRepresentation) { Tests().PointwiseRepresentation(); }
TEST(ArrayType_zone) { Tests().Array(); }
TEST(BitsetType) { Tests().Bitset(); }
TEST(FunctionType_zone) { Tests().Function(); }
TEST(ConstantType) { Tests().Constant(); }
TEST(Of_zone) { Tests().Of(); }
TEST(RangeType) { Tests().Range(); }
TEST(NowOf_zone) { Tests().NowOf(); }
TEST(ArrayType) { Tests().Array(); }
TEST(MinMax_zone) { Tests().MinMax(); }
TEST(FunctionType) { Tests().Function(); }
TEST(BitsetGlb_zone) { Tests().BitsetGlb(); }
TEST(Of) { Tests().Of(); }
TEST(BitsetLub_zone) { Tests().BitsetLub(); }
TEST(MinMax) { Tests().MinMax(); }
TEST(Is1_zone) { Tests().Is1(); }
TEST(BitsetGlb) { Tests().BitsetGlb(); }
TEST(Is2_zone) { Tests().Is2(); }
TEST(BitsetLub) { Tests().BitsetLub(); }
TEST(NowIs_zone) { Tests().NowIs(); }
TEST(Is1) { Tests().Is1(); }
TEST(Contains_zone) { Tests().Contains(); }
TEST(Is2) { Tests().Is2(); }
TEST(NowContains_zone) { Tests().NowContains(); }
TEST(Contains) { Tests().Contains(); }
TEST(Maybe_zone) { Tests().Maybe(); }
TEST(Maybe) { Tests().Maybe(); }
TEST(Union1_zone) { Tests().Union1(); }
TEST(Union1) { Tests().Union1(); }
TEST(Union2_zone) { Tests().Union2(); }
TEST(Union2) { Tests().Union2(); }
TEST(Union3_zone) { Tests().Union3(); }
TEST(Union3) { Tests().Union3(); }
TEST(Union4_zone) { Tests().Union4(); }
TEST(Union4) { Tests().Union4(); }
TEST(Intersect_zone) { Tests().Intersect(); }
TEST(Intersect) { Tests().Intersect(); }
TEST(Distributivity_zone) { Tests().Distributivity(); }
TEST(Distributivity) { Tests().Distributivity(); }
TEST(GetRange_zone) { Tests().GetRange(); }
TEST(GetRange) { Tests().GetRange(); }
......@@ -36,11 +36,10 @@
namespace v8 {
namespace internal {
class Types {
public:
Types(Zone* zone, Isolate* isolate, v8::base::RandomNumberGenerator* rng)
: zone_(zone), isolate_(isolate), rng_(rng) {
: zone_(zone), rng_(rng) {
#define DECLARE_TYPE(name, value) \
name = Type::name(); \
types.push_back(name);
......@@ -52,22 +51,6 @@ class Types {
object_map = isolate->factory()->NewMap(
JS_OBJECT_TYPE, JSObject::kHeaderSize);
array_map = isolate->factory()->NewMap(
JS_ARRAY_TYPE, JSArray::kSize);
number_map = isolate->factory()->NewMap(
HEAP_NUMBER_TYPE, HeapNumber::kSize);
uninitialized_map = isolate->factory()->uninitialized_map();
ObjectClass = Type::Class(object_map, zone);
ArrayClass = Type::Class(array_map, zone);
NumberClass = Type::Class(number_map, zone);
UninitializedClass = Type::Class(uninitialized_map, zone);
maps.push_back(object_map);
maps.push_back(array_map);
maps.push_back(uninitialized_map);
for (MapVector::iterator it = maps.begin(); it != maps.end(); ++it) {
types.push_back(Type::Class(*it, zone));
}
smi = handle(Smi::FromInt(666), isolate);
signed32 = isolate->factory()->NewHeapNumber(0x40000000);
......@@ -121,9 +104,6 @@ class Types {
}
Handle<i::Map> object_map;
Handle<i::Map> array_map;
Handle<i::Map> number_map;
Handle<i::Map> uninitialized_map;
Handle<i::Smi> smi;
Handle<i::HeapNumber> signed32;
......@@ -142,11 +122,6 @@ class Types {
Type* SignedSmall;
Type* UnsignedSmall;
Type* ObjectClass;
Type* ArrayClass;
Type* NumberClass;
Type* UninitializedClass;
Type* SmiConstant;
Type* Signed32Constant;
Type* ObjectConstant1;
......@@ -166,20 +141,14 @@ class Types {
Type* MethodFunction;
typedef std::vector<Type*> TypeVector;
typedef std::vector<Handle<i::Map> > MapVector;
typedef std::vector<Handle<i::Object> > ValueVector;
TypeVector types;
MapVector maps;
ValueVector values;
ValueVector integers; // "Integer" values used for range limits.
Type* Of(Handle<i::Object> value) { return Type::Of(value, zone_); }
Type* NowOf(Handle<i::Object> value) { return Type::NowOf(value, zone_); }
Type* Class(Handle<i::Map> map) { return Type::Class(map, zone_); }
Type* Constant(Handle<i::Object> value) {
return Type::Constant(value, zone_);
}
......@@ -241,15 +210,11 @@ class Types {
}
return result;
}
case 1: { // class
int i = rng_->NextInt(static_cast<int>(maps.size()));
return Type::Class(maps[i], zone_);
}
case 2: { // constant
case 1: { // constant
int i = rng_->NextInt(static_cast<int>(values.size()));
return Type::Constant(values[i], zone_);
}
case 3: { // range
case 2: { // range
int i = rng_->NextInt(static_cast<int>(integers.size()));
int j = rng_->NextInt(static_cast<int>(integers.size()));
double min = integers[i]->Number();
......@@ -257,18 +222,18 @@ class Types {
if (min > max) std::swap(min, max);
return Type::Range(min, max, zone_);
}
case 4: { // context
case 3: { // context
int depth = rng_->NextInt(3);
Type* type = Type::Internal();
for (int i = 0; i < depth; ++i) type = Type::Context(type, zone_);
return type;
}
case 5: { // array
case 4: { // array
Type* element = Fuzz(depth / 2);
return Type::Array(element, zone_);
}
case 6:
case 7: { // function
case 5:
case 6: { // function
Type* result = Fuzz(depth / 2);
Type* receiver = Fuzz(depth / 2);
int arity = rng_->NextInt(3);
......@@ -279,20 +244,6 @@ class Types {
}
return type;
}
case 8: { // simd
static const int num_simd_types =
#define COUNT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) +1
SIMD128_TYPES(COUNT_SIMD_TYPE);
#undef COUNT_SIMD_TYPE
Type* (*simd_constructors[num_simd_types])(Isolate*, Zone*) = {
#define COUNT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) \
&Type::Name,
SIMD128_TYPES(COUNT_SIMD_TYPE)
#undef COUNT_SIMD_TYPE
};
return simd_constructors[rng_->NextInt(num_simd_types)](isolate_,
zone_);
}
default: { // union
int n = rng_->NextInt(10);
Type* type = None;
......@@ -310,7 +261,6 @@ class Types {
private:
Zone* zone_;
Isolate* isolate_;
v8::base::RandomNumberGenerator* rng_;
};
......
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