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 |