summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/typer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/typer.cc')
-rw-r--r--deps/v8/src/compiler/typer.cc270
1 files changed, 208 insertions, 62 deletions
diff --git a/deps/v8/src/compiler/typer.cc b/deps/v8/src/compiler/typer.cc
index 2590342d2e..605a96c944 100644
--- a/deps/v8/src/compiler/typer.cc
+++ b/deps/v8/src/compiler/typer.cc
@@ -264,12 +264,18 @@ class Typer::Visitor : public Reducer {
static ComparisonOutcome Invert(ComparisonOutcome, Typer*);
static Type* FalsifyUndefined(ComparisonOutcome, Typer*);
+ static Type* BitwiseNot(Type*, Typer*);
+ static Type* Decrement(Type*, Typer*);
+ static Type* Increment(Type*, Typer*);
+ static Type* Negate(Type*, Typer*);
+
static Type* ToPrimitive(Type*, Typer*);
static Type* ToBoolean(Type*, Typer*);
static Type* ToInteger(Type*, Typer*);
static Type* ToLength(Type*, Typer*);
static Type* ToName(Type*, Typer*);
static Type* ToNumber(Type*, Typer*);
+ static Type* ToNumeric(Type*, Typer*);
static Type* ToObject(Type*, Typer*);
static Type* ToString(Type*, Typer*);
#define DECLARE_METHOD(Name) \
@@ -288,6 +294,7 @@ class Typer::Visitor : public Reducer {
#undef DECLARE_METHOD
static Type* ObjectIsArrayBufferView(Type*, Typer*);
+ static Type* ObjectIsBigInt(Type*, Typer*);
static Type* ObjectIsCallable(Type*, Typer*);
static Type* ObjectIsConstructor(Type*, Typer*);
static Type* ObjectIsDetectableCallable(Type*, Typer*);
@@ -314,6 +321,7 @@ class Typer::Visitor : public Reducer {
static Type* NumberLessThanTyper(Type*, Type*, Typer*);
static Type* NumberLessThanOrEqualTyper(Type*, Type*, Typer*);
static Type* ReferenceEqualTyper(Type*, Type*, Typer*);
+ static Type* SameValueTyper(Type*, Type*, Typer*);
static Type* StringFromCharCodeTyper(Type*, Typer*);
static Type* StringFromCodePointTyper(Type*, Typer*);
@@ -388,15 +396,15 @@ void Typer::Decorator::Decorate(Node* node) {
Type* Typer::Visitor::TypeUnaryOp(Node* node, UnaryTyperFun f) {
Type* input = Operand(node, 0);
- return input->IsInhabited() ? f(input, typer_) : Type::None();
+ return input->IsNone() ? Type::None() : f(input, typer_);
}
Type* Typer::Visitor::TypeBinaryOp(Node* node, BinaryTyperFun f) {
Type* left = Operand(node, 0);
Type* right = Operand(node, 1);
- return left->IsInhabited() && right->IsInhabited() ? f(left, right, typer_)
- : Type::None();
+ return left->IsNone() || right->IsNone() ? Type::None()
+ : f(left, right, typer_);
}
@@ -421,6 +429,38 @@ Type* Typer::Visitor::FalsifyUndefined(ComparisonOutcome outcome, Typer* t) {
return t->singleton_true_;
}
+Type* Typer::Visitor::BitwiseNot(Type* type, Typer* t) {
+ type = ToNumeric(type, t);
+ if (type->Is(Type::Number())) {
+ return NumberBitwiseXor(type, t->cache_.kSingletonMinusOne, t);
+ }
+ return Type::Numeric();
+}
+
+Type* Typer::Visitor::Decrement(Type* type, Typer* t) {
+ type = ToNumeric(type, t);
+ if (type->Is(Type::Number())) {
+ return NumberSubtract(type, t->cache_.kSingletonOne, t);
+ }
+ return Type::Numeric();
+}
+
+Type* Typer::Visitor::Increment(Type* type, Typer* t) {
+ type = ToNumeric(type, t);
+ if (type->Is(Type::Number())) {
+ return NumberAdd(type, t->cache_.kSingletonOne, t);
+ }
+ return Type::Numeric();
+}
+
+Type* Typer::Visitor::Negate(Type* type, Typer* t) {
+ type = ToNumeric(type, t);
+ if (type->Is(Type::Number())) {
+ return NumberMultiply(type, t->cache_.kSingletonMinusOne, t);
+ }
+ return Type::Numeric();
+}
+
// Type conversion.
Type* Typer::Visitor::ToPrimitive(Type* type, Typer* t) {
@@ -460,6 +500,7 @@ Type* Typer::Visitor::ToInteger(Type* type, Typer* t) {
Type* Typer::Visitor::ToLength(Type* type, Typer* t) {
// ES6 section 7.1.15 ToLength ( argument )
type = ToInteger(type, t);
+ if (type->IsNone()) return type;
double min = type->Min();
double max = type->Max();
if (max <= 0.0) {
@@ -489,6 +530,10 @@ Type* Typer::Visitor::ToNumber(Type* type, Typer* t) {
return t->operation_typer_.ToNumber(type);
}
+// static
+Type* Typer::Visitor::ToNumeric(Type* type, Typer* t) {
+ return t->operation_typer_.ToNumeric(type);
+}
// static
Type* Typer::Visitor::ToObject(Type* type, Typer* t) {
@@ -518,6 +563,12 @@ Type* Typer::Visitor::ObjectIsArrayBufferView(Type* type, Typer* t) {
return Type::Boolean();
}
+Type* Typer::Visitor::ObjectIsBigInt(Type* type, Typer* t) {
+ if (type->Is(Type::BigInt())) return t->singleton_true_;
+ if (!type->Maybe(Type::BigInt())) return t->singleton_false_;
+ return Type::Boolean();
+}
+
Type* Typer::Visitor::ObjectIsCallable(Type* type, Typer* t) {
if (type->Is(Type::Callable())) return t->singleton_true_;
if (!type->Maybe(Type::Callable())) return t->singleton_false_;
@@ -720,7 +771,7 @@ Type* Typer::Visitor::TypeInductionVariablePhi(Node* node) {
}
// If we do not have enough type information for the initial value or
// the increment, just return the initial value's type.
- if (!initial_type->IsInhabited() ||
+ if (initial_type->IsNone() ||
increment_type->Is(typer_->cache_.kSingletonZero)) {
return initial_type;
}
@@ -754,7 +805,7 @@ Type* Typer::Visitor::TypeInductionVariablePhi(Node* node) {
// If the type is not an integer, just skip the bound.
if (!bound_type->Is(typer_->cache_.kInteger)) continue;
// If the type is not inhabited, then we can take the initial value.
- if (!bound_type->IsInhabited()) {
+ if (bound_type->IsNone()) {
max = initial_type->Max();
break;
}
@@ -774,7 +825,7 @@ Type* Typer::Visitor::TypeInductionVariablePhi(Node* node) {
// If the type is not an integer, just skip the bound.
if (!bound_type->Is(typer_->cache_.kInteger)) continue;
// If the type is not inhabited, then we can take the initial value.
- if (!bound_type->IsInhabited()) {
+ if (bound_type->IsNone()) {
min = initial_type->Min();
break;
}
@@ -894,6 +945,10 @@ Type* Typer::Visitor::TypeTypeGuard(Node* node) {
Type* Typer::Visitor::TypeDead(Node* node) { return Type::None(); }
+Type* Typer::Visitor::TypeDeadValue(Node* node) { return Type::None(); }
+
+Type* Typer::Visitor::TypeUnreachable(Node* node) { UNREACHABLE(); }
+
// JS comparison operators.
@@ -914,38 +969,10 @@ Type* Typer::Visitor::JSEqualTyper(Type* lhs, Type* rhs, Typer* t) {
return Type::Boolean();
}
-
-static Type* JSType(Type* type) {
- if (type->Is(Type::Boolean())) return Type::Boolean();
- if (type->Is(Type::String())) return Type::String();
- if (type->Is(Type::Number())) return Type::Number();
- if (type->Is(Type::Undefined())) return Type::Undefined();
- if (type->Is(Type::Null())) return Type::Null();
- if (type->Is(Type::Symbol())) return Type::Symbol();
- if (type->Is(Type::Receiver())) return Type::Receiver(); // JS "Object"
- return Type::Any();
-}
-
-
Type* Typer::Visitor::JSStrictEqualTyper(Type* lhs, Type* rhs, Typer* t) {
- if (!JSType(lhs)->Maybe(JSType(rhs))) return t->singleton_false_;
- if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return t->singleton_false_;
- if (lhs->Is(Type::Number()) && rhs->Is(Type::Number()) &&
- (lhs->Max() < rhs->Min() || lhs->Min() > rhs->Max())) {
- return t->singleton_false_;
- }
- if ((lhs->Is(Type::Hole()) || rhs->Is(Type::Hole())) && !lhs->Maybe(rhs)) {
- return t->singleton_false_;
- }
- if (lhs->IsHeapConstant() && rhs->Is(lhs)) {
- // Types are equal and are inhabited only by a single semantic value,
- // which is not nan due to the earlier check.
- return t->singleton_true_;
- }
- return Type::Boolean();
+ return t->operation_typer()->StrictEqual(lhs, rhs);
}
-
// The EcmaScript specification defines the four relational comparison operators
// (<, <=, >=, >) with the help of a single abstract one. It behaves like <
// but returns undefined when the inputs cannot be compared.
@@ -959,12 +986,22 @@ Typer::Visitor::ComparisonOutcome Typer::Visitor::JSCompareTyper(Type* lhs,
return ComparisonOutcome(kComparisonTrue) |
ComparisonOutcome(kComparisonFalse);
}
- return NumberCompareTyper(ToNumber(lhs, t), ToNumber(rhs, t), t);
+ lhs = ToNumeric(lhs, t);
+ rhs = ToNumeric(rhs, t);
+ if (lhs->Is(Type::Number()) && rhs->Is(Type::Number())) {
+ return NumberCompareTyper(lhs, rhs, t);
+ }
+ return ComparisonOutcome(kComparisonTrue) |
+ ComparisonOutcome(kComparisonFalse) |
+ ComparisonOutcome(kComparisonUndefined);
}
Typer::Visitor::ComparisonOutcome Typer::Visitor::NumberCompareTyper(Type* lhs,
Type* rhs,
Typer* t) {
+ DCHECK(lhs->Is(Type::Number()));
+ DCHECK(rhs->Is(Type::Number()));
+
// Shortcut for NaNs.
if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return kComparisonUndefined;
@@ -1015,27 +1052,53 @@ Type* Typer::Visitor::JSGreaterThanOrEqualTyper(
Type* Typer::Visitor::JSBitwiseOrTyper(Type* lhs, Type* rhs, Typer* t) {
- return NumberBitwiseOr(ToNumber(lhs, t), ToNumber(rhs, t), t);
+ lhs = ToNumeric(lhs, t);
+ rhs = ToNumeric(rhs, t);
+ if (lhs->Is(Type::Number()) && rhs->Is(Type::Number())) {
+ return NumberBitwiseOr(lhs, rhs, t);
+ }
+ return Type::Numeric();
}
Type* Typer::Visitor::JSBitwiseAndTyper(Type* lhs, Type* rhs, Typer* t) {
- return NumberBitwiseAnd(ToNumber(lhs, t), ToNumber(rhs, t), t);
+ lhs = ToNumeric(lhs, t);
+ rhs = ToNumeric(rhs, t);
+ if (lhs->Is(Type::Number()) && rhs->Is(Type::Number())) {
+ return NumberBitwiseAnd(lhs, rhs, t);
+ }
+ return Type::Numeric();
}
Type* Typer::Visitor::JSBitwiseXorTyper(Type* lhs, Type* rhs, Typer* t) {
- return NumberBitwiseXor(ToNumber(lhs, t), ToNumber(rhs, t), t);
+ lhs = ToNumeric(lhs, t);
+ rhs = ToNumeric(rhs, t);
+ if (lhs->Is(Type::Number()) && rhs->Is(Type::Number())) {
+ return NumberBitwiseXor(lhs, rhs, t);
+ }
+ return Type::Numeric();
}
Type* Typer::Visitor::JSShiftLeftTyper(Type* lhs, Type* rhs, Typer* t) {
return NumberShiftLeft(ToNumber(lhs, t), ToNumber(rhs, t), t);
+ lhs = ToNumeric(lhs, t);
+ rhs = ToNumeric(rhs, t);
+ if (lhs->Is(Type::Number()) && rhs->Is(Type::Number())) {
+ return NumberShiftLeft(lhs, rhs, t);
+ }
+ return Type::Numeric();
}
Type* Typer::Visitor::JSShiftRightTyper(Type* lhs, Type* rhs, Typer* t) {
- return NumberShiftRight(ToNumber(lhs, t), ToNumber(rhs, t), t);
+ lhs = ToNumeric(lhs, t);
+ rhs = ToNumeric(rhs, t);
+ if (lhs->Is(Type::Number()) && rhs->Is(Type::Number())) {
+ return NumberShiftRight(lhs, rhs, t);
+ }
+ return Type::Numeric();
}
@@ -1053,45 +1116,88 @@ Type* Typer::Visitor::JSAddTyper(Type* lhs, Type* rhs, Typer* t) {
if (lhs->Is(Type::String()) || rhs->Is(Type::String())) {
return Type::String();
} else {
- return Type::NumberOrString();
+ return Type::NumericOrString();
}
}
// The addition must be numeric.
- return NumberAdd(ToNumber(lhs, t), ToNumber(rhs, t), t);
+ lhs = ToNumeric(lhs, t);
+ rhs = ToNumeric(rhs, t);
+ if (lhs->Is(Type::Number()) && rhs->Is(Type::Number())) {
+ return NumberAdd(lhs, rhs, t);
+ }
+ return Type::Numeric();
}
Type* Typer::Visitor::JSSubtractTyper(Type* lhs, Type* rhs, Typer* t) {
- return NumberSubtract(ToNumber(lhs, t), ToNumber(rhs, t), t);
+ lhs = ToNumeric(lhs, t);
+ rhs = ToNumeric(rhs, t);
+ if (lhs->Is(Type::Number()) && rhs->Is(Type::Number())) {
+ return NumberSubtract(lhs, rhs, t);
+ }
+ return Type::Numeric();
}
Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) {
- return NumberMultiply(ToNumber(lhs, t), ToNumber(rhs, t), t);
+ lhs = ToNumeric(lhs, t);
+ rhs = ToNumeric(rhs, t);
+ if (lhs->Is(Type::Number()) && rhs->Is(Type::Number())) {
+ return NumberMultiply(lhs, rhs, t);
+ }
+ return Type::Numeric();
}
Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) {
- return NumberDivide(ToNumber(lhs, t), ToNumber(rhs, t), t);
+ lhs = ToNumeric(lhs, t);
+ rhs = ToNumeric(rhs, t);
+ if (lhs->Is(Type::Number()) && rhs->Is(Type::Number())) {
+ return NumberDivide(lhs, rhs, t);
+ }
+ return Type::Numeric();
}
Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) {
- return NumberModulus(ToNumber(lhs, t), ToNumber(rhs, t), t);
+ lhs = ToNumeric(lhs, t);
+ rhs = ToNumeric(rhs, t);
+ if (lhs->Is(Type::Number()) && rhs->Is(Type::Number())) {
+ return NumberModulus(lhs, rhs, t);
+ }
+ return Type::Numeric();
}
+Type* Typer::Visitor::JSExponentiateTyper(Type* lhs, Type* rhs, Typer* t) {
+ return Type::Numeric();
+}
// JS unary operators.
-Type* Typer::Visitor::TypeJSClassOf(Node* node) {
+Type* Typer::Visitor::TypeJSBitwiseNot(Node* node) {
+ return TypeUnaryOp(node, BitwiseNot);
+}
+
+Type* Typer::Visitor::TypeJSDecrement(Node* node) {
+ return TypeUnaryOp(node, Decrement);
+}
+
+Type* Typer::Visitor::TypeJSIncrement(Node* node) {
+ return TypeUnaryOp(node, Increment);
+}
+
+Type* Typer::Visitor::TypeJSNegate(Node* node) {
+ return TypeUnaryOp(node, Negate);
+}
+
+Type* Typer::Visitor::TypeClassOf(Node* node) {
return Type::InternalizedStringOrNull();
}
-Type* Typer::Visitor::TypeJSTypeOf(Node* node) {
+Type* Typer::Visitor::TypeTypeOf(Node* node) {
return Type::InternalizedString();
}
// JS conversion operators.
-
-Type* Typer::Visitor::TypeJSToBoolean(Node* node) {
+Type* Typer::Visitor::TypeToBoolean(Node* node) {
return TypeUnaryOp(node, ToBoolean);
}
@@ -1111,6 +1217,10 @@ Type* Typer::Visitor::TypeJSToNumber(Node* node) {
return TypeUnaryOp(node, ToNumber);
}
+Type* Typer::Visitor::TypeJSToNumeric(Node* node) {
+ return TypeUnaryOp(node, ToNumeric);
+}
+
Type* Typer::Visitor::TypeJSToObject(Node* node) {
return TypeUnaryOp(node, ToObject);
}
@@ -1138,6 +1248,10 @@ Type* Typer::Visitor::TypeJSCreateArguments(Node* node) {
Type* Typer::Visitor::TypeJSCreateArray(Node* node) { return Type::Array(); }
+Type* Typer::Visitor::TypeJSCreateBoundFunction(Node* node) {
+ return Type::BoundFunction();
+}
+
Type* Typer::Visitor::TypeJSCreateGeneratorObject(Node* node) {
return Type::OtherObject();
}
@@ -1356,10 +1470,6 @@ Type* Typer::Visitor::TypeJSCreateBlockContext(Node* node) {
return Type::OtherInternal();
}
-Type* Typer::Visitor::TypeJSCreateScriptContext(Node* node) {
- return Type::OtherInternal();
-}
-
// JS other operators.
Type* Typer::Visitor::TypeJSConstructForwardVarargs(Node* node) {
@@ -1670,7 +1780,6 @@ Type* Typer::Visitor::TypeJSCallRuntime(Node* node) {
return Type::Boolean();
case Runtime::kInlineCreateIterResultObject:
return Type::OtherObject();
- case Runtime::kInlineSubString:
case Runtime::kInlineStringCharFromCode:
return Type::String();
case Runtime::kInlineToInteger:
@@ -1697,10 +1806,6 @@ Type* Typer::Visitor::TypeJSCallRuntime(Node* node) {
}
-Type* Typer::Visitor::TypeJSConvertReceiver(Node* node) {
- return Type::Receiver();
-}
-
Type* Typer::Visitor::TypeJSForInEnumerate(Node* node) {
return Type::OtherInternal();
}
@@ -1795,6 +1900,10 @@ Type* Typer::Visitor::TypeSpeculativeNumberLessThanOrEqual(Node* node) {
return TypeBinaryOp(node, NumberLessThanOrEqualTyper);
}
+Type* Typer::Visitor::TypeStringToNumber(Node* node) {
+ return TypeUnaryOp(node, ToNumber);
+}
+
Type* Typer::Visitor::TypePlainPrimitiveToNumber(Node* node) {
return TypeUnaryOp(node, ToNumber);
}
@@ -1820,6 +1929,15 @@ Type* Typer::Visitor::TypeReferenceEqual(Node* node) {
return TypeBinaryOp(node, ReferenceEqualTyper);
}
+// static
+Type* Typer::Visitor::SameValueTyper(Type* lhs, Type* rhs, Typer* t) {
+ return t->operation_typer()->SameValue(lhs, rhs);
+}
+
+Type* Typer::Visitor::TypeSameValue(Node* node) {
+ return TypeBinaryOp(node, SameValueTyper);
+}
+
Type* Typer::Visitor::TypeStringEqual(Node* node) { return Type::Boolean(); }
Type* Typer::Visitor::TypeStringLessThan(Node* node) { return Type::Boolean(); }
@@ -1858,18 +1976,21 @@ Type* Typer::Visitor::TypeStringFromCodePoint(Node* node) {
return TypeUnaryOp(node, StringFromCodePointTyper);
}
-Type* Typer::Visitor::TypeStringIndexOf(Node* node) {
- return Type::Range(-1.0, String::kMaxLength - 1.0, zone());
+Type* Typer::Visitor::TypeStringIndexOf(Node* node) { UNREACHABLE(); }
+
+Type* Typer::Visitor::TypeMaskIndexWithBound(Node* node) {
+ return Type::Union(Operand(node, 0), typer_->cache_.kSingletonZero, zone());
}
Type* Typer::Visitor::TypeCheckBounds(Node* node) {
Type* index = Operand(node, 0);
Type* length = Operand(node, 1);
+ DCHECK(length->Is(Type::Unsigned31()));
if (index->Maybe(Type::MinusZero())) {
index = Type::Union(index, typer_->cache_.kSingletonZero, zone());
}
index = Type::Intersect(index, Type::Integral32(), zone());
- if (!index->IsInhabited() || !length->IsInhabited()) return Type::None();
+ if (index->IsNone() || length->IsNone()) return Type::None();
double min = std::max(index->Min(), 0.0);
double max = std::min(index->Max(), length->Max() - 1);
if (max < min) return Type::None();
@@ -1935,15 +2056,28 @@ Type* Typer::Visitor::TypeCheckNotTaggedHole(Node* node) {
return type;
}
+Type* Typer::Visitor::TypeConvertReceiver(Node* node) {
+ Type* arg = Operand(node, 0);
+ return typer_->operation_typer_.ConvertReceiver(arg);
+}
+
Type* Typer::Visitor::TypeConvertTaggedHoleToUndefined(Node* node) {
Type* type = Operand(node, 0);
return typer_->operation_typer()->ConvertTaggedHoleToUndefined(type);
}
+Type* Typer::Visitor::TypeCheckEqualsInternalizedString(Node* node) {
+ UNREACHABLE();
+}
+
+Type* Typer::Visitor::TypeCheckEqualsSymbol(Node* node) { UNREACHABLE(); }
+
Type* Typer::Visitor::TypeAllocate(Node* node) {
return AllocateTypeOf(node->op());
}
+Type* Typer::Visitor::TypeAllocateRaw(Node* node) { UNREACHABLE(); }
+
Type* Typer::Visitor::TypeLoadFieldByIndex(Node* node) {
return Type::NonInternal();
}
@@ -1979,6 +2113,14 @@ Type* Typer::Visitor::TypeTransitionAndStoreElement(Node* node) {
UNREACHABLE();
}
+Type* Typer::Visitor::TypeTransitionAndStoreNumberElement(Node* node) {
+ UNREACHABLE();
+}
+
+Type* Typer::Visitor::TypeTransitionAndStoreNonNumberElement(Node* node) {
+ UNREACHABLE();
+}
+
Type* Typer::Visitor::TypeStoreSignedSmallElement(Node* node) { UNREACHABLE(); }
Type* Typer::Visitor::TypeStoreTypedElement(Node* node) {
@@ -1989,6 +2131,10 @@ Type* Typer::Visitor::TypeObjectIsArrayBufferView(Node* node) {
return TypeUnaryOp(node, ObjectIsArrayBufferView);
}
+Type* Typer::Visitor::TypeObjectIsBigInt(Node* node) {
+ return TypeUnaryOp(node, ObjectIsBigInt);
+}
+
Type* Typer::Visitor::TypeObjectIsCallable(Node* node) {
return TypeUnaryOp(node, ObjectIsCallable);
}