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(); |
} |