Index: src/compiler/js-typed-lowering.cc |
diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc |
index 8375ece60cd1e2393b104d91182ff63adac67ae8..b5c8af66cf309afc491b01e09a9537ce88324c91 100644 |
--- a/src/compiler/js-typed-lowering.cc |
+++ b/src/compiler/js-typed-lowering.cc |
@@ -27,6 +27,24 @@ class JSBinopReduction final { |
JSBinopReduction(JSTypedLowering* lowering, Node* node) |
: lowering_(lowering), node_(node) {} |
+ BinaryOperationHints::Hint GetUsableNumberFeedback() { |
+ if (!(lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) || |
+ !(lowering_->flags() & JSTypedLowering::kTypeFeedbackEnabled)) { |
+ return BinaryOperationHints::kAny; |
+ } |
+ DCHECK_NE(0, node_->op()->ControlOutputCount()); |
+ DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
+ DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node_->op())); |
+ BinaryOperationHints hints = BinaryOperationHintsOf(node_->op()); |
+ BinaryOperationHints::Hint combined = hints.combined(); |
+ if (combined == BinaryOperationHints::kSignedSmall || |
+ combined == BinaryOperationHints::kSigned32 || |
+ combined == BinaryOperationHints::kNumberOrUndefined) { |
+ return combined; |
+ } |
+ return BinaryOperationHints::kAny; |
+ } |
+ |
void ConvertInputsToNumberOrUndefined(Node* frame_state) { |
// To convert the inputs to numbers, we have to provide frame states |
// for lazy bailouts in the ToNumber conversions. |
@@ -107,6 +125,52 @@ class JSBinopReduction final { |
return lowering_->Changed(node_); |
} |
+ Reduction ChangeToSpeculativeOperator(const Operator* op) { |
+ DCHECK_EQ(1, op->EffectInputCount()); |
+ DCHECK_EQ(1, op->EffectOutputCount()); |
+ DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); |
+ DCHECK_EQ(1, op->ControlInputCount()); |
+ DCHECK_EQ(1, op->ControlOutputCount()); |
+ DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(op)); |
+ DCHECK_EQ(2, op->ValueInputCount()); |
+ |
+ DCHECK_EQ(1, node_->op()->EffectInputCount()); |
+ DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
+ DCHECK_EQ(1, node_->op()->ControlInputCount()); |
+ DCHECK_LT(1, node_->op()->ControlOutputCount()); |
+ DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node_->op())); |
+ DCHECK_EQ(2, node_->op()->ValueInputCount()); |
+ |
+ // Reconnect the control output to bypass the IfSuccess node and |
+ // possibly disconnect from the IfException node. |
+ for (Edge edge : node_->use_edges()) { |
+ Node* const user = edge.from(); |
+ DCHECK(!user->IsDead()); |
+ if (NodeProperties::IsControlEdge(edge)) { |
+ if (user->opcode() == IrOpcode::kIfSuccess) { |
+ user->ReplaceUses(node_); |
+ user->Kill(); |
+ } else { |
+ DCHECK_EQ(user->opcode(), IrOpcode::kIfException); |
+ edge.UpdateTo(jsgraph()->Dead()); |
+ } |
+ } |
+ } |
+ |
+ // Remove the lazy bailout frame state and the context. |
+ node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_)); |
+ node_->RemoveInput(NodeProperties::FirstContextIndex(node_)); |
+ |
+ NodeProperties::ChangeOp(node_, op); |
+ |
+ // Update the type to number. |
+ Type* node_type = NodeProperties::GetType(node_); |
+ NodeProperties::SetType(node_, |
+ Type::Intersect(node_type, Type::Number(), zone())); |
+ |
+ return lowering_->Changed(node_); |
+ } |
+ |
Reduction ChangeToPureOperator(const Operator* op, Type* type) { |
return ChangeToPureOperator(op, false, type); |
} |
@@ -340,9 +404,18 @@ Reduction JSTypedLowering::ReduceJSAdd(Node* node) { |
if (flags() & kDisableBinaryOpReduction) return NoChange(); |
JSBinopReduction r(this, node); |
+ |
+ BinaryOperationHints::Hint feedback = r.GetUsableNumberFeedback(); |
+ if (feedback != BinaryOperationHints::kAny) { |
+ // Lower to the optimistic number binop. |
+ return r.ChangeToSpeculativeOperator( |
+ simplified()->SpeculativeNumberAdd(feedback)); |
+ } |
if (r.BothInputsAre(Type::NumberOrUndefined())) { |
// JSAdd(x:number, y:number) => NumberAdd(x, y) |
- return ReduceNumberBinop(node, simplified()->NumberAdd()); |
+ Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
+ r.ConvertInputsToNumberOrUndefined(frame_state); |
+ return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
} |
if (r.NeitherInputCanBe(Type::StringOrReceiver())) { |
// JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) |
@@ -387,21 +460,34 @@ Reduction JSTypedLowering::ReduceJSModulus(Node* node) { |
return NoChange(); |
} |
+Reduction JSTypedLowering::ReduceJSSubtract(Node* node) { |
+ if (flags() & kDisableBinaryOpReduction) return NoChange(); |
+ JSBinopReduction r(this, node); |
+ BinaryOperationHints::Hint feedback = r.GetUsableNumberFeedback(); |
+ if (feedback != BinaryOperationHints::kAny) { |
+ // Lower to the optimistic number binop. |
+ return r.ChangeToSpeculativeOperator( |
+ simplified()->SpeculativeNumberSubtract(feedback)); |
+ } |
+ Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
+ r.ConvertInputsToNumberOrUndefined(frame_state); |
+ return r.ChangeToPureOperator(simplified()->NumberSubtract(), Type::Number()); |
+} |
-Reduction JSTypedLowering::ReduceNumberBinop(Node* node, |
- const Operator* numberOp) { |
+Reduction JSTypedLowering::ReduceJSMultiply(Node* node) { |
if (flags() & kDisableBinaryOpReduction) return NoChange(); |
+ JSBinopReduction r(this, node); |
+ Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
+ r.ConvertInputsToNumberOrUndefined(frame_state); |
+ return r.ChangeToPureOperator(simplified()->NumberMultiply(), Type::Number()); |
+} |
+Reduction JSTypedLowering::ReduceJSDivide(Node* node) { |
+ if (flags() & kDisableBinaryOpReduction) return NoChange(); |
JSBinopReduction r(this, node); |
- if (numberOp == simplified()->NumberModulus()) { |
- if (r.BothInputsAre(Type::NumberOrUndefined())) { |
- return r.ChangeToPureOperator(numberOp, Type::Number()); |
- } |
- return NoChange(); |
- } |
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
r.ConvertInputsToNumberOrUndefined(frame_state); |
- return r.ChangeToPureOperator(numberOp, Type::Number()); |
+ return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number()); |
} |
@@ -1785,11 +1871,11 @@ Reduction JSTypedLowering::Reduce(Node* node) { |
case IrOpcode::kJSAdd: |
return ReduceJSAdd(node); |
case IrOpcode::kJSSubtract: |
- return ReduceNumberBinop(node, simplified()->NumberSubtract()); |
+ return ReduceJSSubtract(node); |
case IrOpcode::kJSMultiply: |
- return ReduceNumberBinop(node, simplified()->NumberMultiply()); |
+ return ReduceJSMultiply(node); |
case IrOpcode::kJSDivide: |
- return ReduceNumberBinop(node, simplified()->NumberDivide()); |
+ return ReduceJSDivide(node); |
case IrOpcode::kJSModulus: |
return ReduceJSModulus(node); |
case IrOpcode::kJSToBoolean: |