| Index: src/compiler/js-typed-lowering.cc
|
| diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc
|
| index a88658c408eed258899ff31448f2a6e9620a8f8c..8782e12375b3c5744a0c0a1e75ccf29b6c590f8c 100644
|
| --- a/src/compiler/js-typed-lowering.cc
|
| +++ b/src/compiler/js-typed-lowering.cc
|
| @@ -27,35 +27,50 @@ class JSBinopReduction final {
|
| JSBinopReduction(JSTypedLowering* lowering, Node* node)
|
| : lowering_(lowering), node_(node) {}
|
|
|
| - BinaryOperationHints::Hint GetNumberBinaryOperationFeedback() {
|
| + bool GetBinaryNumberOperationHint(NumberOperationHint* hint) {
|
| if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) {
|
| DCHECK_NE(0, node_->op()->ControlOutputCount());
|
| DCHECK_EQ(1, node_->op()->EffectOutputCount());
|
| DCHECK_LE(1, OperatorProperties::GetFrameStateInputCount(node_->op()));
|
| BinaryOperationHints hints = BinaryOperationHintsOf(node_->op());
|
| - BinaryOperationHints::Hint combined = hints.combined();
|
| - if (combined == BinaryOperationHints::kSignedSmall ||
|
| - combined == BinaryOperationHints::kSigned32 ||
|
| - combined == BinaryOperationHints::kNumberOrOddball) {
|
| - return combined;
|
| + switch (hints.combined()) {
|
| + case BinaryOperationHints::kNone:
|
| + *hint = NumberOperationHint::kNone;
|
| + return true;
|
| + case BinaryOperationHints::kSignedSmall:
|
| + case BinaryOperationHints::kSigned32:
|
| + *hint = NumberOperationHint::kSigned32;
|
| + return true;
|
| + case BinaryOperationHints::kNumberOrOddball:
|
| + *hint = NumberOperationHint::kNumberOrOddball;
|
| + return true;
|
| + case BinaryOperationHints::kString:
|
| + case BinaryOperationHints::kAny:
|
| + return false;
|
| }
|
| }
|
| - return BinaryOperationHints::kAny;
|
| + return false;
|
| }
|
|
|
| - CompareOperationHints::Hint GetNumberCompareOperationFeedback() {
|
| + bool GetCompareNumberOperationHint(NumberOperationHint* hint) {
|
| if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) {
|
| DCHECK_NE(0, node_->op()->ControlOutputCount());
|
| DCHECK_EQ(1, node_->op()->EffectOutputCount());
|
| DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op()));
|
| CompareOperationHints hints = CompareOperationHintsOf(node_->op());
|
| CompareOperationHints::Hint combined = hints.combined();
|
| - if (combined == CompareOperationHints::kSignedSmall ||
|
| - combined == CompareOperationHints::kNumberOrOddball) {
|
| - return combined;
|
| + if (combined == CompareOperationHints::kNone) {
|
| + *hint = NumberOperationHint::kNone;
|
| + return true;
|
| + } else if (combined == CompareOperationHints::kSignedSmall) {
|
| + *hint = NumberOperationHint::kSigned32;
|
| + return true;
|
| + } else if (combined == CompareOperationHints::kNumberOrOddball) {
|
| + *hint = NumberOperationHint::kNumberOrOddball;
|
| + return true;
|
| }
|
| }
|
| - return CompareOperationHints::kAny;
|
| + return false;
|
| }
|
|
|
| void ConvertInputsToNumber() {
|
| @@ -138,7 +153,12 @@ class JSBinopReduction final {
|
| return lowering_->Changed(node_);
|
| }
|
|
|
| - Reduction ChangeToSpeculativeOperator(const Operator* op, Type* upper_bound) {
|
| + Reduction ChangeToPureOperator(const Operator* op, Type* type) {
|
| + return ChangeToPureOperator(op, false, type);
|
| + }
|
| +
|
| + Reduction ChangeToSpeculativeOperator(const Operator* op,
|
| + Type* type = Type::Any()) {
|
| DCHECK_EQ(1, op->EffectInputCount());
|
| DCHECK_EQ(1, op->EffectOutputCount());
|
| DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
|
| @@ -181,16 +201,11 @@ class JSBinopReduction final {
|
|
|
| // Update the type to number.
|
| Type* node_type = NodeProperties::GetType(node_);
|
| - NodeProperties::SetType(node_,
|
| - Type::Intersect(node_type, upper_bound, zone()));
|
| + NodeProperties::SetType(node_, Type::Intersect(node_type, type, zone()));
|
|
|
| return lowering_->Changed(node_);
|
| }
|
|
|
| - Reduction ChangeToPureOperator(const Operator* op, Type* type) {
|
| - return ChangeToPureOperator(op, false, type);
|
| - }
|
| -
|
| bool LeftInputIs(Type* t) { return left_type()->Is(t); }
|
|
|
| bool RightInputIs(Type* t) { return right_type()->Is(t); }
|
| @@ -429,31 +444,6 @@ JSTypedLowering::JSTypedLowering(Editor* editor,
|
|
|
| Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
|
| JSBinopReduction r(this, node);
|
| - BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
|
| - if (feedback == BinaryOperationHints::kNumberOrOddball &&
|
| - r.BothInputsAre(Type::PlainPrimitive()) &&
|
| - r.NeitherInputCanBe(Type::StringOrReceiver())) {
|
| - // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
|
| - r.ConvertInputsToNumber();
|
| - return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
|
| - }
|
| - if (feedback != BinaryOperationHints::kAny) {
|
| - // Lower to the optimistic number binop.
|
| - return r.ChangeToSpeculativeOperator(
|
| - simplified()->SpeculativeNumberAdd(feedback), Type::Number());
|
| - }
|
| - if (r.BothInputsAre(Type::Number())) {
|
| - // JSAdd(x:number, y:number) => NumberAdd(x, y)
|
| - r.ConvertInputsToNumber();
|
| - return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
|
| - }
|
| - if ((r.BothInputsAre(Type::PlainPrimitive()) ||
|
| - !(flags() & kDeoptimizationEnabled)) &&
|
| - r.NeitherInputCanBe(Type::StringOrReceiver())) {
|
| - // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
|
| - r.ConvertInputsToNumber();
|
| - return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
|
| - }
|
| if (r.OneInputIs(Type::String())) {
|
| StringAddFlags flags = STRING_ADD_CHECK_NONE;
|
| if (!r.LeftInputIs(Type::String())) {
|
| @@ -474,25 +464,50 @@ Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
|
| NodeProperties::ChangeOp(node, common()->Call(desc));
|
| return Changed(node);
|
| }
|
| + NumberOperationHint hint;
|
| + if (r.GetBinaryNumberOperationHint(&hint)) {
|
| + if (hint == NumberOperationHint::kNumberOrOddball &&
|
| + r.BothInputsAre(Type::PlainPrimitive()) &&
|
| + r.NeitherInputCanBe(Type::StringOrReceiver())) {
|
| + // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
|
| + r.ConvertInputsToNumber();
|
| + return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
|
| + }
|
| + // Lower to the optimistic number binop.
|
| + return r.ChangeToSpeculativeOperator(
|
| + simplified()->SpeculativeNumberAdd(hint), Type::Number());
|
| + }
|
| + if (r.BothInputsAre(Type::Number())) {
|
| + // JSAdd(x:number, y:number) => NumberAdd(x, y)
|
| + r.ConvertInputsToNumber();
|
| + return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
|
| + }
|
| + if ((r.BothInputsAre(Type::PlainPrimitive()) ||
|
| + !(flags() & kDeoptimizationEnabled)) &&
|
| + r.NeitherInputCanBe(Type::StringOrReceiver())) {
|
| + // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
|
| + r.ConvertInputsToNumber();
|
| + return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
|
| + }
|
| return NoChange();
|
| }
|
|
|
|
|
| Reduction JSTypedLowering::ReduceJSSubtract(Node* node) {
|
| JSBinopReduction r(this, node);
|
| - BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
|
| - if (feedback == BinaryOperationHints::kNumberOrOddball &&
|
| - r.BothInputsAre(Type::PlainPrimitive())) {
|
| - // JSSubtract(x:plain-primitive, y:plain-primitive)
|
| - // => NumberSubtract(ToNumber(x), ToNumber(y))
|
| - r.ConvertInputsToNumber();
|
| - return r.ChangeToPureOperator(simplified()->NumberSubtract(),
|
| - Type::Number());
|
| - }
|
| - if (feedback != BinaryOperationHints::kAny) {
|
| + NumberOperationHint hint;
|
| + if (r.GetBinaryNumberOperationHint(&hint)) {
|
| + if (hint == NumberOperationHint::kNumberOrOddball &&
|
| + r.BothInputsAre(Type::PlainPrimitive())) {
|
| + // JSSubtract(x:plain-primitive, y:plain-primitive)
|
| + // => NumberSubtract(ToNumber(x), ToNumber(y))
|
| + r.ConvertInputsToNumber();
|
| + return r.ChangeToPureOperator(simplified()->NumberSubtract(),
|
| + Type::Number());
|
| + }
|
| // Lower to the optimistic number binop.
|
| return r.ChangeToSpeculativeOperator(
|
| - simplified()->SpeculativeNumberSubtract(feedback), Type::Number());
|
| + simplified()->SpeculativeNumberSubtract(hint));
|
| }
|
|
|
| // If deoptimization is enabled we rely on type feedback.
|
| @@ -508,18 +523,18 @@ Reduction JSTypedLowering::ReduceJSSubtract(Node* node) {
|
|
|
| Reduction JSTypedLowering::ReduceJSMultiply(Node* node) {
|
| JSBinopReduction r(this, node);
|
| - BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
|
| - if (feedback == BinaryOperationHints::kNumberOrOddball &&
|
| - r.BothInputsAre(Type::PlainPrimitive())) {
|
| - // JSMultiply(x:plain-primitive,
|
| - // y:plain-primitive) => NumberMultiply(ToNumber(x), ToNumber(y))
|
| - r.ConvertInputsToNumber();
|
| - return r.ChangeToPureOperator(simplified()->NumberMultiply(),
|
| - Type::Number());
|
| - }
|
| - if (feedback != BinaryOperationHints::kAny) {
|
| + NumberOperationHint hint;
|
| + if (r.GetBinaryNumberOperationHint(&hint)) {
|
| + if (hint == NumberOperationHint::kNumberOrOddball &&
|
| + r.BothInputsAre(Type::PlainPrimitive())) {
|
| + // JSMultiply(x:plain-primitive, y:plain-primitive)
|
| + // => NumberMultiply(ToNumber(x), ToNumber(y))
|
| + r.ConvertInputsToNumber();
|
| + return r.ChangeToPureOperator(simplified()->NumberMultiply(),
|
| + Type::Number());
|
| + }
|
| return r.ChangeToSpeculativeOperator(
|
| - simplified()->SpeculativeNumberMultiply(feedback), Type::Number());
|
| + simplified()->SpeculativeNumberMultiply(hint));
|
| }
|
|
|
| // If deoptimization is enabled we rely on type feedback.
|
| @@ -535,17 +550,18 @@ Reduction JSTypedLowering::ReduceJSMultiply(Node* node) {
|
|
|
| Reduction JSTypedLowering::ReduceJSDivide(Node* node) {
|
| JSBinopReduction r(this, node);
|
| - BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
|
| - if (feedback == BinaryOperationHints::kNumberOrOddball &&
|
| - r.BothInputsAre(Type::PlainPrimitive())) {
|
| - // JSDivide(x:plain-primitive,
|
| - // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y))
|
| - r.ConvertInputsToNumber();
|
| - return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number());
|
| - }
|
| - if (feedback != BinaryOperationHints::kAny) {
|
| + NumberOperationHint hint;
|
| + if (r.GetBinaryNumberOperationHint(&hint)) {
|
| + if (hint == NumberOperationHint::kNumberOrOddball &&
|
| + r.BothInputsAre(Type::PlainPrimitive())) {
|
| + // JSDivide(x:plain-primitive,
|
| + // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y))
|
| + r.ConvertInputsToNumber();
|
| + return r.ChangeToPureOperator(simplified()->NumberDivide(),
|
| + Type::Number());
|
| + }
|
| return r.ChangeToSpeculativeOperator(
|
| - simplified()->SpeculativeNumberDivide(feedback), Type::Number());
|
| + simplified()->SpeculativeNumberDivide(hint));
|
| }
|
| if (r.BothInputsAre(Type::PlainPrimitive())) {
|
| // JSDivide(x:plain-primitive,
|
| @@ -558,18 +574,18 @@ Reduction JSTypedLowering::ReduceJSDivide(Node* node) {
|
|
|
| Reduction JSTypedLowering::ReduceJSModulus(Node* node) {
|
| JSBinopReduction r(this, node);
|
| - BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
|
| - if (feedback == BinaryOperationHints::kNumberOrOddball &&
|
| - r.BothInputsAre(Type::PlainPrimitive())) {
|
| - // JSModulus(x:plain-primitive,
|
| - // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y))
|
| - r.ConvertInputsToNumber();
|
| - return r.ChangeToPureOperator(simplified()->NumberModulus(),
|
| - Type::Number());
|
| - }
|
| - if (feedback != BinaryOperationHints::kAny) {
|
| + NumberOperationHint hint;
|
| + if (r.GetBinaryNumberOperationHint(&hint)) {
|
| + if (hint == NumberOperationHint::kNumberOrOddball &&
|
| + r.BothInputsAre(Type::PlainPrimitive())) {
|
| + // JSModulus(x:plain-primitive,
|
| + // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y))
|
| + r.ConvertInputsToNumber();
|
| + return r.ChangeToPureOperator(simplified()->NumberModulus(),
|
| + Type::Number());
|
| + }
|
| return r.ChangeToSpeculativeOperator(
|
| - simplified()->SpeculativeNumberModulus(feedback), Type::Number());
|
| + simplified()->SpeculativeNumberModulus(hint));
|
| }
|
| if (r.BothInputsAre(Type::PlainPrimitive())) {
|
| // JSModulus(x:plain-primitive,
|
| @@ -594,11 +610,12 @@ Reduction JSTypedLowering::ReduceShiftLeft(Node* node) {
|
| if (flags() & kDisableIntegerBinaryOpReduction) return NoChange();
|
|
|
| JSBinopReduction r(this, node);
|
| - BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
|
| - if (feedback == BinaryOperationHints::kSigned32 ||
|
| - feedback == BinaryOperationHints::kSignedSmall) {
|
| - return r.ChangeToSpeculativeOperator(
|
| - simplified()->SpeculativeNumberShiftLeft(feedback), Type::Signed32());
|
| + NumberOperationHint hint;
|
| + if (r.GetBinaryNumberOperationHint(&hint)) {
|
| + if (hint == NumberOperationHint::kSigned32) {
|
| + return r.ChangeToSpeculativeOperator(
|
| + simplified()->SpeculativeNumberShiftLeft(hint));
|
| + }
|
| }
|
|
|
| // If deoptimization is enabled we rely on type feedback.
|
| @@ -607,7 +624,7 @@ Reduction JSTypedLowering::ReduceShiftLeft(Node* node) {
|
| r.ConvertInputsToNumber();
|
| r.ConvertInputsToUI32(kSigned, kUnsigned);
|
| return r.ChangeToPureOperator(simplified()->NumberShiftLeft(),
|
| - Type::Number());
|
| + Type::Signed32());
|
| }
|
| return NoChange();
|
| }
|
| @@ -623,7 +640,6 @@ Reduction JSTypedLowering::ReduceUI32Shift(Node* node,
|
| return r.ChangeToPureOperator(shift_op);
|
| }
|
|
|
| -
|
| Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
|
| JSBinopReduction r(this, node);
|
| if (r.BothInputsAre(Type::String())) {
|
| @@ -651,49 +667,45 @@ Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
|
| return Changed(node);
|
| }
|
|
|
| - CompareOperationHints::Hint hint = r.GetNumberCompareOperationFeedback();
|
| - if (hint != CompareOperationHints::kAny ||
|
| - r.OneInputCannotBe(Type::StringOrReceiver())) {
|
| - const Operator* less_than;
|
| - const Operator* less_than_or_equal;
|
| - if (hint != CompareOperationHints::kAny) {
|
| - less_than = simplified()->SpeculativeNumberLessThan(hint);
|
| - less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint);
|
| - } else if (r.BothInputsAre(Type::PlainPrimitive()) ||
|
| - !(flags() & kDeoptimizationEnabled)) {
|
| - r.ConvertInputsToNumber();
|
| - less_than = simplified()->NumberLessThan();
|
| - less_than_or_equal = simplified()->NumberLessThanOrEqual();
|
| - } else {
|
| + NumberOperationHint hint;
|
| + const Operator* less_than;
|
| + const Operator* less_than_or_equal;
|
| + if (r.GetCompareNumberOperationHint(&hint)) {
|
| + less_than = simplified()->SpeculativeNumberLessThan(hint);
|
| + less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint);
|
| + } else if (r.OneInputCannotBe(Type::StringOrReceiver()) &&
|
| + (!(flags() & kDeoptimizationEnabled) ||
|
| + r.BothInputsAre(Type::PlainPrimitive()))) {
|
| + r.ConvertInputsToNumber();
|
| + less_than = simplified()->NumberLessThan();
|
| + less_than_or_equal = simplified()->NumberLessThanOrEqual();
|
| + } else {
|
| + return NoChange();
|
| + }
|
| + const Operator* comparison;
|
| + switch (node->opcode()) {
|
| + case IrOpcode::kJSLessThan:
|
| + comparison = less_than;
|
| + break;
|
| + case IrOpcode::kJSGreaterThan:
|
| + comparison = less_than;
|
| + r.SwapInputs(); // a > b => b < a
|
| + break;
|
| + case IrOpcode::kJSLessThanOrEqual:
|
| + comparison = less_than_or_equal;
|
| + break;
|
| + case IrOpcode::kJSGreaterThanOrEqual:
|
| + comparison = less_than_or_equal;
|
| + r.SwapInputs(); // a >= b => b <= a
|
| + break;
|
| + default:
|
| return NoChange();
|
| - }
|
| - const Operator* comparison;
|
| - switch (node->opcode()) {
|
| - case IrOpcode::kJSLessThan:
|
| - comparison = less_than;
|
| - break;
|
| - case IrOpcode::kJSGreaterThan:
|
| - comparison = less_than;
|
| - r.SwapInputs(); // a > b => b < a
|
| - break;
|
| - case IrOpcode::kJSLessThanOrEqual:
|
| - comparison = less_than_or_equal;
|
| - break;
|
| - case IrOpcode::kJSGreaterThanOrEqual:
|
| - comparison = less_than_or_equal;
|
| - r.SwapInputs(); // a >= b => b <= a
|
| - break;
|
| - default:
|
| - return NoChange();
|
| - }
|
| - if (comparison->EffectInputCount() > 0) {
|
| - return r.ChangeToSpeculativeOperator(comparison, Type::Boolean());
|
| - } else {
|
| - return r.ChangeToPureOperator(comparison);
|
| - }
|
| }
|
| - // TODO(turbofan): relax/remove effects of this operator in other cases.
|
| - return NoChange(); // Keep a generic comparison.
|
| + if (comparison->EffectInputCount() > 0) {
|
| + return r.ChangeToSpeculativeOperator(comparison);
|
| + } else {
|
| + return r.ChangeToPureOperator(comparison);
|
| + }
|
| }
|
|
|
| Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) {
|
| @@ -773,6 +785,7 @@ Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) {
|
| }
|
| return Changed(node);
|
| }
|
| + // TODO(turbofan): Add support for comparison type feedback.
|
| return NoChange();
|
| }
|
|
|
|
|