diff options
Diffstat (limited to 'deps/v8/src/compiler/typer.cc')
-rw-r--r-- | deps/v8/src/compiler/typer.cc | 270 |
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); } |