| 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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 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 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 case Token::kGTE: return GE; | 432 case Token::kGTE: return GE; |
| 433 default: | 433 default: |
| 434 UNREACHABLE(); | 434 UNREACHABLE(); |
| 435 return VS; | 435 return VS; |
| 436 } | 436 } |
| 437 } | 437 } |
| 438 | 438 |
| 439 | 439 |
| 440 // Branches on condition c assuming comparison results in CMPRES1 and CMPRES2. | 440 // Branches on condition c assuming comparison results in CMPRES1 and CMPRES2. |
| 441 static void EmitBranchAfterCompare( | 441 static void EmitBranchAfterCompare( |
| 442 FlowGraphCompiler* compiler, Condition c, Label* is_true) { | 442 FlowGraphCompiler* compiler, Condition condition, Label* is_true) { |
| 443 switch (c) { | 443 switch (condition) { |
| 444 case EQ: __ beq(CMPRES1, CMPRES2, is_true); break; | 444 case EQ: __ beq(CMPRES1, CMPRES2, is_true); break; |
| 445 case NE: __ bne(CMPRES1, CMPRES2, is_true); break; | 445 case NE: __ bne(CMPRES1, CMPRES2, is_true); break; |
| 446 case GT: __ bne(CMPRES2, ZR, is_true); break; | 446 case GT: __ bne(CMPRES2, ZR, is_true); break; |
| 447 case GE: __ beq(CMPRES1, ZR, is_true); break; | 447 case GE: __ beq(CMPRES1, ZR, is_true); break; |
| 448 case LT: __ bne(CMPRES1, ZR, is_true); break; | 448 case LT: __ bne(CMPRES1, ZR, is_true); break; |
| 449 case LE: __ beq(CMPRES2, ZR, is_true); break; | 449 case LE: __ beq(CMPRES2, ZR, is_true); break; |
| 450 default: | 450 default: |
| 451 UNREACHABLE(); | 451 UNREACHABLE(); |
| 452 break; | 452 break; |
| 453 } | 453 } |
| 454 } | 454 } |
| 455 | 455 |
| 456 | 456 |
| 457 static Condition FlipCondition(Condition condition) { | 457 static Condition FlipCondition(Condition condition) { |
| 458 switch (condition) { | 458 switch (condition) { |
| 459 case EQ: return EQ; | 459 case EQ: return EQ; |
| 460 case NE: return NE; | 460 case NE: return NE; |
| 461 case LT: return GT; | 461 case LT: return GT; |
| 462 case LE: return GE; | 462 case LE: return GE; |
| 463 case GT: return LT; | 463 case GT: return LT; |
| 464 case GE: return LE; | 464 case GE: return LE; |
| 465 default: | 465 default: |
| 466 UNREACHABLE(); | 466 UNREACHABLE(); |
| 467 return EQ; | 467 return EQ; |
| 468 } | 468 } |
| 469 } | 469 } |
| 470 | 470 |
| 471 | 471 |
| 472 // The comparison result is in CMPRES1. | 472 // The comparison result is in CMPRES1/CMPRES2. |
| 473 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 473 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 474 TargetEntryInstr* true_successor, | 474 Condition true_condition, |
| 475 TargetEntryInstr* false_successor, | 475 BranchLabels labels) { |
| 476 Condition true_condition) { | |
| 477 __ TraceSimMsg("ControlInstruction::EmitBranchOnCondition"); | 476 __ TraceSimMsg("ControlInstruction::EmitBranchOnCondition"); |
| 478 if (compiler->CanFallThroughTo(false_successor)) { | 477 if (labels.fall_through == labels.false_label) { |
| 479 // If the next block is the false successor, fall through to it. | 478 // If the next block is the false successor, fall through to it. |
| 480 Label* label = compiler->GetJumpLabel(true_successor); | 479 EmitBranchAfterCompare(compiler, true_condition, labels.true_label); |
| 481 EmitBranchAfterCompare(compiler, true_condition, label); | |
| 482 } else { | 480 } else { |
| 483 // If the next block is not the false successor, branch to it. | 481 // If the next block is not the false successor, branch to it. |
| 484 Condition false_condition = NegateCondition(true_condition); | 482 Condition false_condition = NegateCondition(true_condition); |
| 485 Label* label = compiler->GetJumpLabel(false_successor); | 483 EmitBranchAfterCompare(compiler, false_condition, labels.false_label); |
| 486 EmitBranchAfterCompare(compiler, false_condition, label); | |
| 487 // Fall through or jump to the true successor. | 484 // Fall through or jump to the true successor. |
| 488 if (!compiler->CanFallThroughTo(true_successor)) { | 485 if (labels.fall_through != labels.true_label) { |
| 489 __ b(compiler->GetJumpLabel(true_successor)); | 486 __ b(labels.true_label); |
| 490 } | 487 } |
| 491 } | 488 } |
| 492 } | 489 } |
| 493 | 490 |
| 494 | 491 |
| 495 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 492 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 496 const LocationSummary& locs, | 493 const LocationSummary& locs, |
| 497 Token::Kind kind, | 494 Token::Kind kind, |
| 498 BranchInstr* branch) { | 495 BranchLabels labels) { |
| 499 __ TraceSimMsg("EmitSmiComparisonOp"); | 496 __ TraceSimMsg("EmitSmiComparisonOp"); |
| 500 __ Comment("EmitSmiComparisonOp"); | 497 __ Comment("EmitSmiComparisonOp"); |
| 501 Location left = locs.in(0); | 498 Location left = locs.in(0); |
| 502 Location right = locs.in(1); | 499 Location right = locs.in(1); |
| 503 ASSERT(!left.IsConstant() || !right.IsConstant()); | 500 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 504 | 501 |
| 505 Condition true_condition = TokenKindToSmiCondition(kind); | 502 Condition true_condition = TokenKindToSmiCondition(kind); |
| 506 | 503 |
| 507 if (left.IsConstant()) { | 504 if (left.IsConstant()) { |
| 508 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant()); | 505 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant()); |
| 509 true_condition = FlipCondition(true_condition); | 506 true_condition = FlipCondition(true_condition); |
| 510 } else if (right.IsConstant()) { | 507 } else if (right.IsConstant()) { |
| 511 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant()); | 508 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant()); |
| 512 } else { | 509 } else { |
| 513 __ slt(CMPRES1, left.reg(), right.reg()); | 510 __ slt(CMPRES1, left.reg(), right.reg()); |
| 514 __ slt(CMPRES2, right.reg(), left.reg()); | 511 __ slt(CMPRES2, right.reg(), left.reg()); |
| 515 } | 512 } |
| 516 | 513 EmitBranchOnCondition(compiler, true_condition, labels); |
| 517 if (branch != NULL) { | |
| 518 EmitBranchOnCondition(compiler, | |
| 519 branch->true_successor(), | |
| 520 branch->false_successor(), | |
| 521 true_condition); | |
| 522 } else { | |
| 523 Register result = locs.out().reg(); | |
| 524 Label done, is_true; | |
| 525 EmitBranchAfterCompare(compiler, true_condition, &is_true); | |
| 526 __ LoadObject(result, Bool::False()); | |
| 527 __ b(&done); | |
| 528 __ Bind(&is_true); | |
| 529 __ LoadObject(result, Bool::True()); | |
| 530 __ Bind(&done); | |
| 531 } | |
| 532 } | |
| 533 | |
| 534 | |
| 535 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | |
| 536 const LocationSummary& locs, | |
| 537 Token::Kind kind, | |
| 538 BranchInstr* branch) { | |
| 539 UNIMPLEMENTED(); | |
| 540 } | |
| 541 | |
| 542 | |
| 543 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | |
| 544 const LocationSummary& locs, | |
| 545 Token::Kind kind, | |
| 546 BranchInstr* branch) { | |
| 547 UNIMPLEMENTED(); | |
| 548 } | 514 } |
| 549 | 515 |
| 550 | 516 |
| 551 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 517 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 552 switch (kind) { | 518 switch (kind) { |
| 553 case Token::kEQ: return EQ; | 519 case Token::kEQ: return EQ; |
| 554 case Token::kNE: return NE; | 520 case Token::kNE: return NE; |
| 555 case Token::kLT: return LT; | 521 case Token::kLT: return LT; |
| 556 case Token::kGT: return GT; | 522 case Token::kGT: return GT; |
| 557 case Token::kLTE: return LE; | 523 case Token::kLTE: return LE; |
| 558 case Token::kGTE: return GE; | 524 case Token::kGTE: return GE; |
| 559 default: | 525 default: |
| 560 UNREACHABLE(); | 526 UNREACHABLE(); |
| 561 return VS; | 527 return VS; |
| 562 } | 528 } |
| 563 } | 529 } |
| 564 | 530 |
| 565 | 531 |
| 566 static void EmitDoubleCompareBranch(FlowGraphCompiler* compiler, | 532 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 567 Condition true_condition, | 533 const LocationSummary& locs, |
| 568 FpuRegister left, | 534 Token::Kind kind, |
| 569 FpuRegister right, | 535 BranchLabels labels) { |
| 570 BranchInstr* branch) { | 536 DRegister left = locs.in(0).fpu_reg(); |
| 571 ASSERT(branch != NULL); | 537 DRegister right = locs.in(1).fpu_reg(); |
| 572 __ Comment("DoubleCompareBranch"); | 538 |
| 539 __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right); |
| 540 |
| 541 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 573 __ cund(left, right); | 542 __ cund(left, right); |
| 574 BlockEntryInstr* nan_result = (true_condition == NE) ? | 543 Label* nan_label = (true_condition == NE) |
| 575 branch->true_successor() : branch->false_successor(); | 544 ? labels.true_label : labels.false_label; |
| 576 __ bc1t(compiler->GetJumpLabel(nan_result)); | 545 __ bc1t(nan_label); |
| 577 | 546 |
| 578 switch (true_condition) { | 547 switch (true_condition) { |
| 579 case EQ: __ ceqd(left, right); break; | 548 case EQ: __ ceqd(left, right); break; |
| 580 case NE: __ ceqd(left, right); break; | 549 case NE: __ ceqd(left, right); break; |
| 581 case LT: __ coltd(left, right); break; | 550 case LT: __ coltd(left, right); break; |
| 582 case LE: __ coled(left, right); break; | 551 case LE: __ coled(left, right); break; |
| 583 case GT: __ coltd(right, left); break; | 552 case GT: __ coltd(right, left); break; |
| 584 case GE: __ coled(right, left); break; | 553 case GE: __ coled(right, left); break; |
| 585 default: { | 554 default: { |
| 586 // Should only passing the above conditions to this function. | 555 // Should only passing the above conditions to this function. |
| 587 UNREACHABLE(); | 556 UNREACHABLE(); |
| 588 break; | 557 break; |
| 589 } | 558 } |
| 590 } | 559 } |
| 591 | 560 |
| 592 __ LoadImmediate(TMP, 1); | 561 __ LoadImmediate(TMP, 1); |
| 593 if (true_condition == NE) { | 562 if (true_condition == NE) { |
| 594 __ movf(CMPRES1, ZR); | 563 __ movf(CMPRES1, ZR); |
| 595 __ movt(CMPRES1, TMP); | 564 __ movt(CMPRES1, TMP); |
| 596 } else { | 565 } else { |
| 597 __ movf(CMPRES1, TMP); | 566 __ movf(CMPRES1, TMP); |
| 598 __ movt(CMPRES1, ZR); | 567 __ movt(CMPRES1, ZR); |
| 599 } | 568 } |
| 600 __ mov(CMPRES2, ZR); | 569 __ mov(CMPRES2, ZR); |
| 601 | 570 |
| 602 // EmitBranchOnCondition expects ordering to be described by CMPRES1, CMPRES2. | 571 // EmitBranchOnCondition expects ordering to be described by CMPRES1, CMPRES2. |
| 603 EmitBranchOnCondition(compiler, | 572 EmitBranchOnCondition(compiler, EQ, labels); |
| 604 branch->true_successor(), | |
| 605 branch->false_successor(), | |
| 606 EQ); | |
| 607 } | |
| 608 | |
| 609 | |
| 610 static void EmitDoubleCompareBool(FlowGraphCompiler* compiler, | |
| 611 Condition true_condition, | |
| 612 FpuRegister left, | |
| 613 FpuRegister right, | |
| 614 Register result) { | |
| 615 Label done, is_true; | |
| 616 Label* nan_label = (true_condition == NE) ? &is_true : &done; | |
| 617 __ Comment("DoubleCompareBool"); | |
| 618 __ LoadObject(result, Bool::False()); | |
| 619 __ cund(left, right); | |
| 620 __ bc1t(nan_label); | |
| 621 | |
| 622 switch (true_condition) { | |
| 623 case EQ: __ ceqd(left, right); break; | |
| 624 case NE: __ ceqd(left, right); break; | |
| 625 case LT: __ coltd(left, right); break; | |
| 626 case LE: __ coled(left, right); break; | |
| 627 case GT: __ coltd(right, left); break; | |
| 628 case GE: __ coled(right, left); break; | |
| 629 default: { | |
| 630 // Should only passing the above conditions to this function. | |
| 631 UNREACHABLE(); | |
| 632 break; | |
| 633 } | |
| 634 } | |
| 635 | |
| 636 if (true_condition == NE) { | |
| 637 __ bc1t(&done); // False is already in result. | |
| 638 } else { | |
| 639 __ bc1f(&done); | |
| 640 } | |
| 641 __ Bind(&is_true); | |
| 642 __ LoadObject(result, Bool::True()); | |
| 643 __ Bind(&done); | |
| 644 } | |
| 645 | |
| 646 | |
| 647 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | |
| 648 const LocationSummary& locs, | |
| 649 Token::Kind kind, | |
| 650 BranchInstr* branch) { | |
| 651 DRegister left = locs.in(0).fpu_reg(); | |
| 652 DRegister right = locs.in(1).fpu_reg(); | |
| 653 | |
| 654 __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right); | |
| 655 | |
| 656 Condition true_condition = TokenKindToDoubleCondition(kind); | |
| 657 if (branch != NULL) { | |
| 658 EmitDoubleCompareBranch(compiler, true_condition, left, right, branch); | |
| 659 } else { | |
| 660 EmitDoubleCompareBool(compiler, true_condition, | |
| 661 left, right, locs.out().reg()); | |
| 662 } | |
| 663 } | 573 } |
| 664 | 574 |
| 665 | 575 |
| 666 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 576 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 667 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 577 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 668 BranchInstr* kNoBranch = NULL; | |
| 669 __ Comment("EqualityCompareInstr"); | 578 __ Comment("EqualityCompareInstr"); |
| 579 |
| 580 Label is_true, is_false; |
| 581 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 582 |
| 670 if (operation_cid() == kSmiCid) { | 583 if (operation_cid() == kSmiCid) { |
| 671 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); | 584 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 672 return; | 585 } else { |
| 586 ASSERT(operation_cid() == kDoubleCid); |
| 587 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 673 } | 588 } |
| 674 if (operation_cid() == kMintCid) { | 589 Register result = locs()->out().reg(); |
| 675 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch); | 590 Label done; |
| 676 return; | 591 __ Bind(&is_false); |
| 677 } | 592 __ LoadObject(result, Bool::False()); |
| 678 if (operation_cid() == kDoubleCid) { | 593 __ b(&done); |
| 679 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); | 594 __ Bind(&is_true); |
| 680 return; | 595 __ LoadObject(result, Bool::True()); |
| 681 } | 596 __ Bind(&done); |
| 682 UNREACHABLE(); | |
| 683 } | 597 } |
| 684 | 598 |
| 685 | 599 |
| 686 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 600 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 687 BranchInstr* branch) { | 601 BranchInstr* branch) { |
| 688 __ TraceSimMsg("EqualityCompareInstr"); | 602 __ TraceSimMsg("EqualityCompareInstr"); |
| 689 __ Comment("EqualityCompareInstr:BranchCode"); | 603 __ Comment("EqualityCompareInstr:BranchCode"); |
| 690 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 604 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 605 |
| 606 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 607 |
| 691 if (operation_cid() == kSmiCid) { | 608 if (operation_cid() == kSmiCid) { |
| 692 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 609 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 693 return; | 610 } else { |
| 611 ASSERT(operation_cid() == kDoubleCid); |
| 612 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 694 } | 613 } |
| 695 if (operation_cid() == kMintCid) { | |
| 696 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch); | |
| 697 return; | |
| 698 } | |
| 699 if (operation_cid() == kDoubleCid) { | |
| 700 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | |
| 701 return; | |
| 702 } | |
| 703 UNREACHABLE(); | |
| 704 } | 614 } |
| 705 | 615 |
| 706 | 616 |
| 707 LocationSummary* TestSmiInstr::MakeLocationSummary() const { | 617 LocationSummary* TestSmiInstr::MakeLocationSummary() const { |
| 708 const intptr_t kNumInputs = 2; | 618 const intptr_t kNumInputs = 2; |
| 709 const intptr_t kNumTemps = 0; | 619 const intptr_t kNumTemps = 0; |
| 710 LocationSummary* locs = | 620 LocationSummary* locs = |
| 711 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 621 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 712 locs->set_in(0, Location::RequiresRegister()); | 622 locs->set_in(0, Location::RequiresRegister()); |
| 713 // Only one input can be a constant operand. The case of two constant | 623 // Only one input can be a constant operand. The case of two constant |
| 714 // operands should be handled by constant propagation. | 624 // operands should be handled by constant propagation. |
| 715 locs->set_in(1, Location::RegisterOrConstant(right())); | 625 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 716 return locs; | 626 return locs; |
| 717 } | 627 } |
| 718 | 628 |
| 719 | 629 |
| 720 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 630 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 721 // Never emitted outside of the BranchInstr. | 631 // Never emitted outside of the BranchInstr. |
| 722 UNREACHABLE(); | 632 UNREACHABLE(); |
| 723 } | 633 } |
| 724 | 634 |
| 725 | 635 |
| 726 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 636 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 727 BranchInstr* branch) { | 637 BranchInstr* branch) { |
| 728 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ; | 638 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 639 |
| 640 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; |
| 729 Register left = locs()->in(0).reg(); | 641 Register left = locs()->in(0).reg(); |
| 730 Location right = locs()->in(1); | 642 Location right = locs()->in(1); |
| 731 if (right.IsConstant()) { | 643 if (right.IsConstant()) { |
| 732 ASSERT(right.constant().IsSmi()); | 644 ASSERT(right.constant().IsSmi()); |
| 733 const int32_t imm = | 645 const int32_t imm = |
| 734 reinterpret_cast<int32_t>(right.constant().raw()); | 646 reinterpret_cast<int32_t>(right.constant().raw()); |
| 735 __ AndImmediate(CMPRES1, left, imm); | 647 __ AndImmediate(CMPRES1, left, imm); |
| 736 } else { | 648 } else { |
| 737 __ and_(CMPRES1, left, right.reg()); | 649 __ and_(CMPRES1, left, right.reg()); |
| 738 } | 650 } |
| 739 __ mov(CMPRES2, ZR); | 651 __ mov(CMPRES2, ZR); |
| 740 EmitBranchOnCondition(compiler, | 652 EmitBranchOnCondition(compiler, true_condition, labels); |
| 741 branch->true_successor(), | |
| 742 branch->false_successor(), | |
| 743 branch_condition); | |
| 744 } | 653 } |
| 745 | 654 |
| 746 | 655 |
| 747 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 656 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| 748 const intptr_t kNumInputs = 2; | 657 const intptr_t kNumInputs = 2; |
| 749 const intptr_t kNumTemps = 0; | 658 const intptr_t kNumTemps = 0; |
| 750 if (operation_cid() == kMintCid) { | 659 if (operation_cid() == kMintCid) { |
| 751 const intptr_t kNumTemps = 2; | 660 const intptr_t kNumTemps = 2; |
| 752 LocationSummary* locs = | 661 LocationSummary* locs = |
| 753 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 662 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 775 summary->set_in(1, summary->in(0).IsConstant() | 684 summary->set_in(1, summary->in(0).IsConstant() |
| 776 ? Location::RequiresRegister() | 685 ? Location::RequiresRegister() |
| 777 : Location::RegisterOrConstant(right())); | 686 : Location::RegisterOrConstant(right())); |
| 778 summary->set_out(Location::RequiresRegister()); | 687 summary->set_out(Location::RequiresRegister()); |
| 779 return summary; | 688 return summary; |
| 780 } | 689 } |
| 781 | 690 |
| 782 | 691 |
| 783 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 692 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 784 __ TraceSimMsg("RelationalOpInstr"); | 693 __ TraceSimMsg("RelationalOpInstr"); |
| 694 |
| 695 Label is_true, is_false; |
| 696 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 697 |
| 785 if (operation_cid() == kSmiCid) { | 698 if (operation_cid() == kSmiCid) { |
| 786 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); | 699 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 787 return; | 700 } else { |
| 701 ASSERT(operation_cid() == kDoubleCid); |
| 702 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 788 } | 703 } |
| 789 if (operation_cid() == kMintCid) { | 704 Register result = locs()->out().reg(); |
| 790 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL); | 705 Label done; |
| 791 return; | 706 __ Bind(&is_false); |
| 792 } | 707 __ LoadObject(result, Bool::False()); |
| 793 ASSERT(operation_cid() == kDoubleCid); | 708 __ b(&done); |
| 794 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); | 709 __ Bind(&is_true); |
| 795 return; | 710 __ LoadObject(result, Bool::True()); |
| 711 __ Bind(&done); |
| 796 } | 712 } |
| 797 | 713 |
| 798 | 714 |
| 799 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 715 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 800 BranchInstr* branch) { | 716 BranchInstr* branch) { |
| 801 __ TraceSimMsg("RelationalOpInstr"); | 717 __ TraceSimMsg("RelationalOpInstr"); |
| 718 |
| 719 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 720 |
| 802 if (operation_cid() == kSmiCid) { | 721 if (operation_cid() == kSmiCid) { |
| 803 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 722 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 804 return; | 723 } else { |
| 724 ASSERT(operation_cid() == kDoubleCid); |
| 725 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 805 } | 726 } |
| 806 if (operation_cid() == kMintCid) { | |
| 807 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); | |
| 808 return; | |
| 809 } | |
| 810 ASSERT(operation_cid() == kDoubleCid); | |
| 811 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | |
| 812 } | 727 } |
| 813 | 728 |
| 814 | 729 |
| 815 LocationSummary* NativeCallInstr::MakeLocationSummary() const { | 730 LocationSummary* NativeCallInstr::MakeLocationSummary() const { |
| 816 const intptr_t kNumInputs = 0; | 731 const intptr_t kNumInputs = 0; |
| 817 const intptr_t kNumTemps = 3; | 732 const intptr_t kNumTemps = 3; |
| 818 LocationSummary* locs = | 733 LocationSummary* locs = |
| 819 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 734 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 820 locs->set_temp(0, Location::RegisterLocation(A1)); | 735 locs->set_temp(0, Location::RegisterLocation(A1)); |
| 821 locs->set_temp(1, Location::RegisterLocation(A2)); | 736 locs->set_temp(1, Location::RegisterLocation(A2)); |
| (...skipping 3018 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3840 // Only one of the inputs can be a constant. Choose register if the first one | 3755 // Only one of the inputs can be a constant. Choose register if the first one |
| 3841 // is a constant. | 3756 // is a constant. |
| 3842 locs->set_in(1, locs->in(0).IsConstant() | 3757 locs->set_in(1, locs->in(0).IsConstant() |
| 3843 ? Location::RequiresRegister() | 3758 ? Location::RequiresRegister() |
| 3844 : Location::RegisterOrConstant(right())); | 3759 : Location::RegisterOrConstant(right())); |
| 3845 locs->set_out(Location::RequiresRegister()); | 3760 locs->set_out(Location::RequiresRegister()); |
| 3846 return locs; | 3761 return locs; |
| 3847 } | 3762 } |
| 3848 | 3763 |
| 3849 | 3764 |
| 3765 static void EmitStrictComparison(FlowGraphCompiler* compiler, |
| 3766 StrictCompareInstr* compare, |
| 3767 BranchLabels labels) { |
| 3768 LocationSummary* locs = compare->locs(); |
| 3769 bool needs_number_check = compare->needs_number_check(); |
| 3770 intptr_t token_pos = compare->token_pos(); |
| 3771 Token::Kind kind = compare->kind(); |
| 3772 Location left = locs->in(0); |
| 3773 Location right = locs->in(1); |
| 3774 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 3775 if (left.IsConstant()) { |
| 3776 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 3777 left.constant(), |
| 3778 needs_number_check, |
| 3779 token_pos); |
| 3780 } else if (right.IsConstant()) { |
| 3781 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 3782 right.constant(), |
| 3783 needs_number_check, |
| 3784 token_pos); |
| 3785 } else { |
| 3786 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 3787 right.reg(), |
| 3788 needs_number_check, |
| 3789 token_pos); |
| 3790 } |
| 3791 Condition true_condition = (kind == Token::kEQ_STRICT) ? EQ : NE; |
| 3792 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3793 } |
| 3794 |
| 3850 // Special code for numbers (compare values instead of references.) | 3795 // Special code for numbers (compare values instead of references.) |
| 3851 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3796 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3852 __ TraceSimMsg("StrictCompareInstr"); | 3797 __ TraceSimMsg("StrictCompareInstr"); |
| 3853 __ Comment("StrictCompareInstr"); | 3798 __ Comment("StrictCompareInstr"); |
| 3854 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 3799 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 3855 Location left = locs()->in(0); | 3800 |
| 3856 Location right = locs()->in(1); | 3801 Label is_true, is_false; |
| 3857 ASSERT(!left.IsConstant() || !right.IsConstant()); | 3802 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 3858 if (left.IsConstant()) { | 3803 |
| 3859 compiler->EmitEqualityRegConstCompare(right.reg(), | 3804 EmitStrictComparison(compiler, this, labels); |
| 3860 left.constant(), | |
| 3861 needs_number_check(), | |
| 3862 token_pos()); | |
| 3863 } else if (right.IsConstant()) { | |
| 3864 compiler->EmitEqualityRegConstCompare(left.reg(), | |
| 3865 right.constant(), | |
| 3866 needs_number_check(), | |
| 3867 token_pos()); | |
| 3868 } else { | |
| 3869 compiler->EmitEqualityRegRegCompare(left.reg(), | |
| 3870 right.reg(), | |
| 3871 needs_number_check(), | |
| 3872 token_pos()); | |
| 3873 } | |
| 3874 | 3805 |
| 3875 Register result = locs()->out().reg(); | 3806 Register result = locs()->out().reg(); |
| 3876 Label load_true, done; | 3807 Label done; |
| 3877 if (kind() == Token::kEQ_STRICT) { | 3808 __ Bind(&is_false); |
| 3878 __ beq(CMPRES1, CMPRES2, &load_true); | |
| 3879 } else { | |
| 3880 ASSERT(kind() == Token::kNE_STRICT); | |
| 3881 __ bne(CMPRES1, CMPRES2, &load_true); | |
| 3882 } | |
| 3883 __ LoadObject(result, Bool::False()); | 3809 __ LoadObject(result, Bool::False()); |
| 3884 __ b(&done); | 3810 __ b(&done); |
| 3885 __ Bind(&load_true); | 3811 __ Bind(&is_true); |
| 3886 __ LoadObject(result, Bool::True()); | 3812 __ LoadObject(result, Bool::True()); |
| 3887 __ Bind(&done); | 3813 __ Bind(&done); |
| 3888 } | 3814 } |
| 3889 | 3815 |
| 3890 | 3816 |
| 3891 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 3817 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 3892 BranchInstr* branch) { | 3818 BranchInstr* branch) { |
| 3893 __ TraceSimMsg("StrictCompareInstr::EmitBranchCode"); | 3819 __ TraceSimMsg("StrictCompareInstr::EmitBranchCode"); |
| 3894 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 3820 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 3895 Location left = locs()->in(0); | |
| 3896 Location right = locs()->in(1); | |
| 3897 ASSERT(!left.IsConstant() || !right.IsConstant()); | |
| 3898 if (left.IsConstant()) { | |
| 3899 compiler->EmitEqualityRegConstCompare(right.reg(), | |
| 3900 left.constant(), | |
| 3901 needs_number_check(), | |
| 3902 token_pos()); | |
| 3903 } else if (right.IsConstant()) { | |
| 3904 compiler->EmitEqualityRegConstCompare(left.reg(), | |
| 3905 right.constant(), | |
| 3906 needs_number_check(), | |
| 3907 token_pos()); | |
| 3908 } else { | |
| 3909 compiler->EmitEqualityRegRegCompare(left.reg(), | |
| 3910 right.reg(), | |
| 3911 needs_number_check(), | |
| 3912 token_pos()); | |
| 3913 } | |
| 3914 | 3821 |
| 3915 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; | 3822 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 3916 EmitBranchOnCondition(compiler, | 3823 |
| 3917 branch->true_successor(), | 3824 EmitStrictComparison(compiler, this, labels); |
| 3918 branch->false_successor(), | |
| 3919 true_condition); | |
| 3920 } | 3825 } |
| 3921 | 3826 |
| 3922 | 3827 |
| 3923 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { | 3828 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { |
| 3924 return LocationSummary::Make(1, | 3829 return LocationSummary::Make(1, |
| 3925 Location::RequiresRegister(), | 3830 Location::RequiresRegister(), |
| 3926 LocationSummary::kNoCall); | 3831 LocationSummary::kNoCall); |
| 3927 } | 3832 } |
| 3928 | 3833 |
| 3929 | 3834 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3997 compiler->GenerateCall(token_pos(), | 3902 compiler->GenerateCall(token_pos(), |
| 3998 &label, | 3903 &label, |
| 3999 PcDescriptors::kOther, | 3904 PcDescriptors::kOther, |
| 4000 locs()); | 3905 locs()); |
| 4001 __ Drop(2); // Discard type arguments and receiver. | 3906 __ Drop(2); // Discard type arguments and receiver. |
| 4002 } | 3907 } |
| 4003 | 3908 |
| 4004 } // namespace dart | 3909 } // namespace dart |
| 4005 | 3910 |
| 4006 #endif // defined TARGET_ARCH_MIPS | 3911 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |