Index: runtime/vm/intermediate_language_dbc.cc |
diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc |
index ea9c9d8018624e0de891a80c48c28b431b037863..486322d269171804cbf0b9288f2a34e218c6530c 100644 |
--- a/runtime/vm/intermediate_language_dbc.cc |
+++ b/runtime/vm/intermediate_language_dbc.cc |
@@ -483,6 +483,14 @@ static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
} |
+Condition StrictCompareInstr::GetNextInstructionCondition( |
+ FlowGraphCompiler* compiler, |
+ BranchLabels labels) { |
+ return (labels.fall_through == labels.false_label) ? NEXT_IS_TRUE |
+ : NEXT_IS_FALSE; |
+} |
+ |
+ |
Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
BranchLabels labels) { |
ASSERT((kind() == Token::kNE_STRICT) || (kind() == Token::kEQ_STRICT)); |
@@ -526,43 +534,50 @@ Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
} |
-void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
- BranchInstr* branch) { |
- ASSERT((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)); |
+DEFINE_MAKE_LOCATION_SUMMARY(StrictCompare, |
+ 2, |
+ Location::RequiresRegister(), |
+ needs_number_check() ? LocationSummary::kCall |
+ : LocationSummary::kNoCall) |
+ |
+void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
+ BranchInstr* branch) { |
BranchLabels labels = compiler->CreateBranchLabels(branch); |
Condition true_condition = EmitComparisonCode(compiler, labels); |
- EmitBranchOnCondition(compiler, true_condition, labels); |
+ if (true_condition != INVALID_CONDITION) { |
+ EmitBranchOnCondition(compiler, true_condition, labels); |
+ } |
} |
-EMIT_NATIVE_CODE(StrictCompare, |
- 2, |
- Location::RequiresRegister(), |
- needs_number_check() ? LocationSummary::kCall |
- : LocationSummary::kNoCall) { |
- ASSERT((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)); |
- |
+void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
Label is_true, is_false; |
BranchLabels labels = {&is_true, &is_false, &is_false}; |
- Condition true_condition = EmitComparisonCode(compiler, labels); |
- EmitBranchOnCondition(compiler, true_condition, labels); |
- Label done; |
- if (compiler->is_optimizing()) { |
- const Register result = locs()->out(0).reg(); |
- __ Bind(&is_false); |
- __ LoadConstant(result, Bool::False()); |
- __ Jump(&done); |
- __ Bind(&is_true); |
- __ LoadConstant(result, Bool::True()); |
- __ Bind(&done); |
- } else { |
+ Condition true_condition = |
+ this->GetNextInstructionCondition(compiler, labels); |
+ if (true_condition == INVALID_CONDITION || !compiler->is_optimizing() || |
+ is_true.IsLinked() || is_false.IsLinked()) { |
+ Condition actual_condition = EmitComparisonCode(compiler, labels); |
+ ASSERT(actual_condition == true_condition); |
+ if (true_condition != INVALID_CONDITION) { |
+ EmitBranchOnCondition(compiler, true_condition, labels); |
+ } |
+ Label done; |
__ Bind(&is_false); |
__ PushConstant(Bool::False()); |
__ Jump(&done); |
__ Bind(&is_true); |
__ PushConstant(Bool::True()); |
__ Bind(&done); |
+ } else { |
+ const Register result = this->locs()->out(0).reg(); |
+ __ LoadConstant( |
+ result, true_condition == NEXT_IS_TRUE ? Bool::False() : Bool::True()); |
+ Condition actual_condition = EmitComparisonCode(compiler, labels); |
+ ASSERT(actual_condition == true_condition); |
+ __ LoadConstant( |
+ result, true_condition == NEXT_IS_TRUE ? Bool::True() : Bool::False()); |
} |
} |
@@ -601,6 +616,13 @@ EMIT_NATIVE_CODE(Goto, 0) { |
} |
+Condition TestSmiInstr::GetNextInstructionCondition(FlowGraphCompiler* compiler, |
+ BranchLabels labels) { |
+ ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
+ return (kind() == Token::kEQ) ? NEXT_IS_TRUE : NEXT_IS_FALSE; |
+} |
+ |
+ |
Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
BranchLabels labels) { |
ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
@@ -611,21 +633,10 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
} |
-void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
- BranchInstr* branch) { |
- BranchLabels labels = compiler->CreateBranchLabels(branch); |
- Condition true_condition = EmitComparisonCode(compiler, labels); |
- EmitBranchOnCondition(compiler, true_condition, labels); |
-} |
- |
- |
-EMIT_NATIVE_CODE(TestSmi, |
- 2, |
- Location::RequiresRegister(), |
- LocationSummary::kNoCall) { |
- // Never emitted outside of the BranchInstr. |
- UNREACHABLE(); |
-} |
+DEFINE_MAKE_LOCATION_SUMMARY(TestSmi, |
+ 2, |
+ Location::RequiresRegister(), |
+ LocationSummary::kNoCall) |
Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
@@ -662,30 +673,17 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
} |
-void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
- BranchInstr* branch) { |
- BranchLabels labels = compiler->CreateBranchLabels(branch); |
- Condition true_condition = EmitComparisonCode(compiler, labels); |
- EmitBranchOnCondition(compiler, true_condition, labels); |
+Condition TestCidsInstr::GetNextInstructionCondition( |
+ FlowGraphCompiler* compiler, |
+ BranchLabels labels) { |
+ return NEXT_IS_TRUE; |
} |
-EMIT_NATIVE_CODE(TestCids, |
- 1, |
- Location::RequiresRegister(), |
- LocationSummary::kNoCall) { |
- Register result_reg = locs()->out(0).reg(); |
- Label is_true, is_false, done; |
- BranchLabels labels = {&is_true, &is_false, &is_false}; |
- EmitComparisonCode(compiler, labels); |
- __ Jump(&is_true); |
- __ Bind(&is_false); |
- __ LoadConstant(result_reg, Bool::False()); |
- __ Jump(&done); |
- __ Bind(&is_true); |
- __ LoadConstant(result_reg, Bool::True()); |
- __ Bind(&done); |
-} |
+DEFINE_MAKE_LOCATION_SUMMARY(TestCids, |
+ 1, |
+ Location::RequiresRegister(), |
+ LocationSummary::kNoCall) |
EMIT_NATIVE_CODE(CreateArray, |
@@ -1753,15 +1751,7 @@ EMIT_NATIVE_CODE(BinaryDoubleOp, 2, Location::RequiresRegister()) { |
Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
BranchLabels labels) { |
- UNREACHABLE(); |
- return Condition(); |
-} |
- |
- |
-void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
- BranchInstr* branch) { |
ASSERT(compiler->is_optimizing()); |
- BranchLabels labels = compiler->CreateBranchLabels(branch); |
const Register value = locs()->in(0).reg(); |
switch (op_kind()) { |
case MethodRecognizer::kDouble_getIsNaN: |
@@ -1774,31 +1764,21 @@ void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
UNREACHABLE(); |
} |
const bool is_negated = kind() != Token::kEQ; |
- EmitBranchOnCondition(compiler, is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE, |
- labels); |
+ return is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE; |
} |
-EMIT_NATIVE_CODE(DoubleTestOp, 1, Location::RequiresRegister()) { |
- ASSERT(compiler->is_optimizing()); |
- const Register value = locs()->in(0).reg(); |
- const Register result = locs()->out(0).reg(); |
+Condition DoubleTestOpInstr::GetNextInstructionCondition( |
+ FlowGraphCompiler* compiler, |
+ BranchLabels labels) { |
const bool is_negated = kind() != Token::kEQ; |
- __ LoadConstant(result, is_negated ? Bool::True() : Bool::False()); |
- switch (op_kind()) { |
- case MethodRecognizer::kDouble_getIsNaN: |
- __ DoubleIsNaN(value); |
- break; |
- case MethodRecognizer::kDouble_getIsInfinite: |
- __ DoubleIsInfinite(value); |
- break; |
- default: |
- UNREACHABLE(); |
- } |
- __ LoadConstant(result, is_negated ? Bool::False() : Bool::True()); |
+ return is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE; |
} |
+DEFINE_MAKE_LOCATION_SUMMARY(DoubleTestOp, 1, Location::RequiresRegister()) |
+ |
+ |
EMIT_NATIVE_CODE(UnaryDoubleOp, 1, Location::RequiresRegister()) { |
const Register value = locs()->in(0).reg(); |
const Register result = locs()->out(0).reg(); |
@@ -1973,7 +1953,8 @@ static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
// If we aren't falling through to the false label, we can save a Jump |
// instruction in the case that the true case is the fall through by |
// flipping the sense of the test such that the instruction following the |
- // test is the Jump to the false label. |
+ // test is the Jump to the false label. In the case where both labels are |
+ // null we don't flip the sense of the test. |
condition = NEXT_IS_FALSE; |
comparison = FlipCondition(kind); |
} |
@@ -2010,29 +1991,20 @@ Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
} |
-EMIT_NATIVE_CODE(EqualityCompare, 2, Location::RequiresRegister()) { |
- ASSERT(compiler->is_optimizing()); |
- ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
- Label is_true, is_false; |
- // These labels are not used. They are arranged so that EmitComparisonCode |
- // emits a test that executes the following instruction when the test |
- // succeeds. |
- BranchLabels labels = {&is_true, &is_false, &is_false}; |
- const Register result = locs()->out(0).reg(); |
- __ LoadConstant(result, Bool::False()); |
- Condition true_condition = EmitComparisonCode(compiler, labels); |
- ASSERT(true_condition == NEXT_IS_TRUE); |
- __ LoadConstant(result, Bool::True()); |
+Condition EqualityCompareInstr::GetNextInstructionCondition( |
+ FlowGraphCompiler* compiler, |
+ BranchLabels labels) { |
+ if (operation_cid() == kSmiCid) { |
+ return (labels.fall_through != labels.false_label) ? NEXT_IS_FALSE |
+ : NEXT_IS_TRUE; |
+ } else { |
+ ASSERT(operation_cid() == kDoubleCid); |
+ return NEXT_IS_TRUE; |
+ } |
} |
-void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
- BranchInstr* branch) { |
- ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
- BranchLabels labels = compiler->CreateBranchLabels(branch); |
- Condition true_condition = EmitComparisonCode(compiler, labels); |
- EmitBranchOnCondition(compiler, true_condition, labels); |
-} |
+DEFINE_MAKE_LOCATION_SUMMARY(EqualityCompare, 2, Location::RequiresRegister()); |
Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
@@ -2046,24 +2018,20 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
} |
-EMIT_NATIVE_CODE(RelationalOp, 2, Location::RequiresRegister()) { |
- ASSERT(compiler->is_optimizing()); |
- Label is_true, is_false; |
- BranchLabels labels = {&is_true, &is_false, &is_false}; |
- const Register result = locs()->out(0).reg(); |
- __ LoadConstant(result, Bool::False()); |
- Condition true_condition = EmitComparisonCode(compiler, labels); |
- ASSERT(true_condition == NEXT_IS_TRUE); |
- __ LoadConstant(result, Bool::True()); |
+Condition RelationalOpInstr::GetNextInstructionCondition( |
+ FlowGraphCompiler* compiler, |
+ BranchLabels labels) { |
+ if (operation_cid() == kSmiCid) { |
+ return (labels.fall_through != labels.false_label) ? NEXT_IS_FALSE |
+ : NEXT_IS_TRUE; |
+ } else { |
+ ASSERT(operation_cid() == kDoubleCid); |
+ return NEXT_IS_TRUE; |
+ } |
} |
-void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
- BranchInstr* branch) { |
- BranchLabels labels = compiler->CreateBranchLabels(branch); |
- Condition true_condition = EmitComparisonCode(compiler, labels); |
- EmitBranchOnCondition(compiler, true_condition, labels); |
-} |
+DEFINE_MAKE_LOCATION_SUMMARY(RelationalOp, 2, Location::RequiresRegister()) |
EMIT_NATIVE_CODE(CheckArrayBound, 2) { |