Chromium Code Reviews| 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 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 441 case HI: return CC; | 441 case HI: return CC; |
| 442 case CS: return LS; | 442 case CS: return LS; |
| 443 default: | 443 default: |
| 444 UNREACHABLE(); | 444 UNREACHABLE(); |
| 445 return EQ; | 445 return EQ; |
| 446 } | 446 } |
| 447 } | 447 } |
| 448 | 448 |
| 449 | 449 |
| 450 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 450 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 451 TargetEntryInstr* true_successor, | 451 Condition true_condition, |
| 452 TargetEntryInstr* false_successor, | 452 BranchLabels labels) { |
| 453 Condition true_condition) { | 453 if (labels.fall_through == labels.false_label) { |
| 454 if (compiler->CanFallThroughTo(false_successor)) { | |
| 455 // If the next block is the false successor we will fall through to it. | 454 // If the next block is the false successor we will fall through to it. |
| 456 __ b(compiler->GetJumpLabel(true_successor), true_condition); | 455 __ b(labels.true_label, true_condition); |
| 457 } else { | 456 } else { |
| 458 // If the next block is not the false successor we will branch to it. | 457 // If the next block is not the false successor we will branch to it. |
| 459 Condition false_condition = NegateCondition(true_condition); | 458 Condition false_condition = NegateCondition(true_condition); |
| 460 __ b(compiler->GetJumpLabel(false_successor), false_condition); | 459 __ b(labels.false_label, false_condition); |
| 461 | 460 |
| 462 // Fall through or jump to the true successor. | 461 // Fall through or jump to the true successor. |
| 463 if (!compiler->CanFallThroughTo(true_successor)) { | 462 if (labels.fall_through != labels.true_label) { |
| 464 __ b(compiler->GetJumpLabel(true_successor)); | 463 __ b(labels.true_label); |
| 465 } | 464 } |
| 466 } | 465 } |
| 467 } | 466 } |
| 468 | 467 |
| 469 | 468 |
| 470 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 469 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 471 const LocationSummary& locs, | 470 LocationSummary* locs, |
| 472 Token::Kind kind, | 471 Token::Kind kind) { |
| 473 BranchInstr* branch) { | 472 Location left = locs->in(0); |
| 474 Location left = locs.in(0); | 473 Location right = locs->in(1); |
| 475 Location right = locs.in(1); | |
| 476 ASSERT(!left.IsConstant() || !right.IsConstant()); | 474 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 477 | 475 |
| 478 Condition true_condition = TokenKindToSmiCondition(kind); | 476 Condition true_condition = TokenKindToSmiCondition(kind); |
| 479 | 477 |
| 480 if (left.IsConstant()) { | 478 if (left.IsConstant()) { |
| 481 __ CompareObject(right.reg(), left.constant()); | 479 __ CompareObject(right.reg(), left.constant()); |
| 482 true_condition = FlipCondition(true_condition); | 480 true_condition = FlipCondition(true_condition); |
| 483 } else if (right.IsConstant()) { | 481 } else if (right.IsConstant()) { |
| 484 __ CompareObject(left.reg(), right.constant()); | 482 __ CompareObject(left.reg(), right.constant()); |
| 485 } else { | 483 } else { |
| 486 __ cmp(left.reg(), ShifterOperand(right.reg())); | 484 __ cmp(left.reg(), ShifterOperand(right.reg())); |
| 487 } | 485 } |
| 488 | 486 return true_condition; |
| 489 if (branch != NULL) { | |
| 490 EmitBranchOnCondition(compiler, | |
| 491 branch->true_successor(), | |
| 492 branch->false_successor(), | |
| 493 true_condition); | |
| 494 } else { | |
| 495 Register result = locs.out().reg(); | |
| 496 __ LoadObject(result, Bool::True(), true_condition); | |
| 497 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | |
| 498 } | |
| 499 } | |
| 500 | |
| 501 | |
| 502 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | |
| 503 const LocationSummary& locs, | |
| 504 Token::Kind kind, | |
| 505 BranchInstr* branch) { | |
| 506 UNIMPLEMENTED(); | |
| 507 } | |
| 508 | |
| 509 | |
| 510 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | |
| 511 const LocationSummary& locs, | |
| 512 Token::Kind kind, | |
| 513 BranchInstr* branch) { | |
| 514 UNIMPLEMENTED(); | |
| 515 } | 487 } |
| 516 | 488 |
| 517 | 489 |
| 518 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 490 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 519 switch (kind) { | 491 switch (kind) { |
| 520 case Token::kEQ: return EQ; | 492 case Token::kEQ: return EQ; |
| 521 case Token::kNE: return NE; | 493 case Token::kNE: return NE; |
| 522 case Token::kLT: return LT; | 494 case Token::kLT: return LT; |
| 523 case Token::kGT: return GT; | 495 case Token::kGT: return GT; |
| 524 case Token::kLTE: return LE; | 496 case Token::kLTE: return LE; |
| 525 case Token::kGTE: return GE; | 497 case Token::kGTE: return GE; |
| 526 default: | 498 default: |
| 527 UNREACHABLE(); | 499 UNREACHABLE(); |
| 528 return VS; | 500 return VS; |
| 529 } | 501 } |
| 530 } | 502 } |
| 531 | 503 |
| 532 | 504 |
| 533 static void EmitDoubleCompareBranch(FlowGraphCompiler* compiler, | 505 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 534 Condition true_condition, | 506 LocationSummary* locs) { |
| 535 FpuRegister left, | 507 QRegister left = locs->in(0).fpu_reg(); |
| 536 FpuRegister right, | 508 QRegister right = locs->in(1).fpu_reg(); |
| 537 BranchInstr* branch) { | |
| 538 ASSERT(branch != NULL); | |
| 539 DRegister dleft = EvenDRegisterOf(left); | 509 DRegister dleft = EvenDRegisterOf(left); |
| 540 DRegister dright = EvenDRegisterOf(right); | 510 DRegister dright = EvenDRegisterOf(right); |
| 541 __ vcmpd(dleft, dright); | 511 __ vcmpd(dleft, dright); |
| 542 __ vmstat(); | 512 __ vmstat(); |
| 543 BlockEntryInstr* nan_result = (true_condition == NE) ? | |
| 544 branch->true_successor() : branch->false_successor(); | |
| 545 __ b(compiler->GetJumpLabel(nan_result), VS); | |
| 546 EmitBranchOnCondition(compiler, | |
| 547 branch->true_successor(), | |
| 548 branch->false_successor(), | |
| 549 true_condition); | |
| 550 } | |
| 551 | |
| 552 | |
| 553 static void EmitDoubleCompareBool(FlowGraphCompiler* compiler, | |
| 554 Condition true_condition, | |
| 555 FpuRegister left, | |
| 556 FpuRegister right, | |
| 557 Register result) { | |
| 558 DRegister dleft = EvenDRegisterOf(left); | |
| 559 DRegister dright = EvenDRegisterOf(right); | |
| 560 __ vcmpd(dleft, dright); | |
| 561 __ vmstat(); | |
| 562 __ LoadObject(result, Bool::False()); | |
| 563 Label done; | |
| 564 if (true_condition != NE) { | |
| 565 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. | |
| 566 } | |
| 567 __ LoadObject(result, Bool::True(), true_condition); | |
| 568 __ Bind(&done); | |
| 569 } | |
| 570 | |
| 571 | |
| 572 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | |
| 573 const LocationSummary& locs, | |
| 574 Token::Kind kind, | |
| 575 BranchInstr* branch) { | |
| 576 QRegister left = locs.in(0).fpu_reg(); | |
| 577 QRegister right = locs.in(1).fpu_reg(); | |
| 578 | |
| 579 Condition true_condition = TokenKindToDoubleCondition(kind); | |
| 580 if (branch != NULL) { | |
| 581 EmitDoubleCompareBranch(compiler, true_condition, left, right, branch); | |
| 582 } else { | |
| 583 EmitDoubleCompareBool(compiler, true_condition, | |
| 584 left, right, locs.out().reg()); | |
| 585 } | |
| 586 } | 513 } |
| 587 | 514 |
| 588 | 515 |
| 589 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 516 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 590 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 517 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 591 BranchInstr* kNoBranch = NULL; | 518 |
| 592 if (operation_cid() == kSmiCid) { | 519 if (operation_cid() == kSmiCid) { |
| 593 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); | 520 Condition true_condition = EmitSmiComparisonOp(compiler, locs(), kind()); |
| 594 return; | 521 Register result = locs()->out().reg(); |
| 522 __ LoadObject(result, Bool::True(), true_condition); | |
|
Florian Schneider
2013/11/11 13:30:42
The ARM code differs slightly from the other platf
| |
| 523 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | |
| 524 } else { | |
| 525 ASSERT(operation_cid() == kDoubleCid); | |
| 526 EmitDoubleComparisonOp(compiler, locs()); | |
| 527 | |
| 528 Register result = locs()->out().reg(); | |
| 529 Condition true_condition = TokenKindToDoubleCondition(kind()); | |
| 530 Label done; | |
| 531 __ LoadObject(result, Bool::False()); | |
| 532 if (true_condition != NE) { | |
| 533 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. | |
| 534 } | |
| 535 __ LoadObject(result, Bool::True(), true_condition); | |
| 536 __ Bind(&done); | |
| 595 } | 537 } |
| 596 if (operation_cid() == kMintCid) { | |
| 597 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch); | |
| 598 return; | |
| 599 } | |
| 600 if (operation_cid() == kDoubleCid) { | |
| 601 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); | |
| 602 return; | |
| 603 } | |
| 604 UNREACHABLE(); | |
| 605 } | 538 } |
| 606 | 539 |
| 607 | 540 |
| 608 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 541 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 609 BranchInstr* branch) { | 542 BranchInstr* branch) { |
| 610 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 543 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 544 | |
| 545 BranchLabels labels = compiler->CreateBranchLabels(branch); | |
| 546 | |
| 547 Condition true_condition = kNoCondition; | |
| 611 if (operation_cid() == kSmiCid) { | 548 if (operation_cid() == kSmiCid) { |
| 612 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 549 true_condition = EmitSmiComparisonOp(compiler, locs(), kind()); |
| 613 return; | 550 } else { |
| 551 ASSERT(operation_cid() == kDoubleCid); | |
| 552 true_condition = TokenKindToDoubleCondition(kind()); | |
| 553 EmitDoubleComparisonOp(compiler, locs()); | |
| 554 | |
| 555 Label* nan_result = (true_condition == NE) ? | |
| 556 labels.true_label : labels.false_label; | |
| 557 __ b(nan_result, VS); | |
| 614 } | 558 } |
| 615 if (operation_cid() == kMintCid) { | 559 EmitBranchOnCondition(compiler, true_condition, labels); |
| 616 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch); | |
| 617 return; | |
| 618 } | |
| 619 if (operation_cid() == kDoubleCid) { | |
| 620 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | |
| 621 return; | |
| 622 } | |
| 623 UNREACHABLE(); | |
| 624 } | 560 } |
| 625 | 561 |
| 626 | 562 |
| 627 LocationSummary* TestSmiInstr::MakeLocationSummary() const { | 563 LocationSummary* TestSmiInstr::MakeLocationSummary() const { |
| 628 const intptr_t kNumInputs = 2; | 564 const intptr_t kNumInputs = 2; |
| 629 const intptr_t kNumTemps = 0; | 565 const intptr_t kNumTemps = 0; |
| 630 LocationSummary* locs = | 566 LocationSummary* locs = |
| 631 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 567 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 632 locs->set_in(0, Location::RequiresRegister()); | 568 locs->set_in(0, Location::RequiresRegister()); |
| 633 // Only one input can be a constant operand. The case of two constant | 569 // Only one input can be a constant operand. The case of two constant |
| 634 // operands should be handled by constant propagation. | 570 // operands should be handled by constant propagation. |
| 635 locs->set_in(1, Location::RegisterOrConstant(right())); | 571 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 636 return locs; | 572 return locs; |
| 637 } | 573 } |
| 638 | 574 |
| 639 | 575 |
| 640 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 576 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 641 // Never emitted outside of the BranchInstr. | 577 // Never emitted outside of the BranchInstr. |
| 642 UNREACHABLE(); | 578 UNREACHABLE(); |
| 643 } | 579 } |
| 644 | 580 |
| 645 | 581 |
| 646 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 582 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 647 BranchInstr* branch) { | 583 BranchInstr* branch) { |
| 648 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ; | 584 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 585 | |
| 586 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; | |
| 649 Register left = locs()->in(0).reg(); | 587 Register left = locs()->in(0).reg(); |
| 650 Location right = locs()->in(1); | 588 Location right = locs()->in(1); |
| 651 if (right.IsConstant()) { | 589 if (right.IsConstant()) { |
| 652 ASSERT(right.constant().IsSmi()); | 590 ASSERT(right.constant().IsSmi()); |
| 653 const int32_t imm = | 591 const int32_t imm = |
| 654 reinterpret_cast<int32_t>(right.constant().raw()); | 592 reinterpret_cast<int32_t>(right.constant().raw()); |
| 655 __ TestImmediate(left, imm); | 593 __ TestImmediate(left, imm); |
| 656 } else { | 594 } else { |
| 657 __ tst(left, ShifterOperand(right.reg())); | 595 __ tst(left, ShifterOperand(right.reg())); |
| 658 } | 596 } |
| 659 EmitBranchOnCondition(compiler, | 597 EmitBranchOnCondition(compiler, true_condition, labels); |
| 660 branch->true_successor(), | |
| 661 branch->false_successor(), | |
| 662 branch_condition); | |
| 663 } | 598 } |
| 664 | 599 |
| 665 | 600 |
| 666 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 601 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| 667 const intptr_t kNumInputs = 2; | 602 const intptr_t kNumInputs = 2; |
| 668 const intptr_t kNumTemps = 0; | 603 const intptr_t kNumTemps = 0; |
| 669 if (operation_cid() == kMintCid) { | 604 if (operation_cid() == kMintCid) { |
| 670 const intptr_t kNumTemps = 2; | 605 const intptr_t kNumTemps = 2; |
| 671 LocationSummary* locs = | 606 LocationSummary* locs = |
| 672 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 607 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 694 summary->set_in(1, summary->in(0).IsConstant() | 629 summary->set_in(1, summary->in(0).IsConstant() |
| 695 ? Location::RequiresRegister() | 630 ? Location::RequiresRegister() |
| 696 : Location::RegisterOrConstant(right())); | 631 : Location::RegisterOrConstant(right())); |
| 697 summary->set_out(Location::RequiresRegister()); | 632 summary->set_out(Location::RequiresRegister()); |
| 698 return summary; | 633 return summary; |
| 699 } | 634 } |
| 700 | 635 |
| 701 | 636 |
| 702 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 637 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 703 if (operation_cid() == kSmiCid) { | 638 if (operation_cid() == kSmiCid) { |
| 704 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); | 639 Condition true_condition = EmitSmiComparisonOp(compiler, locs(), kind()); |
| 705 return; | 640 Register result = locs()->out().reg(); |
| 641 __ LoadObject(result, Bool::True(), true_condition); | |
| 642 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | |
| 643 } else { | |
| 644 ASSERT(operation_cid() == kDoubleCid); | |
| 645 EmitDoubleComparisonOp(compiler, locs()); | |
| 646 | |
| 647 Register result = locs()->out().reg(); | |
| 648 Condition true_condition = TokenKindToDoubleCondition(kind()); | |
| 649 Label done; | |
| 650 __ LoadObject(result, Bool::False()); | |
| 651 if (true_condition != NE) { | |
| 652 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. | |
| 653 } | |
| 654 __ LoadObject(result, Bool::True(), true_condition); | |
| 655 __ Bind(&done); | |
| 706 } | 656 } |
| 707 if (operation_cid() == kMintCid) { | |
| 708 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL); | |
| 709 return; | |
| 710 } | |
| 711 ASSERT(operation_cid() == kDoubleCid); | |
| 712 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); | |
| 713 } | 657 } |
| 714 | 658 |
| 715 | 659 |
| 716 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 660 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 717 BranchInstr* branch) { | 661 BranchInstr* branch) { |
| 662 BranchLabels labels = compiler->CreateBranchLabels(branch); | |
| 663 | |
| 664 Condition true_condition = kNoCondition; | |
| 718 if (operation_cid() == kSmiCid) { | 665 if (operation_cid() == kSmiCid) { |
| 719 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 666 true_condition = EmitSmiComparisonOp(compiler, locs(), kind()); |
| 720 return; | 667 } else { |
| 668 ASSERT(operation_cid() == kDoubleCid); | |
| 669 true_condition = TokenKindToDoubleCondition(kind()); | |
| 670 EmitDoubleComparisonOp(compiler, locs()); | |
| 671 | |
| 672 Label* nan_result = (true_condition == NE) ? | |
| 673 labels.true_label : labels.false_label; | |
| 674 __ b(nan_result, VS); | |
| 721 } | 675 } |
| 722 if (operation_cid() == kMintCid) { | 676 EmitBranchOnCondition(compiler, true_condition, labels); |
| 723 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); | |
| 724 return; | |
| 725 } | |
| 726 ASSERT(operation_cid() == kDoubleCid); | |
| 727 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | |
| 728 } | 677 } |
| 729 | 678 |
| 730 | 679 |
| 731 LocationSummary* NativeCallInstr::MakeLocationSummary() const { | 680 LocationSummary* NativeCallInstr::MakeLocationSummary() const { |
| 732 const intptr_t kNumInputs = 0; | 681 const intptr_t kNumInputs = 0; |
| 733 const intptr_t kNumTemps = 3; | 682 const intptr_t kNumTemps = 3; |
| 734 LocationSummary* locs = | 683 LocationSummary* locs = |
| 735 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 684 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 736 locs->set_temp(0, Location::RegisterLocation(R1)); | 685 locs->set_temp(0, Location::RegisterLocation(R1)); |
| 737 locs->set_temp(1, Location::RegisterLocation(R2)); | 686 locs->set_temp(1, Location::RegisterLocation(R2)); |
| (...skipping 3734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4472 // Only one of the inputs can be a constant. Choose register if the first one | 4421 // Only one of the inputs can be a constant. Choose register if the first one |
| 4473 // is a constant. | 4422 // is a constant. |
| 4474 locs->set_in(1, locs->in(0).IsConstant() | 4423 locs->set_in(1, locs->in(0).IsConstant() |
| 4475 ? Location::RequiresRegister() | 4424 ? Location::RequiresRegister() |
| 4476 : Location::RegisterOrConstant(right())); | 4425 : Location::RegisterOrConstant(right())); |
| 4477 locs->set_out(Location::RequiresRegister()); | 4426 locs->set_out(Location::RequiresRegister()); |
| 4478 return locs; | 4427 return locs; |
| 4479 } | 4428 } |
| 4480 | 4429 |
| 4481 | 4430 |
| 4431 static void EmitStrictComparison(FlowGraphCompiler* compiler, | |
| 4432 StrictCompareInstr* compare) { | |
| 4433 LocationSummary* locs = compare->locs(); | |
| 4434 bool needs_number_check = compare->needs_number_check(); | |
| 4435 intptr_t token_pos = compare->token_pos(); | |
| 4436 Location left = locs->in(0); | |
| 4437 Location right = locs->in(1); | |
| 4438 ASSERT(!left.IsConstant() || !right.IsConstant()); | |
| 4439 if (left.IsConstant()) { | |
| 4440 compiler->EmitEqualityRegConstCompare(right.reg(), | |
| 4441 left.constant(), | |
| 4442 needs_number_check, | |
| 4443 token_pos); | |
| 4444 } else if (right.IsConstant()) { | |
| 4445 compiler->EmitEqualityRegConstCompare(left.reg(), | |
| 4446 right.constant(), | |
| 4447 needs_number_check, | |
| 4448 token_pos); | |
| 4449 } else { | |
| 4450 compiler->EmitEqualityRegRegCompare(left.reg(), | |
| 4451 right.reg(), | |
| 4452 needs_number_check, | |
| 4453 token_pos); | |
| 4454 } | |
| 4455 } | |
| 4456 | |
| 4457 | |
| 4482 // Special code for numbers (compare values instead of references.) | 4458 // Special code for numbers (compare values instead of references.) |
| 4483 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4459 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4484 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4460 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 4485 Location left = locs()->in(0); | 4461 |
| 4486 Location right = locs()->in(1); | 4462 EmitStrictComparison(compiler, this); |
| 4487 ASSERT(!left.IsConstant() || !right.IsConstant()); | |
| 4488 if (left.IsConstant()) { | |
| 4489 compiler->EmitEqualityRegConstCompare(right.reg(), | |
| 4490 left.constant(), | |
| 4491 needs_number_check(), | |
| 4492 token_pos()); | |
| 4493 } else if (right.IsConstant()) { | |
| 4494 compiler->EmitEqualityRegConstCompare(left.reg(), | |
| 4495 right.constant(), | |
| 4496 needs_number_check(), | |
| 4497 token_pos()); | |
| 4498 } else { | |
| 4499 compiler->EmitEqualityRegRegCompare(left.reg(), | |
| 4500 right.reg(), | |
| 4501 needs_number_check(), | |
| 4502 token_pos()); | |
| 4503 } | |
| 4504 | 4463 |
| 4505 Register result = locs()->out().reg(); | 4464 Register result = locs()->out().reg(); |
| 4506 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; | 4465 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; |
| 4507 __ LoadObject(result, Bool::True(), true_condition); | 4466 __ LoadObject(result, Bool::True(), true_condition); |
| 4508 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 4467 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
| 4509 } | 4468 } |
| 4510 | 4469 |
| 4511 | 4470 |
| 4512 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 4471 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 4513 BranchInstr* branch) { | 4472 BranchInstr* branch) { |
| 4514 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4473 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 4515 Location left = locs()->in(0); | |
| 4516 Location right = locs()->in(1); | |
| 4517 ASSERT(!left.IsConstant() || !right.IsConstant()); | |
| 4518 if (left.IsConstant()) { | |
| 4519 compiler->EmitEqualityRegConstCompare(right.reg(), | |
| 4520 left.constant(), | |
| 4521 needs_number_check(), | |
| 4522 token_pos()); | |
| 4523 } else if (right.IsConstant()) { | |
| 4524 compiler->EmitEqualityRegConstCompare(left.reg(), | |
| 4525 right.constant(), | |
| 4526 needs_number_check(), | |
| 4527 token_pos()); | |
| 4528 } else { | |
| 4529 compiler->EmitEqualityRegRegCompare(left.reg(), | |
| 4530 right.reg(), | |
| 4531 needs_number_check(), | |
| 4532 token_pos()); | |
| 4533 } | |
| 4534 | 4474 |
| 4475 EmitStrictComparison(compiler, this); | |
| 4476 | |
| 4477 BranchLabels labels = compiler->CreateBranchLabels(branch); | |
| 4535 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; | 4478 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; |
| 4536 EmitBranchOnCondition(compiler, | 4479 EmitBranchOnCondition(compiler, true_condition, labels); |
| 4537 branch->true_successor(), | |
| 4538 branch->false_successor(), | |
| 4539 true_condition); | |
| 4540 } | 4480 } |
| 4541 | 4481 |
| 4542 | 4482 |
| 4543 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { | 4483 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { |
| 4544 return LocationSummary::Make(1, | 4484 return LocationSummary::Make(1, |
| 4545 Location::RequiresRegister(), | 4485 Location::RequiresRegister(), |
| 4546 LocationSummary::kNoCall); | 4486 LocationSummary::kNoCall); |
| 4547 } | 4487 } |
| 4548 | 4488 |
| 4549 | 4489 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4613 compiler->GenerateCall(token_pos(), | 4553 compiler->GenerateCall(token_pos(), |
| 4614 &label, | 4554 &label, |
| 4615 PcDescriptors::kOther, | 4555 PcDescriptors::kOther, |
| 4616 locs()); | 4556 locs()); |
| 4617 __ Drop(2); // Discard type arguments and receiver. | 4557 __ Drop(2); // Discard type arguments and receiver. |
| 4618 } | 4558 } |
| 4619 | 4559 |
| 4620 } // namespace dart | 4560 } // namespace dart |
| 4621 | 4561 |
| 4622 #endif // defined TARGET_ARCH_ARM | 4562 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |