| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 | 129 |
| 130 | 130 |
| 131 // Detect pattern when one value is zero and another is a power of 2. | 131 // Detect pattern when one value is zero and another is a power of 2. |
| 132 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 132 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| 133 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 133 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| 134 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 134 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
| 135 } | 135 } |
| 136 | 136 |
| 137 | 137 |
| 138 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { | 138 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { |
| 139 const intptr_t kNumInputs = 2; | 139 return comparison()->MakeLocationSummary(); |
| 140 const intptr_t kNumTemps = 0; | |
| 141 LocationSummary* locs = | |
| 142 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 143 locs->set_in(0, Location::RegisterOrConstant(left())); | |
| 144 // Only one of the inputs can be a constant. Choose register if the first one | |
| 145 // is a constant. | |
| 146 locs->set_in(1, locs->in(0).IsConstant() | |
| 147 ? Location::RequiresRegister() | |
| 148 : Location::RegisterOrConstant(right())); | |
| 149 locs->set_out(Location::RequiresRegister()); | |
| 150 return locs; | |
| 151 } | 140 } |
| 152 | 141 |
| 153 | 142 |
| 154 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 143 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 155 const Register result = locs()->out().reg(); | 144 const Register result = locs()->out().reg(); |
| 156 ASSERT(Token::IsEqualityOperator(kind())); | |
| 157 | 145 |
| 158 Location left = locs()->in(0); | 146 Location left = locs()->in(0); |
| 159 Location right = locs()->in(1); | 147 Location right = locs()->in(1); |
| 160 ASSERT(!left.IsConstant() || !right.IsConstant()); | 148 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 161 | 149 |
| 162 // Clear out register. | 150 // Clear out register. |
| 163 __ eor(result, result, ShifterOperand(result)); | 151 __ eor(result, result, ShifterOperand(result)); |
| 164 | 152 |
| 165 // Compare left and right. For now only equality comparison is supported. | 153 // Emit comparison code. This must not overwrite the result register. |
| 166 // TODO(vegorov): reuse code from the other comparison instructions instead of | 154 BranchLabels labels = { NULL, NULL, NULL }; |
| 167 // generating it inline here. | 155 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
| 168 if (left.IsConstant()) { | |
| 169 __ CompareObject(right.reg(), left.constant()); | |
| 170 } else if (right.IsConstant()) { | |
| 171 __ CompareObject(left.reg(), right.constant()); | |
| 172 } else { | |
| 173 __ cmp(left.reg(), ShifterOperand(right.reg())); | |
| 174 } | |
| 175 | |
| 176 Condition true_condition = | |
| 177 ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQ : NE; | |
| 178 | 156 |
| 179 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 157 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
| 180 | 158 |
| 181 intptr_t true_value = if_true_; | 159 intptr_t true_value = if_true_; |
| 182 intptr_t false_value = if_false_; | 160 intptr_t false_value = if_false_; |
| 183 | 161 |
| 184 if (is_power_of_two_kind) { | 162 if (is_power_of_two_kind) { |
| 185 if (true_value == 0) { | 163 if (true_value == 0) { |
| 186 // We need to have zero in result on true_condition. | 164 // We need to have zero in result on true_condition. |
| 187 true_condition = NegateCondition(true_condition); | 165 true_condition = NegateCondition(true_condition); |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 case Token::kGT: return GT; | 466 case Token::kGT: return GT; |
| 489 case Token::kLTE: return LE; | 467 case Token::kLTE: return LE; |
| 490 case Token::kGTE: return GE; | 468 case Token::kGTE: return GE; |
| 491 default: | 469 default: |
| 492 UNREACHABLE(); | 470 UNREACHABLE(); |
| 493 return VS; | 471 return VS; |
| 494 } | 472 } |
| 495 } | 473 } |
| 496 | 474 |
| 497 | 475 |
| 498 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 476 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 499 LocationSummary* locs) { | 477 LocationSummary* locs, |
| 478 Token::Kind kind) { |
| 500 QRegister left = locs->in(0).fpu_reg(); | 479 QRegister left = locs->in(0).fpu_reg(); |
| 501 QRegister right = locs->in(1).fpu_reg(); | 480 QRegister right = locs->in(1).fpu_reg(); |
| 502 DRegister dleft = EvenDRegisterOf(left); | 481 DRegister dleft = EvenDRegisterOf(left); |
| 503 DRegister dright = EvenDRegisterOf(right); | 482 DRegister dright = EvenDRegisterOf(right); |
| 504 __ vcmpd(dleft, dright); | 483 __ vcmpd(dleft, dright); |
| 505 __ vmstat(); | 484 __ vmstat(); |
| 485 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 486 return true_condition; |
| 487 } |
| 488 |
| 489 |
| 490 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 491 BranchLabels labels) { |
| 492 if (operation_cid() == kSmiCid) { |
| 493 return EmitSmiComparisonOp(compiler, locs(), kind()); |
| 494 } else { |
| 495 ASSERT(operation_cid() == kDoubleCid); |
| 496 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
| 497 } |
| 506 } | 498 } |
| 507 | 499 |
| 508 | 500 |
| 509 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 501 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 510 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 502 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 511 | 503 |
| 504 // The ARM code does not use true- and false-labels here. |
| 505 BranchLabels labels = { NULL, NULL, NULL }; |
| 506 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 507 |
| 508 Register result = locs()->out().reg(); |
| 512 if (operation_cid() == kSmiCid) { | 509 if (operation_cid() == kSmiCid) { |
| 513 Condition true_condition = EmitSmiComparisonOp(compiler, locs(), kind()); | |
| 514 Register result = locs()->out().reg(); | |
| 515 __ LoadObject(result, Bool::True(), true_condition); | 510 __ LoadObject(result, Bool::True(), true_condition); |
| 516 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 511 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
| 517 } else { | 512 } else { |
| 518 ASSERT(operation_cid() == kDoubleCid); | 513 ASSERT(operation_cid() == kDoubleCid); |
| 519 EmitDoubleComparisonOp(compiler, locs()); | |
| 520 | |
| 521 Register result = locs()->out().reg(); | |
| 522 Condition true_condition = TokenKindToDoubleCondition(kind()); | |
| 523 Label done; | 514 Label done; |
| 524 __ LoadObject(result, Bool::False()); | 515 __ LoadObject(result, Bool::False()); |
| 525 if (true_condition != NE) { | 516 if (true_condition != NE) { |
| 526 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. | 517 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. |
| 527 } | 518 } |
| 528 __ LoadObject(result, Bool::True(), true_condition); | 519 __ LoadObject(result, Bool::True(), true_condition); |
| 529 __ Bind(&done); | 520 __ Bind(&done); |
| 530 } | 521 } |
| 531 } | 522 } |
| 532 | 523 |
| 533 | 524 |
| 534 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 525 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 535 BranchInstr* branch) { | 526 BranchInstr* branch) { |
| 536 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 527 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 537 | 528 |
| 538 BranchLabels labels = compiler->CreateBranchLabels(branch); | 529 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 530 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 539 | 531 |
| 540 Condition true_condition = kNoCondition; | 532 if (operation_cid() == kDoubleCid) { |
| 541 if (operation_cid() == kSmiCid) { | |
| 542 true_condition = EmitSmiComparisonOp(compiler, locs(), kind()); | |
| 543 } else { | |
| 544 ASSERT(operation_cid() == kDoubleCid); | |
| 545 true_condition = TokenKindToDoubleCondition(kind()); | |
| 546 EmitDoubleComparisonOp(compiler, locs()); | |
| 547 | |
| 548 Label* nan_result = (true_condition == NE) ? | 533 Label* nan_result = (true_condition == NE) ? |
| 549 labels.true_label : labels.false_label; | 534 labels.true_label : labels.false_label; |
| 550 __ b(nan_result, VS); | 535 __ b(nan_result, VS); |
| 551 } | 536 } |
| 552 EmitBranchOnCondition(compiler, true_condition, labels); | 537 EmitBranchOnCondition(compiler, true_condition, labels); |
| 553 } | 538 } |
| 554 | 539 |
| 555 | 540 |
| 556 LocationSummary* TestSmiInstr::MakeLocationSummary() const { | 541 LocationSummary* TestSmiInstr::MakeLocationSummary() const { |
| 557 const intptr_t kNumInputs = 2; | 542 const intptr_t kNumInputs = 2; |
| 558 const intptr_t kNumTemps = 0; | 543 const intptr_t kNumTemps = 0; |
| 559 LocationSummary* locs = | 544 LocationSummary* locs = |
| 560 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 545 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 561 locs->set_in(0, Location::RequiresRegister()); | 546 locs->set_in(0, Location::RequiresRegister()); |
| 562 // Only one input can be a constant operand. The case of two constant | 547 // Only one input can be a constant operand. The case of two constant |
| 563 // operands should be handled by constant propagation. | 548 // operands should be handled by constant propagation. |
| 564 locs->set_in(1, Location::RegisterOrConstant(right())); | 549 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 565 return locs; | 550 return locs; |
| 566 } | 551 } |
| 567 | 552 |
| 568 | 553 |
| 569 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 554 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 570 // Never emitted outside of the BranchInstr. | 555 BranchLabels labels) { |
| 571 UNREACHABLE(); | |
| 572 } | |
| 573 | |
| 574 | |
| 575 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | |
| 576 BranchInstr* branch) { | |
| 577 BranchLabels labels = compiler->CreateBranchLabels(branch); | |
| 578 | |
| 579 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; | |
| 580 Register left = locs()->in(0).reg(); | 556 Register left = locs()->in(0).reg(); |
| 581 Location right = locs()->in(1); | 557 Location right = locs()->in(1); |
| 582 if (right.IsConstant()) { | 558 if (right.IsConstant()) { |
| 583 ASSERT(right.constant().IsSmi()); | 559 ASSERT(right.constant().IsSmi()); |
| 584 const int32_t imm = | 560 const int32_t imm = |
| 585 reinterpret_cast<int32_t>(right.constant().raw()); | 561 reinterpret_cast<int32_t>(right.constant().raw()); |
| 586 __ TestImmediate(left, imm); | 562 __ TestImmediate(left, imm); |
| 587 } else { | 563 } else { |
| 588 __ tst(left, ShifterOperand(right.reg())); | 564 __ tst(left, ShifterOperand(right.reg())); |
| 589 } | 565 } |
| 566 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; |
| 567 return true_condition; |
| 568 } |
| 569 |
| 570 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 571 // Never emitted outside of the BranchInstr. |
| 572 UNREACHABLE(); |
| 573 } |
| 574 |
| 575 |
| 576 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 577 BranchInstr* branch) { |
| 578 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 579 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 590 EmitBranchOnCondition(compiler, true_condition, labels); | 580 EmitBranchOnCondition(compiler, true_condition, labels); |
| 591 } | 581 } |
| 592 | 582 |
| 593 | 583 |
| 594 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 584 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| 595 const intptr_t kNumInputs = 2; | 585 const intptr_t kNumInputs = 2; |
| 596 const intptr_t kNumTemps = 0; | 586 const intptr_t kNumTemps = 0; |
| 597 if (operation_cid() == kMintCid) { | 587 if (operation_cid() == kMintCid) { |
| 598 const intptr_t kNumTemps = 2; | 588 const intptr_t kNumTemps = 2; |
| 599 LocationSummary* locs = | 589 LocationSummary* locs = |
| (...skipping 20 matching lines...) Expand all Loading... |
| 620 // Only one input can be a constant operand. The case of two constant | 610 // Only one input can be a constant operand. The case of two constant |
| 621 // operands should be handled by constant propagation. | 611 // operands should be handled by constant propagation. |
| 622 summary->set_in(1, summary->in(0).IsConstant() | 612 summary->set_in(1, summary->in(0).IsConstant() |
| 623 ? Location::RequiresRegister() | 613 ? Location::RequiresRegister() |
| 624 : Location::RegisterOrConstant(right())); | 614 : Location::RegisterOrConstant(right())); |
| 625 summary->set_out(Location::RequiresRegister()); | 615 summary->set_out(Location::RequiresRegister()); |
| 626 return summary; | 616 return summary; |
| 627 } | 617 } |
| 628 | 618 |
| 629 | 619 |
| 620 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 621 BranchLabels labels) { |
| 622 if (operation_cid() == kSmiCid) { |
| 623 return EmitSmiComparisonOp(compiler, locs(), kind()); |
| 624 } else { |
| 625 ASSERT(operation_cid() == kDoubleCid); |
| 626 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
| 627 } |
| 628 } |
| 629 |
| 630 |
| 630 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 631 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 632 // The ARM code does not use true- and false-labels here. |
| 633 BranchLabels labels = { NULL, NULL, NULL }; |
| 634 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 635 |
| 636 Register result = locs()->out().reg(); |
| 631 if (operation_cid() == kSmiCid) { | 637 if (operation_cid() == kSmiCid) { |
| 632 Condition true_condition = EmitSmiComparisonOp(compiler, locs(), kind()); | |
| 633 Register result = locs()->out().reg(); | |
| 634 __ LoadObject(result, Bool::True(), true_condition); | 638 __ LoadObject(result, Bool::True(), true_condition); |
| 635 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 639 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
| 636 } else { | 640 } else { |
| 637 ASSERT(operation_cid() == kDoubleCid); | 641 ASSERT(operation_cid() == kDoubleCid); |
| 638 EmitDoubleComparisonOp(compiler, locs()); | |
| 639 | |
| 640 Register result = locs()->out().reg(); | |
| 641 Condition true_condition = TokenKindToDoubleCondition(kind()); | |
| 642 Label done; | 642 Label done; |
| 643 __ LoadObject(result, Bool::False()); | 643 __ LoadObject(result, Bool::False()); |
| 644 if (true_condition != NE) { | 644 if (true_condition != NE) { |
| 645 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. | 645 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. |
| 646 } | 646 } |
| 647 __ LoadObject(result, Bool::True(), true_condition); | 647 __ LoadObject(result, Bool::True(), true_condition); |
| 648 __ Bind(&done); | 648 __ Bind(&done); |
| 649 } | 649 } |
| 650 } | 650 } |
| 651 | 651 |
| 652 | 652 |
| 653 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 653 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 654 BranchInstr* branch) { | 654 BranchInstr* branch) { |
| 655 BranchLabels labels = compiler->CreateBranchLabels(branch); | 655 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 656 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 656 | 657 |
| 657 Condition true_condition = kNoCondition; | 658 if (operation_cid() == kDoubleCid) { |
| 658 if (operation_cid() == kSmiCid) { | |
| 659 true_condition = EmitSmiComparisonOp(compiler, locs(), kind()); | |
| 660 } else { | |
| 661 ASSERT(operation_cid() == kDoubleCid); | |
| 662 true_condition = TokenKindToDoubleCondition(kind()); | |
| 663 EmitDoubleComparisonOp(compiler, locs()); | |
| 664 | |
| 665 Label* nan_result = (true_condition == NE) ? | 659 Label* nan_result = (true_condition == NE) ? |
| 666 labels.true_label : labels.false_label; | 660 labels.true_label : labels.false_label; |
| 667 __ b(nan_result, VS); | 661 __ b(nan_result, VS); |
| 668 } | 662 } |
| 669 EmitBranchOnCondition(compiler, true_condition, labels); | 663 EmitBranchOnCondition(compiler, true_condition, labels); |
| 670 } | 664 } |
| 671 | 665 |
| 672 | 666 |
| 673 LocationSummary* NativeCallInstr::MakeLocationSummary() const { | 667 LocationSummary* NativeCallInstr::MakeLocationSummary() const { |
| 674 const intptr_t kNumInputs = 0; | 668 const intptr_t kNumInputs = 0; |
| (...skipping 3739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4414 // Only one of the inputs can be a constant. Choose register if the first one | 4408 // Only one of the inputs can be a constant. Choose register if the first one |
| 4415 // is a constant. | 4409 // is a constant. |
| 4416 locs->set_in(1, locs->in(0).IsConstant() | 4410 locs->set_in(1, locs->in(0).IsConstant() |
| 4417 ? Location::RequiresRegister() | 4411 ? Location::RequiresRegister() |
| 4418 : Location::RegisterOrConstant(right())); | 4412 : Location::RegisterOrConstant(right())); |
| 4419 locs->set_out(Location::RequiresRegister()); | 4413 locs->set_out(Location::RequiresRegister()); |
| 4420 return locs; | 4414 return locs; |
| 4421 } | 4415 } |
| 4422 | 4416 |
| 4423 | 4417 |
| 4424 static void EmitStrictComparison(FlowGraphCompiler* compiler, | 4418 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 4425 StrictCompareInstr* compare) { | 4419 BranchLabels labels) { |
| 4426 LocationSummary* locs = compare->locs(); | 4420 Location left = locs()->in(0); |
| 4427 bool needs_number_check = compare->needs_number_check(); | 4421 Location right = locs()->in(1); |
| 4428 intptr_t token_pos = compare->token_pos(); | |
| 4429 Location left = locs->in(0); | |
| 4430 Location right = locs->in(1); | |
| 4431 ASSERT(!left.IsConstant() || !right.IsConstant()); | 4422 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 4432 if (left.IsConstant()) { | 4423 if (left.IsConstant()) { |
| 4433 compiler->EmitEqualityRegConstCompare(right.reg(), | 4424 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 4434 left.constant(), | 4425 left.constant(), |
| 4435 needs_number_check, | 4426 needs_number_check(), |
| 4436 token_pos); | 4427 token_pos()); |
| 4437 } else if (right.IsConstant()) { | 4428 } else if (right.IsConstant()) { |
| 4438 compiler->EmitEqualityRegConstCompare(left.reg(), | 4429 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 4439 right.constant(), | 4430 right.constant(), |
| 4440 needs_number_check, | 4431 needs_number_check(), |
| 4441 token_pos); | 4432 token_pos()); |
| 4442 } else { | 4433 } else { |
| 4443 compiler->EmitEqualityRegRegCompare(left.reg(), | 4434 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 4444 right.reg(), | 4435 right.reg(), |
| 4445 needs_number_check, | 4436 needs_number_check(), |
| 4446 token_pos); | 4437 token_pos()); |
| 4447 } | 4438 } |
| 4439 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; |
| 4440 return true_condition; |
| 4448 } | 4441 } |
| 4449 | 4442 |
| 4450 | 4443 |
| 4451 // Special code for numbers (compare values instead of references.) | |
| 4452 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4444 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4453 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4445 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 4454 | 4446 |
| 4455 EmitStrictComparison(compiler, this); | 4447 // The ARM code does not use true- and false-labels here. |
| 4448 BranchLabels labels = { NULL, NULL, NULL }; |
| 4449 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 4456 | 4450 |
| 4457 Register result = locs()->out().reg(); | 4451 Register result = locs()->out().reg(); |
| 4458 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; | |
| 4459 __ LoadObject(result, Bool::True(), true_condition); | 4452 __ LoadObject(result, Bool::True(), true_condition); |
| 4460 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 4453 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
| 4461 } | 4454 } |
| 4462 | 4455 |
| 4463 | 4456 |
| 4464 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 4457 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 4465 BranchInstr* branch) { | 4458 BranchInstr* branch) { |
| 4466 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4459 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 4467 | 4460 |
| 4468 EmitStrictComparison(compiler, this); | |
| 4469 | |
| 4470 BranchLabels labels = compiler->CreateBranchLabels(branch); | 4461 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 4471 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; | 4462 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 4472 EmitBranchOnCondition(compiler, true_condition, labels); | 4463 EmitBranchOnCondition(compiler, true_condition, labels); |
| 4473 } | 4464 } |
| 4474 | 4465 |
| 4475 | 4466 |
| 4476 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { | 4467 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { |
| 4477 return LocationSummary::Make(1, | 4468 return LocationSummary::Make(1, |
| 4478 Location::RequiresRegister(), | 4469 Location::RequiresRegister(), |
| 4479 LocationSummary::kNoCall); | 4470 LocationSummary::kNoCall); |
| 4480 } | 4471 } |
| 4481 | 4472 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4546 compiler->GenerateCall(token_pos(), | 4537 compiler->GenerateCall(token_pos(), |
| 4547 &label, | 4538 &label, |
| 4548 PcDescriptors::kOther, | 4539 PcDescriptors::kOther, |
| 4549 locs()); | 4540 locs()); |
| 4550 __ Drop(2); // Discard type arguments and receiver. | 4541 __ Drop(2); // Discard type arguments and receiver. |
| 4551 } | 4542 } |
| 4552 | 4543 |
| 4553 } // namespace dart | 4544 } // namespace dart |
| 4554 | 4545 |
| 4555 #endif // defined TARGET_ARCH_ARM | 4546 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |