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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 89 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
90 ASSERT(fp_sp_dist <= 0); | 90 ASSERT(fp_sp_dist <= 0); |
91 __ movq(RDI, RSP); | 91 __ movq(RDI, RSP); |
92 __ subq(RDI, RBP); | 92 __ subq(RDI, RBP); |
93 __ cmpq(RDI, Immediate(fp_sp_dist)); | 93 __ cmpq(RDI, Immediate(fp_sp_dist)); |
94 __ j(EQUAL, &done, Assembler::kNearJump); | 94 __ j(EQUAL, &done, Assembler::kNearJump); |
95 __ int3(); | 95 __ int3(); |
96 __ Bind(&done); | 96 __ Bind(&done); |
97 } | 97 } |
98 #endif | 98 #endif |
99 __ LeaveFrame(); | |
100 __ ret(); | |
101 | 99 |
102 // Generate 8 bytes of NOPs so that the debugger can patch the | 100 __ ReturnPatchable(); |
103 // return pattern with a call to the debug stub. | |
104 // Note that the nop(8) byte pattern is not recognized by the debugger. | |
105 __ nop(1); | |
106 __ nop(1); | |
107 __ nop(1); | |
108 __ nop(1); | |
109 __ nop(1); | |
110 __ nop(1); | |
111 __ nop(1); | |
112 __ nop(1); | |
113 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 101 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
114 Isolate::kNoDeoptId, | 102 Isolate::kNoDeoptId, |
115 token_pos()); | 103 token_pos()); |
116 } | 104 } |
117 | 105 |
118 | 106 |
119 static Condition NegateCondition(Condition condition) { | 107 static Condition NegateCondition(Condition condition) { |
120 switch (condition) { | 108 switch (condition) { |
121 case EQUAL: return NOT_EQUAL; | 109 case EQUAL: return NOT_EQUAL; |
122 case NOT_EQUAL: return EQUAL; | 110 case NOT_EQUAL: return EQUAL; |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 return LocationSummary::Make(kNumInputs, | 296 return LocationSummary::Make(kNumInputs, |
309 Location::RequiresRegister(), | 297 Location::RequiresRegister(), |
310 LocationSummary::kNoCall); | 298 LocationSummary::kNoCall); |
311 } | 299 } |
312 | 300 |
313 | 301 |
314 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 302 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
315 // The register allocator drops constant definitions that have no uses. | 303 // The register allocator drops constant definitions that have no uses. |
316 if (!locs()->out().IsInvalid()) { | 304 if (!locs()->out().IsInvalid()) { |
317 Register result = locs()->out().reg(); | 305 Register result = locs()->out().reg(); |
318 __ LoadObject(result, value()); | 306 __ LoadObject(result, value(), PP); |
319 } | 307 } |
320 } | 308 } |
321 | 309 |
322 | 310 |
323 LocationSummary* AssertAssignableInstr::MakeLocationSummary() const { | 311 LocationSummary* AssertAssignableInstr::MakeLocationSummary() const { |
324 const intptr_t kNumInputs = 3; | 312 const intptr_t kNumInputs = 3; |
325 const intptr_t kNumTemps = 0; | 313 const intptr_t kNumTemps = 0; |
326 LocationSummary* summary = | 314 LocationSummary* summary = |
327 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 315 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
328 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. | 316 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 const ICData& original_ic_data) { | 446 const ICData& original_ic_data) { |
459 if (!compiler->is_optimizing()) { | 447 if (!compiler->is_optimizing()) { |
460 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 448 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
461 deopt_id, | 449 deopt_id, |
462 token_pos); | 450 token_pos); |
463 } | 451 } |
464 const int kNumberOfArguments = 2; | 452 const int kNumberOfArguments = 2; |
465 const Array& kNoArgumentNames = Object::null_array(); | 453 const Array& kNoArgumentNames = Object::null_array(); |
466 const int kNumArgumentsChecked = 2; | 454 const int kNumArgumentsChecked = 2; |
467 | 455 |
468 const Immediate& raw_null = | |
469 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
470 Label check_identity; | 456 Label check_identity; |
471 __ cmpq(Address(RSP, 0 * kWordSize), raw_null); | 457 __ LoadObject(TMP, Object::Handle(), PP); |
| 458 __ cmpq(Address(RSP, 0 * kWordSize), TMP); |
472 __ j(EQUAL, &check_identity); | 459 __ j(EQUAL, &check_identity); |
473 __ cmpq(Address(RSP, 1 * kWordSize), raw_null); | 460 __ cmpq(Address(RSP, 1 * kWordSize), TMP); |
474 __ j(EQUAL, &check_identity); | 461 __ j(EQUAL, &check_identity); |
475 | 462 |
476 ICData& equality_ic_data = ICData::ZoneHandle(original_ic_data.raw()); | 463 ICData& equality_ic_data = ICData::ZoneHandle(original_ic_data.raw()); |
477 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { | 464 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { |
478 ASSERT(!original_ic_data.IsNull()); | 465 ASSERT(!original_ic_data.IsNull()); |
479 if (original_ic_data.NumberOfChecks() == 0) { | 466 if (original_ic_data.NumberOfChecks() == 0) { |
480 // IC call for reoptimization populates original ICData. | 467 // IC call for reoptimization populates original ICData. |
481 equality_ic_data = original_ic_data.raw(); | 468 equality_ic_data = original_ic_data.raw(); |
482 } else { | 469 } else { |
483 // Megamorphic call. | 470 // Megamorphic call. |
(...skipping 20 matching lines...) Expand all Loading... |
504 | 491 |
505 __ Bind(&check_identity); | 492 __ Bind(&check_identity); |
506 Label equality_done; | 493 Label equality_done; |
507 if (compiler->is_optimizing()) { | 494 if (compiler->is_optimizing()) { |
508 // No need to update IC data. | 495 // No need to update IC data. |
509 Label is_true; | 496 Label is_true; |
510 __ popq(RAX); | 497 __ popq(RAX); |
511 __ popq(RDX); | 498 __ popq(RDX); |
512 __ cmpq(RAX, RDX); | 499 __ cmpq(RAX, RDX); |
513 __ j(EQUAL, &is_true); | 500 __ j(EQUAL, &is_true); |
514 __ LoadObject(RAX, Bool::Get(kind != Token::kEQ)); | 501 __ LoadObject(RAX, Bool::Get(kind != Token::kEQ), PP); |
515 __ jmp(&equality_done); | 502 __ jmp(&equality_done); |
516 __ Bind(&is_true); | 503 __ Bind(&is_true); |
517 __ LoadObject(RAX, Bool::Get(kind == Token::kEQ)); | 504 __ LoadObject(RAX, Bool::Get(kind == Token::kEQ), PP); |
518 if (kind == Token::kNE) { | 505 if (kind == Token::kNE) { |
519 // Skip not-equal result conversion. | 506 // Skip not-equal result conversion. |
520 __ jmp(&equality_done); | 507 __ jmp(&equality_done); |
521 } | 508 } |
522 } else { | 509 } else { |
523 // Call stub, load IC data in register. The stub will update ICData if | 510 // Call stub, load IC data in register. The stub will update ICData if |
524 // necessary. | 511 // necessary. |
525 Register ic_data_reg = locs->temp(0).reg(); | 512 Register ic_data_reg = locs->temp(0).reg(); |
526 ASSERT(ic_data_reg == RBX); // Stub depends on it. | 513 ASSERT(ic_data_reg == RBX); // Stub depends on it. |
527 __ LoadObject(ic_data_reg, equality_ic_data); | 514 __ LoadObject(ic_data_reg, equality_ic_data, PP); |
528 compiler->GenerateCall(token_pos, | 515 compiler->GenerateCall(token_pos, |
529 &StubCode::EqualityWithNullArgLabel(), | 516 &StubCode::EqualityWithNullArgLabel(), |
530 PcDescriptors::kRuntimeCall, | 517 PcDescriptors::kRuntimeCall, |
531 locs); | 518 locs); |
532 __ Drop(2); | 519 __ Drop(2); |
533 } | 520 } |
534 __ Bind(&check_ne); | 521 __ Bind(&check_ne); |
535 if (kind == Token::kNE) { | 522 if (kind == Token::kNE) { |
536 Label true_label, done; | 523 Label true_label, done; |
537 // Negate the condition: true label returns false and vice versa. | 524 // Negate the condition: true label returns false and vice versa. |
538 __ CompareObject(RAX, Bool::True()); | 525 __ CompareObject(RAX, Bool::True()); |
539 __ j(EQUAL, &true_label, Assembler::kNearJump); | 526 __ j(EQUAL, &true_label, Assembler::kNearJump); |
540 __ LoadObject(RAX, Bool::True()); | 527 __ LoadObject(RAX, Bool::True(), PP); |
541 __ jmp(&done, Assembler::kNearJump); | 528 __ jmp(&done, Assembler::kNearJump); |
542 __ Bind(&true_label); | 529 __ Bind(&true_label); |
543 __ LoadObject(RAX, Bool::False()); | 530 __ LoadObject(RAX, Bool::False(), PP); |
544 __ Bind(&done); | 531 __ Bind(&done); |
545 } | 532 } |
546 __ Bind(&equality_done); | 533 __ Bind(&equality_done); |
547 } | 534 } |
548 | 535 |
549 | 536 |
550 static void LoadValueCid(FlowGraphCompiler* compiler, | 537 static void LoadValueCid(FlowGraphCompiler* compiler, |
551 Register value_cid_reg, | 538 Register value_cid_reg, |
552 Register value_reg, | 539 Register value_reg, |
553 Label* value_is_smi = NULL) { | 540 Label* value_is_smi = NULL) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 // Object.== is same as ===. | 590 // Object.== is same as ===. |
604 __ Drop(2); | 591 __ Drop(2); |
605 __ cmpq(left, right); | 592 __ cmpq(left, right); |
606 if (branch != NULL) { | 593 if (branch != NULL) { |
607 branch->EmitBranchOnCondition(compiler, cond); | 594 branch->EmitBranchOnCondition(compiler, cond); |
608 } else { | 595 } else { |
609 // This case should be rare. | 596 // This case should be rare. |
610 Register result = locs->out().reg(); | 597 Register result = locs->out().reg(); |
611 Label load_true; | 598 Label load_true; |
612 __ j(cond, &load_true, Assembler::kNearJump); | 599 __ j(cond, &load_true, Assembler::kNearJump); |
613 __ LoadObject(result, Bool::False()); | 600 __ LoadObject(result, Bool::False(), PP); |
614 __ jmp(&done); | 601 __ jmp(&done); |
615 __ Bind(&load_true); | 602 __ Bind(&load_true); |
616 __ LoadObject(result, Bool::True()); | 603 __ LoadObject(result, Bool::True(), PP); |
617 } | 604 } |
618 } else { | 605 } else { |
619 const int kNumberOfArguments = 2; | 606 const int kNumberOfArguments = 2; |
620 const Array& kNoArgumentNames = Object::null_array(); | 607 const Array& kNoArgumentNames = Object::null_array(); |
621 compiler->GenerateStaticCall(deopt_id, | 608 compiler->GenerateStaticCall(deopt_id, |
622 token_pos, | 609 token_pos, |
623 target, | 610 target, |
624 kNumberOfArguments, | 611 kNumberOfArguments, |
625 kNoArgumentNames, | 612 kNoArgumentNames, |
626 locs); | 613 locs); |
627 if (branch == NULL) { | 614 if (branch == NULL) { |
628 if (kind == Token::kNE) { | 615 if (kind == Token::kNE) { |
629 Label false_label; | 616 Label false_label; |
630 __ CompareObject(RAX, Bool::True()); | 617 __ CompareObject(RAX, Bool::True()); |
631 __ j(EQUAL, &false_label, Assembler::kNearJump); | 618 __ j(EQUAL, &false_label, Assembler::kNearJump); |
632 __ LoadObject(RAX, Bool::True()); | 619 __ LoadObject(RAX, Bool::True(), PP); |
633 __ jmp(&done); | 620 __ jmp(&done); |
634 __ Bind(&false_label); | 621 __ Bind(&false_label); |
635 __ LoadObject(RAX, Bool::False()); | 622 __ LoadObject(RAX, Bool::False(), PP); |
636 } | 623 } |
637 } else { | 624 } else { |
638 if (branch->is_checked()) { | 625 if (branch->is_checked()) { |
639 EmitAssertBoolean(RAX, token_pos, deopt_id, locs, compiler); | 626 EmitAssertBoolean(RAX, token_pos, deopt_id, locs, compiler); |
640 } | 627 } |
641 __ CompareObject(RAX, Bool::True()); | 628 __ CompareObject(RAX, Bool::True()); |
642 branch->EmitBranchOnCondition(compiler, cond); | 629 branch->EmitBranchOnCondition(compiler, cond); |
643 } | 630 } |
644 } | 631 } |
645 if (i < len - 1) { | 632 if (i < len - 1) { |
(...skipping 13 matching lines...) Expand all Loading... |
659 BranchInstr* branch, | 646 BranchInstr* branch, |
660 intptr_t deopt_id) { | 647 intptr_t deopt_id) { |
661 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 648 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
662 Register left = locs.in(0).reg(); | 649 Register left = locs.in(0).reg(); |
663 Register right = locs.in(1).reg(); | 650 Register right = locs.in(1).reg(); |
664 Register temp = locs.temp(0).reg(); | 651 Register temp = locs.temp(0).reg(); |
665 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); | 652 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); |
666 __ testq(left, Immediate(kSmiTagMask)); | 653 __ testq(left, Immediate(kSmiTagMask)); |
667 __ j(ZERO, deopt); | 654 __ j(ZERO, deopt); |
668 // 'left' is not Smi. | 655 // 'left' is not Smi. |
669 const Immediate& raw_null = | 656 |
670 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
671 Label identity_compare; | 657 Label identity_compare; |
672 __ cmpq(right, raw_null); | 658 __ CompareObject(right, Object::Handle()); |
673 __ j(EQUAL, &identity_compare); | 659 __ j(EQUAL, &identity_compare); |
674 __ cmpq(left, raw_null); | 660 __ CompareObject(left, Object::Handle()); |
675 __ j(EQUAL, &identity_compare); | 661 __ j(EQUAL, &identity_compare); |
676 | 662 |
677 __ LoadClassId(temp, left); | 663 __ LoadClassId(temp, left); |
678 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); | 664 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); |
679 const intptr_t len = ic_data.NumberOfChecks(); | 665 const intptr_t len = ic_data.NumberOfChecks(); |
680 for (intptr_t i = 0; i < len; i++) { | 666 for (intptr_t i = 0; i < len; i++) { |
681 __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); | 667 __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); |
682 if (i == (len - 1)) { | 668 if (i == (len - 1)) { |
683 __ j(NOT_EQUAL, deopt); | 669 __ j(NOT_EQUAL, deopt); |
684 } else { | 670 } else { |
685 __ j(EQUAL, &identity_compare); | 671 __ j(EQUAL, &identity_compare); |
686 } | 672 } |
687 } | 673 } |
688 __ Bind(&identity_compare); | 674 __ Bind(&identity_compare); |
689 __ cmpq(left, right); | 675 __ cmpq(left, right); |
690 if (branch == NULL) { | 676 if (branch == NULL) { |
691 Label done, is_equal; | 677 Label done, is_equal; |
692 Register result = locs.out().reg(); | 678 Register result = locs.out().reg(); |
693 __ j(EQUAL, &is_equal, Assembler::kNearJump); | 679 __ j(EQUAL, &is_equal, Assembler::kNearJump); |
694 // Not equal. | 680 // Not equal. |
695 __ LoadObject(result, Bool::Get(kind != Token::kEQ)); | 681 __ LoadObject(result, Bool::Get(kind != Token::kEQ), PP); |
696 __ jmp(&done, Assembler::kNearJump); | 682 __ jmp(&done, Assembler::kNearJump); |
697 __ Bind(&is_equal); | 683 __ Bind(&is_equal); |
698 __ LoadObject(result, Bool::Get(kind == Token::kEQ)); | 684 __ LoadObject(result, Bool::Get(kind == Token::kEQ), PP); |
699 __ Bind(&done); | 685 __ Bind(&done); |
700 } else { | 686 } else { |
701 Condition cond = TokenKindToSmiCondition(kind); | 687 Condition cond = TokenKindToSmiCondition(kind); |
702 branch->EmitBranchOnCondition(compiler, cond); | 688 branch->EmitBranchOnCondition(compiler, cond); |
703 } | 689 } |
704 } | 690 } |
705 | 691 |
706 | 692 |
707 // First test if receiver is NULL, in which case === is applied. | 693 // First test if receiver is NULL, in which case === is applied. |
708 // If type feedback was provided (lists of <class-id, target>), do a | 694 // If type feedback was provided (lists of <class-id, target>), do a |
709 // type by type check (either === or static call to the operator. | 695 // type by type check (either === or static call to the operator. |
710 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, | 696 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
711 LocationSummary* locs, | 697 LocationSummary* locs, |
712 Token::Kind kind, | 698 Token::Kind kind, |
713 BranchInstr* branch, | 699 BranchInstr* branch, |
714 const ICData& ic_data, | 700 const ICData& ic_data, |
715 intptr_t deopt_id, | 701 intptr_t deopt_id, |
716 intptr_t token_pos) { | 702 intptr_t token_pos) { |
717 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 703 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
718 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 704 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
719 Register left = locs->in(0).reg(); | 705 Register left = locs->in(0).reg(); |
720 Register right = locs->in(1).reg(); | 706 Register right = locs->in(1).reg(); |
721 const Immediate& raw_null = | 707 |
722 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
723 Label done, identity_compare, non_null_compare; | 708 Label done, identity_compare, non_null_compare; |
724 __ cmpq(right, raw_null); | 709 __ CompareObject(right, Object::Handle()); |
725 __ j(EQUAL, &identity_compare, Assembler::kNearJump); | 710 __ j(EQUAL, &identity_compare, Assembler::kNearJump); |
726 __ cmpq(left, raw_null); | 711 __ CompareObject(left, Object::Handle()); |
727 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); | 712 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); |
728 // Comparison with NULL is "===". | 713 // Comparison with NULL is "===". |
729 __ Bind(&identity_compare); | 714 __ Bind(&identity_compare); |
730 __ cmpq(left, right); | 715 __ cmpq(left, right); |
731 Condition cond = TokenKindToSmiCondition(kind); | 716 Condition cond = TokenKindToSmiCondition(kind); |
732 if (branch != NULL) { | 717 if (branch != NULL) { |
733 branch->EmitBranchOnCondition(compiler, cond); | 718 branch->EmitBranchOnCondition(compiler, cond); |
734 } else { | 719 } else { |
735 Register result = locs->out().reg(); | 720 Register result = locs->out().reg(); |
736 Label load_true; | 721 Label load_true; |
737 __ j(cond, &load_true, Assembler::kNearJump); | 722 __ j(cond, &load_true, Assembler::kNearJump); |
738 __ LoadObject(result, Bool::False()); | 723 __ LoadObject(result, Bool::False(), PP); |
739 __ jmp(&done); | 724 __ jmp(&done); |
740 __ Bind(&load_true); | 725 __ Bind(&load_true); |
741 __ LoadObject(result, Bool::True()); | 726 __ LoadObject(result, Bool::True(), PP); |
742 } | 727 } |
743 __ jmp(&done); | 728 __ jmp(&done); |
744 __ Bind(&non_null_compare); // Receiver is not null. | 729 __ Bind(&non_null_compare); // Receiver is not null. |
745 __ pushq(left); | 730 __ pushq(left); |
746 __ pushq(right); | 731 __ pushq(right); |
747 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 732 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
748 deopt_id, token_pos); | 733 deopt_id, token_pos); |
749 __ Bind(&done); | 734 __ Bind(&done); |
750 } | 735 } |
751 | 736 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 } else { | 774 } else { |
790 __ cmpq(left.reg(), right.reg()); | 775 __ cmpq(left.reg(), right.reg()); |
791 } | 776 } |
792 | 777 |
793 if (branch != NULL) { | 778 if (branch != NULL) { |
794 branch->EmitBranchOnCondition(compiler, true_condition); | 779 branch->EmitBranchOnCondition(compiler, true_condition); |
795 } else { | 780 } else { |
796 Register result = locs.out().reg(); | 781 Register result = locs.out().reg(); |
797 Label done, is_true; | 782 Label done, is_true; |
798 __ j(true_condition, &is_true); | 783 __ j(true_condition, &is_true); |
799 __ LoadObject(result, Bool::False()); | 784 __ LoadObject(result, Bool::False(), PP); |
800 __ jmp(&done); | 785 __ jmp(&done); |
801 __ Bind(&is_true); | 786 __ Bind(&is_true); |
802 __ LoadObject(result, Bool::True()); | 787 __ LoadObject(result, Bool::True(), PP); |
803 __ Bind(&done); | 788 __ Bind(&done); |
804 } | 789 } |
805 } | 790 } |
806 | 791 |
807 | 792 |
808 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 793 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
809 switch (kind) { | 794 switch (kind) { |
810 case Token::kEQ: return EQUAL; | 795 case Token::kEQ: return EQUAL; |
811 case Token::kNE: return NOT_EQUAL; | 796 case Token::kNE: return NOT_EQUAL; |
812 case Token::kLT: return BELOW; | 797 case Token::kLT: return BELOW; |
(...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1520 if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) { | 1505 if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) { |
1521 if (!compiler->is_optimizing() && (field_reg == kNoRegister)) { | 1506 if (!compiler->is_optimizing() && (field_reg == kNoRegister)) { |
1522 // Currently we can't have different location summaries for optimized | 1507 // Currently we can't have different location summaries for optimized |
1523 // and non-optimized code. So instead we manually pick up a register | 1508 // and non-optimized code. So instead we manually pick up a register |
1524 // that is known to be free because we know how non-optimizing compiler | 1509 // that is known to be free because we know how non-optimizing compiler |
1525 // allocates registers. | 1510 // allocates registers. |
1526 field_reg = RBX; | 1511 field_reg = RBX; |
1527 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg)); | 1512 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg)); |
1528 } | 1513 } |
1529 | 1514 |
1530 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); | 1515 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP); |
1531 | 1516 |
1532 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); | 1517 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); |
1533 FieldAddress field_nullability_operand( | 1518 FieldAddress field_nullability_operand( |
1534 field_reg, Field::is_nullable_offset()); | 1519 field_reg, Field::is_nullable_offset()); |
1535 FieldAddress field_length_operand( | 1520 FieldAddress field_length_operand( |
1536 field_reg, Field::guarded_list_length_offset()); | 1521 field_reg, Field::guarded_list_length_offset()); |
1537 | 1522 |
1538 if (value_cid == kDynamicCid) { | 1523 if (value_cid == kDynamicCid) { |
1539 if (value_cid_reg == kNoRegister) { | 1524 if (value_cid_reg == kNoRegister) { |
1540 ASSERT(!compiler->is_optimizing()); | 1525 ASSERT(!compiler->is_optimizing()); |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1704 __ movq(field_length_operand, | 1689 __ movq(field_length_operand, |
1705 Immediate(Smi::RawValue(Field::kNoFixedLength))); | 1690 Immediate(Smi::RawValue(Field::kNoFixedLength))); |
1706 } | 1691 } |
1707 } | 1692 } |
1708 } | 1693 } |
1709 if (!ok_is_fall_through) { | 1694 if (!ok_is_fall_through) { |
1710 __ jmp(&ok); | 1695 __ jmp(&ok); |
1711 } | 1696 } |
1712 } else { | 1697 } else { |
1713 if (field_reg != kNoRegister) { | 1698 if (field_reg != kNoRegister) { |
1714 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); | 1699 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP); |
1715 } | 1700 } |
1716 | 1701 |
1717 if (value_cid == kDynamicCid) { | 1702 if (value_cid == kDynamicCid) { |
1718 // Field's guarded class id is fixed but value's class id is not known. | 1703 // Field's guarded class id is fixed but value's class id is not known. |
1719 __ testq(value_reg, Immediate(kSmiTagMask)); | 1704 __ testq(value_reg, Immediate(kSmiTagMask)); |
1720 | 1705 |
1721 if (field_cid != kSmiCid) { | 1706 if (field_cid != kSmiCid) { |
1722 __ j(ZERO, fail); | 1707 __ j(ZERO, fail); |
1723 __ LoadClassId(value_cid_reg, value_reg); | 1708 __ LoadClassId(value_cid_reg, value_reg); |
1724 __ cmpq(value_cid_reg, Immediate(field_cid)); | 1709 __ cmpq(value_cid_reg, Immediate(field_cid)); |
(...skipping 15 matching lines...) Expand all Loading... |
1740 } else if (RawObject::IsTypedDataClassId(field_cid)) { | 1725 } else if (RawObject::IsTypedDataClassId(field_cid)) { |
1741 // Destroy value_cid_reg (safe because we are finished with it). | 1726 // Destroy value_cid_reg (safe because we are finished with it). |
1742 __ movq(value_cid_reg, | 1727 __ movq(value_cid_reg, |
1743 FieldAddress(value_reg, TypedData::length_offset())); | 1728 FieldAddress(value_reg, TypedData::length_offset())); |
1744 } | 1729 } |
1745 __ cmpq(value_cid_reg, field_length_operand); | 1730 __ cmpq(value_cid_reg, field_length_operand); |
1746 } | 1731 } |
1747 | 1732 |
1748 if (field().is_nullable() && (field_cid != kNullCid)) { | 1733 if (field().is_nullable() && (field_cid != kNullCid)) { |
1749 __ j(EQUAL, &ok); | 1734 __ j(EQUAL, &ok); |
1750 const Immediate& raw_null = | 1735 __ CompareObject(value_reg, Object::Handle()); |
1751 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
1752 __ cmpq(value_reg, raw_null); | |
1753 } | 1736 } |
1754 | 1737 |
1755 if (ok_is_fall_through) { | 1738 if (ok_is_fall_through) { |
1756 __ j(NOT_EQUAL, fail); | 1739 __ j(NOT_EQUAL, fail); |
1757 } else { | 1740 } else { |
1758 __ j(EQUAL, &ok); | 1741 __ j(EQUAL, &ok); |
1759 } | 1742 } |
1760 } else { | 1743 } else { |
1761 // Both value's and field's class id is known. | 1744 // Both value's and field's class id is known. |
1762 if ((value_cid != field_cid) && (value_cid != nullability)) { | 1745 if ((value_cid != field_cid) && (value_cid != nullability)) { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1867 : Location::RequiresRegister()); | 1850 : Location::RequiresRegister()); |
1868 locs->set_temp(0, Location::RequiresRegister()); | 1851 locs->set_temp(0, Location::RequiresRegister()); |
1869 return locs; | 1852 return locs; |
1870 } | 1853 } |
1871 | 1854 |
1872 | 1855 |
1873 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1856 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1874 Register value = locs()->in(0).reg(); | 1857 Register value = locs()->in(0).reg(); |
1875 Register temp = locs()->temp(0).reg(); | 1858 Register temp = locs()->temp(0).reg(); |
1876 | 1859 |
1877 __ LoadObject(temp, field()); | 1860 __ LoadObject(temp, field(), PP); |
1878 if (this->value()->NeedsStoreBuffer()) { | 1861 if (this->value()->NeedsStoreBuffer()) { |
1879 __ StoreIntoObject(temp, | 1862 __ StoreIntoObject(temp, |
1880 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi()); | 1863 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi()); |
1881 } else { | 1864 } else { |
1882 __ StoreIntoObjectNoBarrier( | 1865 __ StoreIntoObjectNoBarrier( |
1883 temp, FieldAddress(temp, Field::value_offset()), value); | 1866 temp, FieldAddress(temp, Field::value_offset()), value); |
1884 } | 1867 } |
1885 } | 1868 } |
1886 | 1869 |
1887 | 1870 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2021 // (or null). | 2004 // (or null). |
2022 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 2005 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
2023 !type_arguments().CanShareInstantiatorTypeArguments( | 2006 !type_arguments().CanShareInstantiatorTypeArguments( |
2024 instantiator_class())); | 2007 instantiator_class())); |
2025 // If the instantiator is null and if the type argument vector | 2008 // If the instantiator is null and if the type argument vector |
2026 // instantiated from null becomes a vector of dynamic, then use null as | 2009 // instantiated from null becomes a vector of dynamic, then use null as |
2027 // the type arguments. | 2010 // the type arguments. |
2028 Label type_arguments_instantiated; | 2011 Label type_arguments_instantiated; |
2029 const intptr_t len = type_arguments().Length(); | 2012 const intptr_t len = type_arguments().Length(); |
2030 if (type_arguments().IsRawInstantiatedRaw(len)) { | 2013 if (type_arguments().IsRawInstantiatedRaw(len)) { |
2031 const Immediate& raw_null = | 2014 __ CompareObject(instantiator_reg, Object::Handle()); |
2032 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
2033 __ cmpq(instantiator_reg, raw_null); | |
2034 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2015 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
2035 } | 2016 } |
2036 // Instantiate non-null type arguments. | 2017 // Instantiate non-null type arguments. |
2037 // A runtime call to instantiate the type arguments is required. | 2018 // A runtime call to instantiate the type arguments is required. |
2038 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 2019 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
2039 __ PushObject(type_arguments()); | 2020 __ PushObject(type_arguments()); |
2040 __ pushq(instantiator_reg); // Push instantiator type arguments. | 2021 __ pushq(instantiator_reg); // Push instantiator type arguments. |
2041 compiler->GenerateCallRuntime(token_pos(), | 2022 compiler->GenerateCallRuntime(token_pos(), |
2042 deopt_id(), | 2023 deopt_id(), |
2043 kInstantiateTypeArgumentsRuntimeEntry, | 2024 kInstantiateTypeArgumentsRuntimeEntry, |
(...skipping 27 matching lines...) Expand all Loading... |
2071 // instantiator_reg is the instantiator type argument vector, i.e. an | 2052 // instantiator_reg is the instantiator type argument vector, i.e. an |
2072 // AbstractTypeArguments object (or null). | 2053 // AbstractTypeArguments object (or null). |
2073 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 2054 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
2074 !type_arguments().CanShareInstantiatorTypeArguments( | 2055 !type_arguments().CanShareInstantiatorTypeArguments( |
2075 instantiator_class())); | 2056 instantiator_class())); |
2076 // If the instantiator is null and if the type argument vector | 2057 // If the instantiator is null and if the type argument vector |
2077 // instantiated from null becomes a vector of dynamic, then use null as | 2058 // instantiated from null becomes a vector of dynamic, then use null as |
2078 // the type arguments. | 2059 // the type arguments. |
2079 Label type_arguments_instantiated; | 2060 Label type_arguments_instantiated; |
2080 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); | 2061 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); |
2081 const Immediate& raw_null = | 2062 |
2082 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 2063 __ CompareObject(instantiator_reg, Object::Handle()); |
2083 __ cmpq(instantiator_reg, raw_null); | |
2084 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2064 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
2085 // Instantiate non-null type arguments. | 2065 // Instantiate non-null type arguments. |
2086 // In the non-factory case, we rely on the allocation stub to | 2066 // In the non-factory case, we rely on the allocation stub to |
2087 // instantiate the type arguments. | 2067 // instantiate the type arguments. |
2088 __ LoadObject(result_reg, type_arguments()); | 2068 __ LoadObject(result_reg, type_arguments(), PP); |
2089 // result_reg: uninstantiated type arguments. | 2069 // result_reg: uninstantiated type arguments. |
2090 | 2070 |
2091 __ Bind(&type_arguments_instantiated); | 2071 __ Bind(&type_arguments_instantiated); |
2092 // result_reg: uninstantiated or instantiated type arguments. | 2072 // result_reg: uninstantiated or instantiated type arguments. |
2093 } | 2073 } |
2094 | 2074 |
2095 | 2075 |
2096 LocationSummary* | 2076 LocationSummary* |
2097 ExtractConstructorInstantiatorInstr::MakeLocationSummary() const { | 2077 ExtractConstructorInstantiatorInstr::MakeLocationSummary() const { |
2098 const intptr_t kNumInputs = 1; | 2078 const intptr_t kNumInputs = 1; |
(...skipping 14 matching lines...) Expand all Loading... |
2113 // instantiator_reg is the instantiator AbstractTypeArguments object | 2093 // instantiator_reg is the instantiator AbstractTypeArguments object |
2114 // (or null). | 2094 // (or null). |
2115 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 2095 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
2116 !type_arguments().CanShareInstantiatorTypeArguments( | 2096 !type_arguments().CanShareInstantiatorTypeArguments( |
2117 instantiator_class())); | 2097 instantiator_class())); |
2118 | 2098 |
2119 // If the instantiator is null and if the type argument vector | 2099 // If the instantiator is null and if the type argument vector |
2120 // instantiated from null becomes a vector of dynamic, then use null as | 2100 // instantiated from null becomes a vector of dynamic, then use null as |
2121 // the type arguments and do not pass the instantiator. | 2101 // the type arguments and do not pass the instantiator. |
2122 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); | 2102 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); |
2123 const Immediate& raw_null = | 2103 |
2124 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
2125 Label instantiator_not_null; | 2104 Label instantiator_not_null; |
2126 __ cmpq(instantiator_reg, raw_null); | 2105 __ CompareObject(instantiator_reg, Object::Handle()); |
2127 __ j(NOT_EQUAL, &instantiator_not_null, Assembler::kNearJump); | 2106 __ j(NOT_EQUAL, &instantiator_not_null, Assembler::kNearJump); |
2128 // Null was used in VisitExtractConstructorTypeArguments as the | 2107 // Null was used in VisitExtractConstructorTypeArguments as the |
2129 // instantiated type arguments, no proper instantiator needed. | 2108 // instantiated type arguments, no proper instantiator needed. |
2130 __ movq(instantiator_reg, | 2109 __ movq(instantiator_reg, |
2131 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 2110 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
2132 __ Bind(&instantiator_not_null); | 2111 __ Bind(&instantiator_not_null); |
2133 // instantiator_reg: instantiator or kNoInstantiator. | 2112 // instantiator_reg: instantiator or kNoInstantiator. |
2134 } | 2113 } |
2135 | 2114 |
2136 | 2115 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2192 } | 2171 } |
2193 | 2172 |
2194 | 2173 |
2195 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2174 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2196 __ Bind(compiler->GetJumpLabel(this)); | 2175 __ Bind(compiler->GetJumpLabel(this)); |
2197 compiler->AddExceptionHandler(catch_try_index(), | 2176 compiler->AddExceptionHandler(catch_try_index(), |
2198 try_index(), | 2177 try_index(), |
2199 compiler->assembler()->CodeSize(), | 2178 compiler->assembler()->CodeSize(), |
2200 catch_handler_types_, | 2179 catch_handler_types_, |
2201 needs_stacktrace()); | 2180 needs_stacktrace()); |
| 2181 |
| 2182 // Restore the pool pointer. |
| 2183 __ LoadPoolPointer(PP); |
| 2184 |
2202 if (HasParallelMove()) { | 2185 if (HasParallelMove()) { |
2203 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 2186 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
2204 } | 2187 } |
2205 | 2188 |
2206 // Restore RSP from RBP as we are coming from a throw and the code for | 2189 // Restore RSP from RBP as we are coming from a throw and the code for |
2207 // popping arguments has not been run. | 2190 // popping arguments has not been run. |
2208 const intptr_t fp_sp_dist = | 2191 const intptr_t fp_sp_dist = |
2209 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 2192 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
2210 ASSERT(fp_sp_dist <= 0); | 2193 ASSERT(fp_sp_dist <= 0); |
2211 __ leaq(RSP, Address(RBP, fp_sp_dist)); | 2194 __ leaq(RSP, Address(RBP, fp_sp_dist)); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2272 | 2255 |
2273 Register temp = locs()->temp(0).reg(); | 2256 Register temp = locs()->temp(0).reg(); |
2274 // Generate stack overflow check. | 2257 // Generate stack overflow check. |
2275 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); | 2258 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); |
2276 __ cmpq(RSP, Address(temp, 0)); | 2259 __ cmpq(RSP, Address(temp, 0)); |
2277 __ j(BELOW_EQUAL, slow_path->entry_label()); | 2260 __ j(BELOW_EQUAL, slow_path->entry_label()); |
2278 if (compiler->CanOSRFunction() && in_loop()) { | 2261 if (compiler->CanOSRFunction() && in_loop()) { |
2279 // In unoptimized code check the usage counter to trigger OSR at loop | 2262 // In unoptimized code check the usage counter to trigger OSR at loop |
2280 // stack checks. Use progressively higher thresholds for more deeply | 2263 // stack checks. Use progressively higher thresholds for more deeply |
2281 // nested loops to attempt to hit outer loops with OSR when possible. | 2264 // nested loops to attempt to hit outer loops with OSR when possible. |
2282 __ LoadObject(temp, compiler->parsed_function().function()); | 2265 __ LoadObject(temp, compiler->parsed_function().function(), PP); |
2283 intptr_t threshold = | 2266 intptr_t threshold = |
2284 FLAG_optimization_counter_threshold * (loop_depth() + 1); | 2267 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
2285 __ cmpq(FieldAddress(temp, Function::usage_counter_offset()), | 2268 __ cmpq(FieldAddress(temp, Function::usage_counter_offset()), |
2286 Immediate(threshold)); | 2269 Immediate(threshold)); |
2287 __ j(GREATER_EQUAL, slow_path->entry_label()); | 2270 __ j(GREATER_EQUAL, slow_path->entry_label()); |
2288 } | 2271 } |
2289 __ Bind(slow_path->exit_label()); | 2272 __ Bind(slow_path->exit_label()); |
2290 } | 2273 } |
2291 | 2274 |
2292 | 2275 |
(...skipping 1426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3719 __ movl(result, Address(RSP, 8)); | 3702 __ movl(result, Address(RSP, 8)); |
3720 break; | 3703 break; |
3721 case MethodRecognizer::kUint32x4GetFlagW: | 3704 case MethodRecognizer::kUint32x4GetFlagW: |
3722 __ movl(result, Address(RSP, 12)); | 3705 __ movl(result, Address(RSP, 12)); |
3723 break; | 3706 break; |
3724 default: UNREACHABLE(); | 3707 default: UNREACHABLE(); |
3725 } | 3708 } |
3726 __ addq(RSP, Immediate(16)); | 3709 __ addq(RSP, Immediate(16)); |
3727 __ testl(result, result); | 3710 __ testl(result, result); |
3728 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); | 3711 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); |
3729 __ LoadObject(result, Bool::False()); | 3712 __ LoadObject(result, Bool::False(), PP); |
3730 __ jmp(&done); | 3713 __ jmp(&done); |
3731 __ Bind(&non_zero); | 3714 __ Bind(&non_zero); |
3732 __ LoadObject(result, Bool::True()); | 3715 __ LoadObject(result, Bool::True(), PP); |
3733 __ Bind(&done); | 3716 __ Bind(&done); |
3734 } | 3717 } |
3735 | 3718 |
3736 | 3719 |
3737 LocationSummary* Uint32x4SelectInstr::MakeLocationSummary() const { | 3720 LocationSummary* Uint32x4SelectInstr::MakeLocationSummary() const { |
3738 const intptr_t kNumInputs = 3; | 3721 const intptr_t kNumInputs = 3; |
3739 const intptr_t kNumTemps = 1; | 3722 const intptr_t kNumTemps = 1; |
3740 LocationSummary* summary = | 3723 LocationSummary* summary = |
3741 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3724 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3742 summary->set_in(0, Location::RequiresFpuRegister()); | 3725 summary->set_in(0, Location::RequiresFpuRegister()); |
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4240 // return double.NAN; | 4223 // return double.NAN; |
4241 // } | 4224 // } |
4242 XmmRegister base = locs()->in(0).fpu_reg(); | 4225 XmmRegister base = locs()->in(0).fpu_reg(); |
4243 XmmRegister exp = locs()->in(1).fpu_reg(); | 4226 XmmRegister exp = locs()->in(1).fpu_reg(); |
4244 XmmRegister result = locs()->out().fpu_reg(); | 4227 XmmRegister result = locs()->out().fpu_reg(); |
4245 Register temp = locs()->temp(0).reg(); | 4228 Register temp = locs()->temp(0).reg(); |
4246 XmmRegister zero_temp = locs()->temp(1).fpu_reg(); | 4229 XmmRegister zero_temp = locs()->temp(1).fpu_reg(); |
4247 | 4230 |
4248 Label check_base_is_one; | 4231 Label check_base_is_one; |
4249 // Check if exponent is 0.0 -> return 1.0; | 4232 // Check if exponent is 0.0 -> return 1.0; |
4250 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0))); | 4233 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0)), PP); |
4251 __ movsd(zero_temp, FieldAddress(temp, Double::value_offset())); | 4234 __ movsd(zero_temp, FieldAddress(temp, Double::value_offset())); |
4252 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1))); | 4235 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1)), PP); |
4253 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 4236 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
4254 // 'result' contains 1.0. | 4237 // 'result' contains 1.0. |
4255 __ comisd(exp, zero_temp); | 4238 __ comisd(exp, zero_temp); |
4256 __ j(PARITY_EVEN, &check_base_is_one, Assembler::kNearJump); // NaN. | 4239 __ j(PARITY_EVEN, &check_base_is_one, Assembler::kNearJump); // NaN. |
4257 __ j(EQUAL, &skip_call, Assembler::kNearJump); // exp is 0, result is 1.0. | 4240 __ j(EQUAL, &skip_call, Assembler::kNearJump); // exp is 0, result is 1.0. |
4258 | 4241 |
4259 Label base_is_nan; | 4242 Label base_is_nan; |
4260 __ Bind(&check_base_is_one); | 4243 __ Bind(&check_base_is_one); |
4261 // Checks if base == 1.0. | 4244 // Checks if base == 1.0. |
4262 __ comisd(base, result); | 4245 __ comisd(base, result); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4340 summary->AddTemp(Location::RequiresRegister()); | 4323 summary->AddTemp(Location::RequiresRegister()); |
4341 } | 4324 } |
4342 return summary; | 4325 return summary; |
4343 } | 4326 } |
4344 | 4327 |
4345 | 4328 |
4346 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4329 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4347 if (IsNullCheck()) { | 4330 if (IsNullCheck()) { |
4348 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 4331 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
4349 kDeoptCheckClass); | 4332 kDeoptCheckClass); |
4350 const Immediate& raw_null = | 4333 __ CompareObject(locs()->in(0).reg(), |
4351 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 4334 Object::Handle()); |
4352 __ cmpq(locs()->in(0).reg(), raw_null); | |
4353 __ j(EQUAL, deopt); | 4335 __ j(EQUAL, deopt); |
4354 return; | 4336 return; |
4355 } | 4337 } |
4356 | 4338 |
4357 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 4339 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
4358 (unary_checks().NumberOfChecks() > 1)); | 4340 (unary_checks().NumberOfChecks() > 1)); |
4359 Register value = locs()->in(0).reg(); | 4341 Register value = locs()->in(0).reg(); |
4360 Register temp = locs()->temp(0).reg(); | 4342 Register temp = locs()->temp(0).reg(); |
4361 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 4343 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
4362 kDeoptCheckClass); | 4344 kDeoptCheckClass); |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4552 __ Bind(compiler->GetJumpLabel(this)); | 4534 __ Bind(compiler->GetJumpLabel(this)); |
4553 if (!compiler->is_optimizing()) { | 4535 if (!compiler->is_optimizing()) { |
4554 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 4536 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
4555 deopt_id_, | 4537 deopt_id_, |
4556 Scanner::kDummyTokenIndex); | 4538 Scanner::kDummyTokenIndex); |
4557 // Add an edge counter. | 4539 // Add an edge counter. |
4558 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); | 4540 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); |
4559 counter.SetAt(0, Smi::Handle(Smi::New(0))); | 4541 counter.SetAt(0, Smi::Handle(Smi::New(0))); |
4560 Label done; | 4542 Label done; |
4561 __ Comment("Edge counter"); | 4543 __ Comment("Edge counter"); |
4562 __ LoadObject(RAX, counter); | 4544 __ LoadObject(RAX, counter, PP); |
4563 __ addq(FieldAddress(RAX, Array::element_offset(0)), | 4545 __ addq(FieldAddress(RAX, Array::element_offset(0)), |
4564 Immediate(Smi::RawValue(1))); | 4546 Immediate(Smi::RawValue(1))); |
4565 __ j(NO_OVERFLOW, &done); | 4547 __ j(NO_OVERFLOW, &done); |
4566 __ movq(FieldAddress(RAX, Array::element_offset(0)), | 4548 __ movq(FieldAddress(RAX, Array::element_offset(0)), |
4567 Immediate(Smi::RawValue(Smi::kMaxValue))); | 4549 Immediate(Smi::RawValue(Smi::kMaxValue))); |
4568 __ Bind(&done); | 4550 __ Bind(&done); |
4569 } | 4551 } |
4570 if (HasParallelMove()) { | 4552 if (HasParallelMove()) { |
4571 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 4553 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
4572 } | 4554 } |
(...skipping 10 matching lines...) Expand all Loading... |
4583 // Add deoptimization descriptor for deoptimizing instructions that may | 4565 // Add deoptimization descriptor for deoptimizing instructions that may |
4584 // be inserted before this instruction. | 4566 // be inserted before this instruction. |
4585 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 4567 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
4586 GetDeoptId(), | 4568 GetDeoptId(), |
4587 0); // No token position. | 4569 0); // No token position. |
4588 // Add an edge counter. | 4570 // Add an edge counter. |
4589 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); | 4571 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); |
4590 counter.SetAt(0, Smi::Handle(Smi::New(0))); | 4572 counter.SetAt(0, Smi::Handle(Smi::New(0))); |
4591 Label done; | 4573 Label done; |
4592 __ Comment("Edge counter"); | 4574 __ Comment("Edge counter"); |
4593 __ LoadObject(RAX, counter); | 4575 __ LoadObject(RAX, counter, PP); |
4594 __ addq(FieldAddress(RAX, Array::element_offset(0)), | 4576 __ addq(FieldAddress(RAX, Array::element_offset(0)), |
4595 Immediate(Smi::RawValue(1))); | 4577 Immediate(Smi::RawValue(1))); |
4596 __ j(NO_OVERFLOW, &done); | 4578 __ j(NO_OVERFLOW, &done); |
4597 __ movq(FieldAddress(RAX, Array::element_offset(0)), | 4579 __ movq(FieldAddress(RAX, Array::element_offset(0)), |
4598 Immediate(Smi::RawValue(Smi::kMaxValue))); | 4580 Immediate(Smi::RawValue(Smi::kMaxValue))); |
4599 __ Bind(&done); | 4581 __ Bind(&done); |
4600 } | 4582 } |
4601 if (HasParallelMove()) { | 4583 if (HasParallelMove()) { |
4602 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 4584 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
4603 } | 4585 } |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4666 // Special code for numbers (compare values instead of references.) | 4648 // Special code for numbers (compare values instead of references.) |
4667 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4649 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4668 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4650 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
4669 Location left = locs()->in(0); | 4651 Location left = locs()->in(0); |
4670 Location right = locs()->in(1); | 4652 Location right = locs()->in(1); |
4671 if (left.IsConstant() && right.IsConstant()) { | 4653 if (left.IsConstant() && right.IsConstant()) { |
4672 // TODO(vegorov): should be eliminated earlier by constant propagation. | 4654 // TODO(vegorov): should be eliminated earlier by constant propagation. |
4673 const bool result = (kind() == Token::kEQ_STRICT) ? | 4655 const bool result = (kind() == Token::kEQ_STRICT) ? |
4674 left.constant().raw() == right.constant().raw() : | 4656 left.constant().raw() == right.constant().raw() : |
4675 left.constant().raw() != right.constant().raw(); | 4657 left.constant().raw() != right.constant().raw(); |
4676 __ LoadObject(locs()->out().reg(), Bool::Get(result)); | 4658 __ LoadObject(locs()->out().reg(), Bool::Get(result), PP); |
4677 return; | 4659 return; |
4678 } | 4660 } |
4679 if (left.IsConstant()) { | 4661 if (left.IsConstant()) { |
4680 compiler->EmitEqualityRegConstCompare(right.reg(), | 4662 compiler->EmitEqualityRegConstCompare(right.reg(), |
4681 left.constant(), | 4663 left.constant(), |
4682 needs_number_check(), | 4664 needs_number_check(), |
4683 token_pos()); | 4665 token_pos()); |
4684 } else if (right.IsConstant()) { | 4666 } else if (right.IsConstant()) { |
4685 compiler->EmitEqualityRegConstCompare(left.reg(), | 4667 compiler->EmitEqualityRegConstCompare(left.reg(), |
4686 right.constant(), | 4668 right.constant(), |
4687 needs_number_check(), | 4669 needs_number_check(), |
4688 token_pos()); | 4670 token_pos()); |
4689 } else { | 4671 } else { |
4690 compiler->EmitEqualityRegRegCompare(left.reg(), | 4672 compiler->EmitEqualityRegRegCompare(left.reg(), |
4691 right.reg(), | 4673 right.reg(), |
4692 needs_number_check(), | 4674 needs_number_check(), |
4693 token_pos()); | 4675 token_pos()); |
4694 } | 4676 } |
4695 | 4677 |
4696 Register result = locs()->out().reg(); | 4678 Register result = locs()->out().reg(); |
4697 Label load_true, done; | 4679 Label load_true, done; |
4698 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 4680 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
4699 __ j(true_condition, &load_true, Assembler::kNearJump); | 4681 __ j(true_condition, &load_true, Assembler::kNearJump); |
4700 __ LoadObject(result, Bool::False()); | 4682 __ LoadObject(result, Bool::False(), PP); |
4701 __ jmp(&done, Assembler::kNearJump); | 4683 __ jmp(&done, Assembler::kNearJump); |
4702 __ Bind(&load_true); | 4684 __ Bind(&load_true); |
4703 __ LoadObject(result, Bool::True()); | 4685 __ LoadObject(result, Bool::True(), PP); |
4704 __ Bind(&done); | 4686 __ Bind(&done); |
4705 } | 4687 } |
4706 | 4688 |
4707 | 4689 |
4708 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 4690 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
4709 BranchInstr* branch) { | 4691 BranchInstr* branch) { |
4710 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4692 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
4711 Location left = locs()->in(0); | 4693 Location left = locs()->in(0); |
4712 Location right = locs()->in(1); | 4694 Location right = locs()->in(1); |
4713 if (left.IsConstant() && right.IsConstant()) { | 4695 if (left.IsConstant() && right.IsConstant()) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4752 | 4734 |
4753 | 4735 |
4754 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4736 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4755 // The arguments to the stub include the closure, as does the arguments | 4737 // The arguments to the stub include the closure, as does the arguments |
4756 // descriptor. | 4738 // descriptor. |
4757 Register temp_reg = locs()->temp(0).reg(); | 4739 Register temp_reg = locs()->temp(0).reg(); |
4758 int argument_count = ArgumentCount(); | 4740 int argument_count = ArgumentCount(); |
4759 const Array& arguments_descriptor = | 4741 const Array& arguments_descriptor = |
4760 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 4742 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
4761 argument_names())); | 4743 argument_names())); |
4762 __ LoadObject(temp_reg, arguments_descriptor); | 4744 __ LoadObject(temp_reg, arguments_descriptor, PP); |
4763 ASSERT(temp_reg == R10); | 4745 ASSERT(temp_reg == R10); |
4764 compiler->GenerateDartCall(deopt_id(), | 4746 compiler->GenerateDartCall(deopt_id(), |
4765 token_pos(), | 4747 token_pos(), |
4766 &StubCode::CallClosureFunctionLabel(), | 4748 &StubCode::CallClosureFunctionLabel(), |
4767 PcDescriptors::kClosureCall, | 4749 PcDescriptors::kClosureCall, |
4768 locs()); | 4750 locs()); |
4769 __ Drop(argument_count); | 4751 __ Drop(argument_count); |
4770 } | 4752 } |
4771 | 4753 |
4772 | 4754 |
4773 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { | 4755 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { |
4774 return LocationSummary::Make(1, | 4756 return LocationSummary::Make(1, |
4775 Location::RequiresRegister(), | 4757 Location::RequiresRegister(), |
4776 LocationSummary::kNoCall); | 4758 LocationSummary::kNoCall); |
4777 } | 4759 } |
4778 | 4760 |
4779 | 4761 |
4780 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4762 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4781 Register value = locs()->in(0).reg(); | 4763 Register value = locs()->in(0).reg(); |
4782 Register result = locs()->out().reg(); | 4764 Register result = locs()->out().reg(); |
4783 | 4765 |
4784 Label done; | 4766 Label done; |
4785 __ LoadObject(result, Bool::True()); | 4767 __ LoadObject(result, Bool::True(), PP); |
4786 __ CompareRegisters(result, value); | 4768 __ CompareRegisters(result, value); |
4787 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 4769 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
4788 __ LoadObject(result, Bool::False()); | 4770 __ LoadObject(result, Bool::False(), PP); |
4789 __ Bind(&done); | 4771 __ Bind(&done); |
4790 } | 4772 } |
4791 | 4773 |
4792 | 4774 |
4793 LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const { | 4775 LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const { |
4794 const intptr_t kNumInputs = 2; | 4776 const intptr_t kNumInputs = 2; |
4795 const intptr_t kNumTemps = 0; | 4777 const intptr_t kNumTemps = 0; |
4796 LocationSummary* locs = | 4778 LocationSummary* locs = |
4797 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4779 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4798 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 4780 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4848 PcDescriptors::kOther, | 4830 PcDescriptors::kOther, |
4849 locs()); | 4831 locs()); |
4850 __ Drop(2); // Discard type arguments and receiver. | 4832 __ Drop(2); // Discard type arguments and receiver. |
4851 } | 4833 } |
4852 | 4834 |
4853 } // namespace dart | 4835 } // namespace dart |
4854 | 4836 |
4855 #undef __ | 4837 #undef __ |
4856 | 4838 |
4857 #endif // defined TARGET_ARCH_X64 | 4839 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |