Index: src/compiler/js-typed-lowering.cc |
diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc |
index 1227e4f08cb6dd60654ac8dc2976ce8ceb25fb28..dc86dc3ad33586979794a54736483912a1ce557f 100644 |
--- a/src/compiler/js-typed-lowering.cc |
+++ b/src/compiler/js-typed-lowering.cc |
@@ -2,11 +2,12 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include "src/compiler/js-typed-lowering.h" |
+ |
#include "src/code-factory.h" |
#include "src/compilation-dependencies.h" |
#include "src/compiler/access-builder.h" |
#include "src/compiler/js-graph.h" |
-#include "src/compiler/js-typed-lowering.h" |
#include "src/compiler/linkage.h" |
#include "src/compiler/node-matchers.h" |
#include "src/compiler/node-properties.h" |
@@ -27,35 +28,55 @@ 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_EQ(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::kSignedSmall: |
+ *hint = NumberOperationHint::kSignedSmall; |
+ return true; |
+ case BinaryOperationHints::kSigned32: |
+ *hint = NumberOperationHint::kSigned32; |
+ return true; |
+ case BinaryOperationHints::kNumberOrOddball: |
+ *hint = NumberOperationHint::kNumberOrOddball; |
+ return true; |
+ case BinaryOperationHints::kAny: |
+ case BinaryOperationHints::kNone: |
+ case BinaryOperationHints::kString: |
+ break; |
} |
} |
- 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; |
+ switch (hints.combined()) { |
+ case CompareOperationHints::kSignedSmall: |
+ *hint = NumberOperationHint::kSignedSmall; |
+ return true; |
+ case CompareOperationHints::kNumberOrOddball: |
+ *hint = NumberOperationHint::kNumberOrOddball; |
+ return true; |
+ case CompareOperationHints::kAny: |
+ case CompareOperationHints::kNone: |
+ case CompareOperationHints::kString: |
+ case CompareOperationHints::kBoolean: |
+ case CompareOperationHints::kUniqueName: |
+ case CompareOperationHints::kInternalizedString: |
+ case CompareOperationHints::kReceiver: |
+ break; |
} |
} |
- return CompareOperationHints::kAny; |
+ return false; |
} |
void ConvertInputsToNumber() { |
@@ -354,18 +375,17 @@ 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. |
+ 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()); |
+ } |
return r.ChangeToSpeculativeOperator( |
- simplified()->SpeculativeNumberAdd(feedback), Type::Number()); |
+ simplified()->SpeculativeNumberAdd(hint), Type::Number()); |
} |
if (r.BothInputsAre(Type::Number())) { |
// JSAdd(x:number, y:number) => NumberAdd(x, y) |
@@ -402,75 +422,69 @@ Reduction JSTypedLowering::ReduceJSAdd(Node* node) { |
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) { |
- // Lower to the optimistic number binop. |
+ 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()); |
+ } |
return r.ChangeToSpeculativeOperator( |
- simplified()->SpeculativeNumberSubtract(feedback), Type::Number()); |
+ simplified()->SpeculativeNumberSubtract(hint), Type::Number()); |
} |
- |
- // If deoptimization is enabled we rely on type feedback. |
if (r.BothInputsAre(Type::PlainPrimitive()) || |
!(flags() & kDeoptimizationEnabled)) { |
r.ConvertInputsToNumber(); |
return r.ChangeToPureOperator(simplified()->NumberSubtract(), |
Type::Number()); |
} |
- |
return NoChange(); |
} |
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), Type::Number()); |
} |
- |
- // If deoptimization is enabled we rely on type feedback. |
if (r.BothInputsAre(Type::PlainPrimitive()) || |
!(flags() & kDeoptimizationEnabled)) { |
r.ConvertInputsToNumber(); |
return r.ChangeToPureOperator(simplified()->NumberMultiply(), |
Type::Number()); |
} |
- |
return NoChange(); |
} |
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), Type::Number()); |
} |
if (r.BothInputsAre(Type::PlainPrimitive())) { |
// JSDivide(x:plain-primitive, |
@@ -483,18 +497,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), Type::Number()); |
} |
if (r.BothInputsAre(Type::PlainPrimitive())) { |
// JSModulus(x:plain-primitive, |
@@ -509,21 +523,19 @@ Reduction JSTypedLowering::ReduceJSModulus(Node* node) { |
Reduction JSTypedLowering::ReduceInt32Binop(Node* node, |
const Operator* int_op) { |
JSBinopReduction r(this, node); |
- BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); |
- if (feedback != BinaryOperationHints::kAny) { |
+ NumberOperationHint hint; |
+ if (r.GetBinaryNumberOperationHint(&hint)) { |
Operator const* speculative_op; |
if (int_op->opcode() == IrOpcode::kNumberBitwiseAnd) { |
- speculative_op = simplified()->SpeculativeNumberBitwiseAnd(feedback); |
+ speculative_op = simplified()->SpeculativeNumberBitwiseAnd(hint); |
} else if (int_op->opcode() == IrOpcode::kNumberBitwiseOr) { |
- speculative_op = simplified()->SpeculativeNumberBitwiseOr(feedback); |
+ speculative_op = simplified()->SpeculativeNumberBitwiseOr(hint); |
} else { |
DCHECK_EQ(IrOpcode::kNumberBitwiseXor, int_op->opcode()); |
- speculative_op = simplified()->SpeculativeNumberBitwiseXor(feedback); |
+ speculative_op = simplified()->SpeculativeNumberBitwiseXor(hint); |
} |
return r.ChangeToSpeculativeOperator(speculative_op, Type::Signed32()); |
} |
- |
- // If deoptimization is enabled we rely on type feedback. |
if (r.BothInputsAre(Type::PlainPrimitive()) || |
!(flags() & kDeoptimizationEnabled)) { |
r.ConvertInputsToNumber(); |
@@ -533,33 +545,28 @@ Reduction JSTypedLowering::ReduceInt32Binop(Node* node, |
return NoChange(); |
} |
-Reduction JSTypedLowering::ReduceUI32Shift(Node* node, |
- Signedness left_signedness, |
+Reduction JSTypedLowering::ReduceUI32Shift(Node* node, Signedness signedness, |
const Operator* shift_op) { |
JSBinopReduction r(this, node); |
- BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); |
- if (feedback != BinaryOperationHints::kAny) { |
+ NumberOperationHint hint; |
+ if (r.GetBinaryNumberOperationHint(&hint)) { |
Operator const* speculative_op; |
if (shift_op->opcode() == IrOpcode::kNumberShiftLeft) { |
- speculative_op = simplified()->SpeculativeNumberShiftLeft(feedback); |
+ speculative_op = simplified()->SpeculativeNumberShiftLeft(hint); |
} else if (shift_op->opcode() == IrOpcode::kNumberShiftRightLogical) { |
- speculative_op = |
- simplified()->SpeculativeNumberShiftRightLogical(feedback); |
+ speculative_op = simplified()->SpeculativeNumberShiftRightLogical(hint); |
} else { |
DCHECK_EQ(IrOpcode::kNumberShiftRight, shift_op->opcode()); |
- speculative_op = simplified()->SpeculativeNumberShiftRight(feedback); |
+ speculative_op = simplified()->SpeculativeNumberShiftRight(hint); |
} |
return r.ChangeToSpeculativeOperator( |
- speculative_op, shift_op->opcode() == IrOpcode::kNumberShiftRightLogical |
- ? Type::Unsigned32() |
- : Type::Signed32()); |
+ speculative_op, |
+ signedness == kUnsigned ? Type::Unsigned32() : Type::Signed32()); |
} |
- |
- // If deoptimization is enabled we rely on type feedback. |
if (r.BothInputsAre(Type::PlainPrimitive()) || |
!(flags() & kDeoptimizationEnabled)) { |
r.ConvertInputsToNumber(); |
- r.ConvertInputsToUI32(left_signedness, kUnsigned); |
+ r.ConvertInputsToUI32(signedness, kUnsigned); |
return r.ChangeToPureOperator(shift_op); |
} |
return NoChange(); |
@@ -592,53 +599,49 @@ 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 (r.BothInputsAre(Type::Signed32()) || |
- r.BothInputsAre(Type::Unsigned32())) { |
- less_than = simplified()->NumberLessThan(); |
- less_than_or_equal = simplified()->NumberLessThanOrEqual(); |
- } else 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.BothInputsAre(Type::Signed32()) || |
+ r.BothInputsAre(Type::Unsigned32())) { |
+ less_than = simplified()->NumberLessThan(); |
+ less_than_or_equal = simplified()->NumberLessThanOrEqual(); |
+ } else if (r.GetCompareNumberOperationHint(&hint)) { |
+ less_than = simplified()->SpeculativeNumberLessThan(hint); |
+ less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint); |
+ } else if (r.OneInputCannotBe(Type::StringOrReceiver()) && |
+ (r.BothInputsAre(Type::PlainPrimitive()) || |
+ !(flags() & kDeoptimizationEnabled))) { |
+ 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, Type::Boolean()); |
+ } else { |
+ return r.ChangeToPureOperator(comparison); |
+ } |
} |
Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) { |