Index: src/interpreter/interpreter.cc |
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc |
index 363a9a1ed2e952f58038d5637cdc36d746a91a7c..3f5b0e34394c874e8ff8bda44181a1b70e1867c5 100644 |
--- a/src/interpreter/interpreter.cc |
+++ b/src/interpreter/interpreter.cc |
@@ -816,6 +816,80 @@ void Interpreter::DoBinaryOpWithFeedback(InterpreterAssembler* assembler) { |
__ Dispatch(); |
} |
+template <class Generator> |
+void Interpreter::DoCompareOpWithFeedback(InterpreterAssembler* assembler) { |
+ Node* reg_index = __ BytecodeOperandReg(0); |
+ Node* lhs = __ LoadRegister(reg_index); |
+ Node* rhs = __ GetAccumulator(); |
+ Node* context = __ GetContext(); |
+ Node* slot_index = __ BytecodeOperandIdx(1); |
+ Node* type_feedback_vector = __ LoadTypeFeedbackVector(); |
+ |
+ // TODO(interpreter): the only reason this check is here is because we |
+ // sometimes emit comparisons that shouldn't collect feedback (e.g. |
+ // try-finally blocks and generators), and we could get rid of this by |
+ // introducing Smi equality tests. |
+ Label skip_feedback_update(assembler); |
+ __ GotoIf(__ WordEqual(slot_index, __ IntPtrConstant(0)), |
+ &skip_feedback_update); |
+ |
+ Variable var_type_feedback(assembler, MachineRepresentation::kWord32); |
+ Label lhs_is_smi(assembler), lhs_is_not_smi(assembler), |
+ gather_rhs_type(assembler), do_compare(assembler); |
+ __ Branch(__ WordIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi); |
+ |
+ __ Bind(&lhs_is_smi); |
+ var_type_feedback.Bind( |
+ __ Int32Constant(CompareOperationFeedback::kSignedSmall)); |
+ __ Goto(&gather_rhs_type); |
+ |
+ __ Bind(&lhs_is_not_smi); |
+ { |
+ Label lhs_is_number(assembler), lhs_is_not_number(assembler); |
+ Node* lhs_map = __ LoadMap(lhs); |
+ __ Branch(__ WordEqual(lhs_map, __ HeapNumberMapConstant()), &lhs_is_number, |
+ &lhs_is_not_number); |
+ |
+ __ Bind(&lhs_is_number); |
+ var_type_feedback.Bind(__ Int32Constant(CompareOperationFeedback::kNumber)); |
+ __ Goto(&gather_rhs_type); |
+ |
+ __ Bind(&lhs_is_not_number); |
+ var_type_feedback.Bind(__ Int32Constant(CompareOperationFeedback::kAny)); |
+ __ Goto(&do_compare); |
+ } |
+ |
+ __ Bind(&gather_rhs_type); |
+ { |
+ Label rhs_is_smi(assembler); |
+ __ GotoIf(__ WordIsSmi(rhs), &rhs_is_smi); |
+ |
+ Node* rhs_map = __ LoadMap(rhs); |
+ Node* rhs_type = |
+ __ Select(__ WordEqual(rhs_map, __ HeapNumberMapConstant()), |
+ __ Int32Constant(CompareOperationFeedback::kNumber), |
+ __ Int32Constant(CompareOperationFeedback::kAny)); |
+ var_type_feedback.Bind(__ Word32Or(var_type_feedback.value(), rhs_type)); |
+ __ Goto(&do_compare); |
+ |
+ __ Bind(&rhs_is_smi); |
+ var_type_feedback.Bind( |
+ __ Word32Or(var_type_feedback.value(), |
+ __ Int32Constant(CompareOperationFeedback::kSignedSmall))); |
+ __ Goto(&do_compare); |
+ } |
+ |
+ __ Bind(&do_compare); |
+ __ UpdateFeedback(var_type_feedback.value(), type_feedback_vector, |
+ slot_index); |
+ __ Goto(&skip_feedback_update); |
+ |
+ __ Bind(&skip_feedback_update); |
+ Node* result = Generator::Generate(assembler, lhs, rhs, context); |
+ __ SetAccumulator(result); |
+ __ Dispatch(); |
+} |
+ |
// Add <src> |
// |
// Add register <src> to accumulator. |
@@ -1520,35 +1594,35 @@ void Interpreter::DoNew(InterpreterAssembler* assembler) { |
// |
// Test if the value in the <src> register equals the accumulator. |
void Interpreter::DoTestEqual(InterpreterAssembler* assembler) { |
- DoBinaryOp<EqualStub>(assembler); |
+ DoCompareOpWithFeedback<EqualStub>(assembler); |
} |
// TestNotEqual <src> |
// |
// Test if the value in the <src> register is not equal to the accumulator. |
void Interpreter::DoTestNotEqual(InterpreterAssembler* assembler) { |
- DoBinaryOp<NotEqualStub>(assembler); |
+ DoCompareOpWithFeedback<NotEqualStub>(assembler); |
} |
// TestEqualStrict <src> |
// |
// Test if the value in the <src> register is strictly equal to the accumulator. |
void Interpreter::DoTestEqualStrict(InterpreterAssembler* assembler) { |
- DoBinaryOp<StrictEqualStub>(assembler); |
+ DoCompareOpWithFeedback<StrictEqualStub>(assembler); |
} |
// TestLessThan <src> |
// |
// Test if the value in the <src> register is less than the accumulator. |
void Interpreter::DoTestLessThan(InterpreterAssembler* assembler) { |
- DoBinaryOp<LessThanStub>(assembler); |
+ DoCompareOpWithFeedback<LessThanStub>(assembler); |
} |
// TestGreaterThan <src> |
// |
// Test if the value in the <src> register is greater than the accumulator. |
void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) { |
- DoBinaryOp<GreaterThanStub>(assembler); |
+ DoCompareOpWithFeedback<GreaterThanStub>(assembler); |
} |
// TestLessThanOrEqual <src> |
@@ -1556,7 +1630,7 @@ void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) { |
// Test if the value in the <src> register is less than or equal to the |
// accumulator. |
void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) { |
- DoBinaryOp<LessThanOrEqualStub>(assembler); |
+ DoCompareOpWithFeedback<LessThanOrEqualStub>(assembler); |
} |
// TestGreaterThanOrEqual <src> |
@@ -1564,7 +1638,7 @@ void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) { |
// Test if the value in the <src> register is greater than or equal to the |
// accumulator. |
void Interpreter::DoTestGreaterThanOrEqual(InterpreterAssembler* assembler) { |
- DoBinaryOp<GreaterThanOrEqualStub>(assembler); |
+ DoCompareOpWithFeedback<GreaterThanOrEqualStub>(assembler); |
} |
// TestIn <src> |