diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc index bc3a78e526..5bd507e2c6 100644 --- a/src/compiler/typer.cc +++ b/src/compiler/typer.cc @@ -986,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; @@ -1042,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(); } @@ -1080,34 +1116,56 @@ 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(); } -// TODO(neis): Adapt all these for bigints. Why does this even work in the -// bigint tests? - Type* Typer::Visitor::JSExponentiateTyper(Type* lhs, Type* rhs, Typer* t) { - return Type::Number(); + return Type::Numeric(); } // JS unary operators. diff --git a/src/compiler/types.h b/src/compiler/types.h index 25d62a7697..d791ec25c5 100644 --- a/src/compiler/types.h +++ b/src/compiler/types.h @@ -171,6 +171,7 @@ namespace compiler { V(NumberOrOddball, kNumber | kNullOrUndefined | kBoolean | \ kHole) \ V(NumberOrString, kNumber | kString) \ + V(NumericOrString, kNumeric | kString) \ V(NumberOrUndefined, kNumber | kUndefined) \ V(NumberOrUndefinedOrNullOrBoolean, \ kNumber | kNullOrUndefined | kBoolean) \ diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc index c604a681b8..bfacb872dd 100644 --- a/src/compiler/verifier.cc +++ b/src/compiler/verifier.cc @@ -591,34 +591,24 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) { CheckTypeIs(node, Type::Boolean()); break; + case IrOpcode::kJSAdd: + CheckTypeIs(node, Type::NumericOrString()); + break; case IrOpcode::kJSBitwiseOr: case IrOpcode::kJSBitwiseXor: case IrOpcode::kJSBitwiseAnd: case IrOpcode::kJSShiftLeft: case IrOpcode::kJSShiftRight: case IrOpcode::kJSShiftRightLogical: - // Type is 32 bit integral. - CheckTypeIs(node, Type::Integral32()); - break; - case IrOpcode::kJSAdd: - // Type is Number or String. - CheckTypeIs(node, Type::NumberOrString()); - break; case IrOpcode::kJSSubtract: case IrOpcode::kJSMultiply: case IrOpcode::kJSDivide: case IrOpcode::kJSModulus: case IrOpcode::kJSExponentiate: - // Type is Number. - // TODO(neis): Adapt for bigints. - CheckTypeIs(node, Type::Number()); - break; - case IrOpcode::kJSBitwiseNot: case IrOpcode::kJSDecrement: case IrOpcode::kJSIncrement: case IrOpcode::kJSNegate: - // Type is Numeric. CheckTypeIs(node, Type::Numeric()); break;