Commit 68b47f5e authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Also nuke Array and Function types.

We used to have Array types for typed arrays in asm.js at some point,
but had to change that quite some time ago already. And Function types
were mostly used for the CallInterfaceDescriptor (and the code-stub.js
experiment), but are also unusedn nowadays.

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

Review-Url: https://codereview.chromium.org/2310923002
Cr-Commit-Position: refs/heads/master@{#39168}
parent df29f3fd
......@@ -136,21 +136,7 @@ class TypeCache final {
Type* const kJSDateYearType =
Type::Union(Type::SignedSmall(), Type::NaN(), zone());
#define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \
Type* const k##TypeName##Array = CreateArray(k##TypeName);
TYPED_ARRAYS(TYPED_ARRAY)
#undef TYPED_ARRAY
private:
Type* CreateArray(Type* element) { return Type::Array(element, zone()); }
Type* CreateArrayFunction(Type* array) {
Type* arg1 = Type::Union(Type::Unsigned32(), Type::Object(), zone());
Type* arg2 = Type::Union(Type::Unsigned32(), Type::Undefined(), zone());
Type* arg3 = arg2;
return Type::Function(array, arg1, arg2, arg3, zone());
}
template <typename T>
Type* CreateRange() {
return CreateRange(std::numeric_limits<T>::min(),
......
......@@ -1273,9 +1273,6 @@ Type* Typer::Visitor::TypeJSCallConstruct(Node* node) {
Type* Typer::Visitor::JSCallFunctionTyper(Type* fun, Typer* t) {
if (fun->IsFunction()) {
return fun->AsFunction()->Result();
}
if (fun->IsConstant() && fun->AsConstant()->Value()->IsJSFunction()) {
Handle<JSFunction> function =
Handle<JSFunction>::cast(fun->AsConstant()->Value());
......
......@@ -146,8 +146,6 @@ Type::bitset BitsetType::Lub(Type* type) {
}
if (type->IsConstant()) return type->AsConstant()->Lub();
if (type->IsRange()) return type->AsRange()->Lub();
if (type->IsArray()) return kOtherObject;
if (type->IsFunction()) return kFunction;
if (type->IsTuple()) return kOtherInternal;
UNREACHABLE();
return kNone;
......@@ -411,24 +409,6 @@ bool Type::SimplyEquals(Type* that) {
return that->IsConstant()
&& *this->AsConstant()->Value() == *that->AsConstant()->Value();
}
if (this->IsArray()) {
return that->IsArray()
&& this->AsArray()->Element()->Equals(that->AsArray()->Element());
}
if (this->IsFunction()) {
if (!that->IsFunction()) return false;
FunctionType* this_fun = this->AsFunction();
FunctionType* that_fun = that->AsFunction();
if (this_fun->Arity() != that_fun->Arity() ||
!this_fun->Result()->Equals(that_fun->Result()) ||
!this_fun->Receiver()->Equals(that_fun->Receiver())) {
return false;
}
for (int i = 0, n = this_fun->Arity(); i < n; ++i) {
if (!this_fun->Parameter(i)->Equals(that_fun->Parameter(i))) return false;
}
return true;
}
if (this->IsTuple()) {
if (!that->IsTuple()) return false;
TupleType* this_tuple = this->AsTuple();
......@@ -1110,22 +1090,6 @@ void Type::PrintTo(std::ostream& os, PrintDimension dim) {
type_i->PrintTo(os, dim);
}
os << ")";
} else if (this->IsArray()) {
os << "Array(";
AsArray()->Element()->PrintTo(os, dim);
os << ")";
} else if (this->IsFunction()) {
if (!this->AsFunction()->Receiver()->IsAny()) {
this->AsFunction()->Receiver()->PrintTo(os, dim);
os << ".";
}
os << "(";
for (int i = 0; i < this->AsFunction()->Arity(); ++i) {
if (i > 0) os << ", ";
this->AsFunction()->Parameter(i)->PrintTo(os, dim);
}
os << ")->";
this->AsFunction()->Result()->PrintTo(os, dim);
} else if (this->IsTuple()) {
os << "<";
for (int i = 0, n = this->AsTuple()->Arity(); i < n; ++i) {
......
......@@ -39,21 +39,11 @@ namespace internal {
// InternalizedString < String
//
// Receiver = Object \/ Proxy
// Array < Object
// Function < Object
// RegExp < Object
// OtherUndetectable < Object
// DetectableReceiver = Receiver - OtherUndetectable
//
// Constant(x) < T iff instance_type(map(x)) < T
// Array(T) < Array
// Function(R, S, T0, T1, ...) < Function
//
// Both structural Array and Function types are invariant in all parameters;
// relaxing this would make Union and Intersect operations more involved.
// There is no subtyping relation between Array or Function types and
// respective Constant types, since these types cannot be reconstructed
// for arbitrary heap values.
//
//
// REPRESENTATIONAL DIMENSION
......@@ -348,8 +338,6 @@ class TypeBase {
enum Kind {
kConstant,
kArray,
kFunction,
kTuple,
kUnion,
kRange
......@@ -464,30 +452,6 @@ class RangeType : public TypeBase {
Limits limits_;
};
// -----------------------------------------------------------------------------
// Array types.
class ArrayType : public TypeBase {
public:
Type* Element() { return element_; }
private:
friend class Type;
explicit ArrayType(Type* element) : TypeBase(kArray), element_(element) {}
static Type* New(Type* element, Zone* zone) {
return AsType(new (zone->New(sizeof(ArrayType))) ArrayType(element));
}
static ArrayType* cast(Type* type) {
DCHECK(IsKind(type, kArray));
return static_cast<ArrayType*>(FromType(type));
}
Type* element_;
};
// -----------------------------------------------------------------------------
// Superclass for types with variable number of type fields.
class StructuralType : public TypeBase {
......@@ -524,38 +488,6 @@ class StructuralType : public TypeBase {
Type** elements_;
};
// -----------------------------------------------------------------------------
// Function types.
class FunctionType : public StructuralType {
public:
int Arity() { return this->Length() - 2; }
Type* Result() { return this->Get(0); }
Type* Receiver() { return this->Get(1); }
Type* Parameter(int i) { return this->Get(2 + i); }
void InitParameter(int i, Type* type) { this->Set(2 + i, type); }
private:
friend class Type;
FunctionType(Type* result, Type* receiver, int arity, Zone* zone)
: StructuralType(kFunction, 2 + arity, zone) {
Set(0, result);
Set(1, receiver);
}
static Type* New(Type* result, Type* receiver, int arity, Zone* zone) {
return AsType(new (zone->New(sizeof(FunctionType)))
FunctionType(result, receiver, arity, zone));
}
static FunctionType* cast(Type* type) {
DCHECK(IsKind(type, kFunction));
return static_cast<FunctionType*>(FromType(type));
}
};
// -----------------------------------------------------------------------------
// Tuple types.
......@@ -632,41 +564,6 @@ class Type {
BitsetType::kUntaggedNumber),
zone);
}
static Type* Array(Type* element, Zone* zone) {
return ArrayType::New(element, zone);
}
static Type* Function(Type* result, Type* receiver, int arity, Zone* zone) {
return FunctionType::New(result, receiver, arity, zone);
}
static Type* Function(Type* result, Zone* zone) {
return Function(result, Any(), 0, zone);
}
static Type* Function(Type* result, Type* param0, Zone* zone) {
Type* function = Function(result, Any(), 1, zone);
function->AsFunction()->InitParameter(0, param0);
return function;
}
static Type* Function(Type* result, Type* param0, Type* param1, Zone* zone) {
Type* function = Function(result, Any(), 2, zone);
function->AsFunction()->InitParameter(0, param0);
function->AsFunction()->InitParameter(1, param1);
return function;
}
static Type* Function(Type* result, Type* param0, Type* param1, Type* param2,
Zone* zone) {
Type* function = Function(result, Any(), 3, zone);
function->AsFunction()->InitParameter(0, param0);
function->AsFunction()->InitParameter(1, param1);
function->AsFunction()->InitParameter(2, param2);
return function;
}
static Type* Function(Type* result, int arity, Type** params, Zone* zone) {
Type* function = Function(result, Any(), arity, zone);
for (int i = 0; i < arity; ++i) {
function->AsFunction()->InitParameter(i, params[i]);
}
return function;
}
static Type* Tuple(Type* first, Type* second, Type* third, Zone* zone) {
Type* tuple = TupleType::New(3, zone);
tuple->AsTuple()->InitElement(0, first);
......@@ -711,14 +608,10 @@ class Type {
// Inspection.
bool IsRange() { return IsKind(TypeBase::kRange); }
bool IsConstant() { return IsKind(TypeBase::kConstant); }
bool IsArray() { return IsKind(TypeBase::kArray); }
bool IsFunction() { return IsKind(TypeBase::kFunction); }
bool IsTuple() { return IsKind(TypeBase::kTuple); }
ConstantType* AsConstant() { return ConstantType::cast(this); }
RangeType* AsRange() { return RangeType::cast(this); }
ArrayType* AsArray() { return ArrayType::cast(this); }
FunctionType* AsFunction() { return FunctionType::cast(this); }
TupleType* AsTuple() { return TupleType::cast(this); }
// Minimum and maximum of a numeric type.
......
......@@ -113,7 +113,7 @@ struct Tests {
Type* t = *it;
CHECK(1 ==
this->IsBitset(t) + t->IsConstant() + t->IsRange() +
this->IsUnion(t) + t->IsArray() + t->IsFunction());
this->IsUnion(t));
}
}
......@@ -378,102 +378,6 @@ struct Tests {
}
}
void Array() {
// Constructor
for (int i = 0; i < 20; ++i) {
Type* type = T.Random();
Type* array = T.Array1(type);
CHECK(array->IsArray());
}
// Attributes
for (int i = 0; i < 20; ++i) {
Type* type = T.Random();
Type* array = T.Array1(type);
CheckEqual(type, array->AsArray()->Element());
}
// Functionality & Injectivity: Array(T1) = Array(T2) iff T1 = T2
for (int i = 0; i < 20; ++i) {
for (int j = 0; j < 20; ++j) {
Type* type1 = T.Random();
Type* type2 = T.Random();
Type* array1 = T.Array1(type1);
Type* array2 = T.Array1(type2);
CHECK(Equal(array1, array2) == Equal(type1, type2));
}
}
}
void Function() {
// Constructors
for (int i = 0; i < 20; ++i) {
for (int j = 0; j < 20; ++j) {
for (int k = 0; k < 20; ++k) {
Type* type1 = T.Random();
Type* type2 = T.Random();
Type* type3 = T.Random();
Type* function0 = T.Function0(type1, type2);
Type* function1 = T.Function1(type1, type2, type3);
Type* function2 = T.Function2(type1, type2, type3);
CHECK(function0->IsFunction());
CHECK(function1->IsFunction());
CHECK(function2->IsFunction());
}
}
}
// Attributes
for (int i = 0; i < 20; ++i) {
for (int j = 0; j < 20; ++j) {
for (int k = 0; k < 20; ++k) {
Type* type1 = T.Random();
Type* type2 = T.Random();
Type* type3 = T.Random();
Type* function0 = T.Function0(type1, type2);
Type* function1 = T.Function1(type1, type2, type3);
Type* function2 = T.Function2(type1, type2, type3);
CHECK_EQ(0, function0->AsFunction()->Arity());
CHECK_EQ(1, function1->AsFunction()->Arity());
CHECK_EQ(2, function2->AsFunction()->Arity());
CheckEqual(type1, function0->AsFunction()->Result());
CheckEqual(type1, function1->AsFunction()->Result());
CheckEqual(type1, function2->AsFunction()->Result());
CheckEqual(type2, function0->AsFunction()->Receiver());
CheckEqual(type2, function1->AsFunction()->Receiver());
CheckEqual(T.Any, function2->AsFunction()->Receiver());
CheckEqual(type3, function1->AsFunction()->Parameter(0));
CheckEqual(type2, function2->AsFunction()->Parameter(0));
CheckEqual(type3, function2->AsFunction()->Parameter(1));
}
}
}
// Functionality & Injectivity: Function(Ts1) = Function(Ts2) iff Ts1 = Ts2
for (int i = 0; i < 20; ++i) {
for (int j = 0; j < 20; ++j) {
for (int k = 0; k < 20; ++k) {
Type* type1 = T.Random();
Type* type2 = T.Random();
Type* type3 = T.Random();
Type* function01 = T.Function0(type1, type2);
Type* function02 = T.Function0(type1, type3);
Type* function03 = T.Function0(type3, type2);
Type* function11 = T.Function1(type1, type2, type2);
Type* function12 = T.Function1(type1, type2, type3);
Type* function21 = T.Function2(type1, type2, type2);
Type* function22 = T.Function2(type1, type2, type3);
Type* function23 = T.Function2(type1, type3, type2);
CHECK(Equal(function01, function02) == Equal(type2, type3));
CHECK(Equal(function01, function03) == Equal(type1, type3));
CHECK(Equal(function11, function12) == Equal(type2, type3));
CHECK(Equal(function21, function22) == Equal(type2, type3));
CHECK(Equal(function21, function23) == Equal(type2, type3));
}
}
}
}
void Of() {
// Constant(V)->Is(Of(V))
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
......@@ -686,8 +590,6 @@ struct Tests {
(type1->IsConstant() && type2->IsRange()) ||
(this->IsBitset(type1) && type2->IsRange()) ||
(type1->IsRange() && type2->IsRange()) ||
(type1->IsArray() && type2->IsArray()) ||
(type1->IsFunction() && type2->IsFunction()) ||
!type1->IsInhabited());
}
}
......@@ -728,32 +630,6 @@ struct Tests {
}
}
// Array(T1)->Is(Array(T2)) 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* element1 = *it1;
Type* element2 = *it2;
Type* type1 = T.Array1(element1);
Type* type2 = T.Array1(element2);
CHECK(type1->Is(type2) == element1->Equals(element2));
}
}
// Function0(S1, T1)->Is(Function0(S2, T2)) iff S1 = S2 and T1 = T2
for (TypeIterator i = T.types.begin(); i != T.types.end(); ++i) {
for (TypeIterator j = T.types.begin(); j != T.types.end(); ++j) {
Type* result1 = *i;
Type* receiver1 = *j;
Type* type1 = T.Function0(result1, receiver1);
Type* result2 = T.Random();
Type* receiver2 = T.Random();
Type* type2 = T.Function0(result2, receiver2);
CHECK(type1->Is(type2) ==
(result1->Equals(result2) && receiver1->Equals(receiver2)));
}
}
// Range-specific subtyping
// If IsInteger(v) then Constant(v)->Is(Range(v, v)).
......@@ -836,16 +712,6 @@ struct Tests {
CheckUnordered(T.ObjectConstant1, T.ArrayConstant);
CheckUnordered(T.UninitializedConstant, T.Null);
CheckUnordered(T.UninitializedConstant, T.Undefined);
CheckSub(T.NumberArray, T.OtherObject);
CheckSub(T.NumberArray, T.Receiver);
CheckSub(T.NumberArray, T.Object);
CheckUnordered(T.StringArray, T.AnyArray);
CheckSub(T.MethodFunction, T.Object);
CheckSub(T.NumberFunction1, T.Object);
CheckUnordered(T.SignedFunction1, T.NumberFunction1);
CheckUnordered(T.NumberFunction1, T.NumberFunction2);
}
void Contains() {
......@@ -962,14 +828,6 @@ struct Tests {
CheckOverlap(T.ObjectConstant1, T.ObjectConstant1);
CheckDisjoint(T.ObjectConstant1, T.ObjectConstant2);
CheckDisjoint(T.ObjectConstant1, T.ArrayConstant);
CheckOverlap(T.NumberArray, T.Receiver);
CheckDisjoint(T.NumberArray, T.AnyArray);
CheckDisjoint(T.NumberArray, T.StringArray);
CheckOverlap(T.MethodFunction, T.Object);
CheckDisjoint(T.SignedFunction1, T.NumberFunction1);
CheckDisjoint(T.SignedFunction1, T.NumberFunction2);
CheckDisjoint(T.NumberFunction1, T.NumberFunction2);
CheckDisjoint(T.SignedFunction1, T.MethodFunction);
}
void Union1() {
......@@ -1112,25 +970,6 @@ struct Tests {
CheckDisjoint(
T.Union(T.ObjectConstant1, T.ArrayConstant), T.Number);
// Bitset-array
CHECK(this->IsBitset(T.Union(T.AnyArray, T.Receiver)));
CHECK(this->IsUnion(T.Union(T.NumberArray, T.Number)));
CheckEqual(T.Union(T.AnyArray, T.Receiver), T.Receiver);
CheckEqual(T.Union(T.AnyArray, T.OtherObject), T.OtherObject);
CheckUnordered(T.Union(T.AnyArray, T.String), T.Receiver);
CheckOverlap(T.Union(T.NumberArray, T.String), T.Object);
CheckDisjoint(T.Union(T.NumberArray, T.String), T.Number);
// Bitset-function
CHECK(this->IsBitset(T.Union(T.MethodFunction, T.Object)));
CHECK(this->IsUnion(T.Union(T.NumberFunction1, T.Number)));
CheckEqual(T.Union(T.MethodFunction, T.Object), T.Object);
CheckUnordered(T.Union(T.NumberFunction1, T.String), T.Object);
CheckOverlap(T.Union(T.NumberFunction2, T.String), T.Object);
CheckDisjoint(T.Union(T.NumberFunction1, T.String), T.Number);
// Bitset-constant
CheckSub(
T.Union(T.ObjectConstant1, T.Signed32), T.Union(T.Object, T.Number));
......@@ -1150,18 +989,6 @@ struct Tests {
T.Union(
T.ObjectConstant2, T.Union(T.ArrayConstant, T.ObjectConstant1)));
// Array-union
CheckEqual(
T.Union(T.AnyArray, T.Union(T.NumberArray, T.AnyArray)),
T.Union(T.AnyArray, T.NumberArray));
CheckSub(T.Union(T.AnyArray, T.NumberArray), T.OtherObject);
// Function-union
CheckEqual(
T.Union(T.NumberFunction1, T.NumberFunction2),
T.Union(T.NumberFunction2, T.NumberFunction1));
CheckSub(T.Union(T.SignedFunction1, T.MethodFunction), T.Object);
// Union-union
CheckEqual(
T.Union(
......@@ -1228,33 +1055,6 @@ struct Tests {
}
}
// Bitset-array
CheckEqual(T.Intersect(T.NumberArray, T.Object), T.NumberArray);
CheckEqual(T.Semantic(T.Intersect(T.AnyArray, T.Proxy)), T.None);
// Bitset-function
CheckEqual(T.Intersect(T.MethodFunction, T.Object), T.MethodFunction);
CheckEqual(T.Semantic(T.Intersect(T.NumberFunction1, T.Proxy)), T.None);
// Array-union
CheckEqual(
T.Intersect(T.AnyArray, T.Union(T.Object, T.SmiConstant)),
T.AnyArray);
CHECK(
!T.Intersect(T.Union(T.AnyArray, T.ArrayConstant), T.NumberArray)
->IsInhabited());
// Function-union
CheckEqual(
T.Intersect(T.MethodFunction, T.Union(T.String, T.MethodFunction)),
T.MethodFunction);
CheckEqual(
T.Intersect(T.NumberFunction1, T.Union(T.Object, T.SmiConstant)),
T.NumberFunction1);
CHECK(
!T.Intersect(T.Union(T.MethodFunction, T.Name), T.NumberFunction2)
->IsInhabited());
// Constant-union
CheckEqual(
T.Intersect(
......@@ -1360,10 +1160,6 @@ TEST(ConstantType) { Tests().Constant(); }
TEST(RangeType) { Tests().Range(); }
TEST(ArrayType) { Tests().Array(); }
TEST(FunctionType) { Tests().Function(); }
TEST(Of) { Tests().Of(); }
TEST(MinMax) { Tests().MinMax(); }
......
......@@ -89,15 +89,6 @@ class Types {
Integer = Type::Range(-V8_INFINITY, +V8_INFINITY, zone);
NumberArray = Type::Array(Number, zone);
StringArray = Type::Array(String, zone);
AnyArray = Type::Array(Any, zone);
SignedFunction1 = Type::Function(SignedSmall, SignedSmall, zone);
NumberFunction1 = Type::Function(Number, Number, zone);
NumberFunction2 = Type::Function(Number, Number, Number, zone);
MethodFunction = Type::Function(String, Object, 0, zone);
for (int i = 0; i < 30; ++i) {
types.push_back(Fuzz());
}
......@@ -131,15 +122,6 @@ class Types {
Type* Integer;
Type* NumberArray;
Type* StringArray;
Type* AnyArray;
Type* SignedFunction1;
Type* NumberFunction1;
Type* NumberFunction2;
Type* MethodFunction;
typedef std::vector<Type*> TypeVector;
typedef std::vector<Handle<i::Object> > ValueVector;
......@@ -155,22 +137,6 @@ class Types {
Type* Range(double min, double max) { return Type::Range(min, max, zone_); }
Type* Array1(Type* element) { return Type::Array(element, zone_); }
Type* Function0(Type* result, Type* receiver) {
return Type::Function(result, receiver, 0, zone_);
}
Type* Function1(Type* result, Type* receiver, Type* arg) {
Type* type = Type::Function(result, receiver, 1, zone_);
type->AsFunction()->InitParameter(0, arg);
return type;
}
Type* Function2(Type* result, Type* arg1, Type* arg2) {
return Type::Function(result, arg1, arg2, zone_);
}
Type* Union(Type* t1, Type* t2) { return Type::Union(t1, t2, zone_); }
Type* Intersect(Type* t1, Type* t2) { return Type::Intersect(t1, t2, zone_); }
......@@ -220,22 +186,6 @@ class Types {
if (min > max) std::swap(min, max);
return Type::Range(min, max, zone_);
}
case 3: { // array
Type* element = Fuzz(depth / 2);
return Type::Array(element, zone_);
}
case 4:
case 5: { // function
Type* result = Fuzz(depth / 2);
Type* receiver = Fuzz(depth / 2);
int arity = rng_->NextInt(3);
Type* type = Type::Function(result, receiver, arity, zone_);
for (int i = 0; i < type->AsFunction()->Arity(); ++i) {
Type* parameter = Fuzz(depth / 2);
type->AsFunction()->InitParameter(i, parameter);
}
return type;
}
default: { // union
int n = rng_->NextInt(10);
Type* type = None;
......
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