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(); | 99 __ LeaveFrameWithPP(); |
100 __ ret(); | 100 __ ret(); |
101 | 101 |
102 // Generate 8 bytes of NOPs so that the debugger can patch the | 102 // Generate 4 bytes of NOPs so that the debugger can patch the |
Florian Schneider
2013/09/05 10:57:45
How is 4 computed? The number of nops should depen
zra
2013/09/05 20:29:26
Moved this sequence into the Assembler function Re
| |
103 // return pattern with a call to the debug stub. | 103 // return pattern with a call to the debug stub. |
104 // Note that the nop(8) byte pattern is not recognized by the debugger. | 104 // Note that the nop(8) byte pattern is not recognized by the debugger. |
105 __ nop(1); | 105 __ nop(1); |
106 __ nop(1); | 106 __ nop(1); |
107 __ nop(1); | 107 __ nop(1); |
108 __ nop(1); | 108 __ nop(1); |
109 __ nop(1); | |
110 __ nop(1); | |
111 __ nop(1); | |
112 __ nop(1); | |
113 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 109 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
114 Isolate::kNoDeoptId, | 110 Isolate::kNoDeoptId, |
115 token_pos()); | 111 token_pos()); |
116 } | 112 } |
117 | 113 |
118 | 114 |
119 static Condition NegateCondition(Condition condition) { | 115 static Condition NegateCondition(Condition condition) { |
120 switch (condition) { | 116 switch (condition) { |
121 case EQUAL: return NOT_EQUAL; | 117 case EQUAL: return NOT_EQUAL; |
122 case NOT_EQUAL: return EQUAL; | 118 case NOT_EQUAL: return EQUAL; |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
308 return LocationSummary::Make(kNumInputs, | 304 return LocationSummary::Make(kNumInputs, |
309 Location::RequiresRegister(), | 305 Location::RequiresRegister(), |
310 LocationSummary::kNoCall); | 306 LocationSummary::kNoCall); |
311 } | 307 } |
312 | 308 |
313 | 309 |
314 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 310 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
315 // The register allocator drops constant definitions that have no uses. | 311 // The register allocator drops constant definitions that have no uses. |
316 if (!locs()->out().IsInvalid()) { | 312 if (!locs()->out().IsInvalid()) { |
317 Register result = locs()->out().reg(); | 313 Register result = locs()->out().reg(); |
318 __ LoadObject(result, value()); | 314 __ LoadObjectFromPool(result, value(), PP); |
Florian Schneider
2013/09/05 10:57:45
This should just be
LoadObject(result, value())
zra
2013/09/05 20:29:26
Done.
| |
319 } | 315 } |
320 } | 316 } |
321 | 317 |
322 | 318 |
323 LocationSummary* AssertAssignableInstr::MakeLocationSummary() const { | 319 LocationSummary* AssertAssignableInstr::MakeLocationSummary() const { |
324 const intptr_t kNumInputs = 3; | 320 const intptr_t kNumInputs = 3; |
325 const intptr_t kNumTemps = 0; | 321 const intptr_t kNumTemps = 0; |
326 LocationSummary* summary = | 322 LocationSummary* summary = |
327 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 323 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
328 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. | 324 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) { | 454 const ICData& original_ic_data) { |
459 if (!compiler->is_optimizing()) { | 455 if (!compiler->is_optimizing()) { |
460 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 456 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
461 deopt_id, | 457 deopt_id, |
462 token_pos); | 458 token_pos); |
463 } | 459 } |
464 const int kNumberOfArguments = 2; | 460 const int kNumberOfArguments = 2; |
465 const Array& kNoArgumentNames = Object::null_array(); | 461 const Array& kNoArgumentNames = Object::null_array(); |
466 const int kNumArgumentsChecked = 2; | 462 const int kNumArgumentsChecked = 2; |
467 | 463 |
468 const Immediate& raw_null = | |
469 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
470 Label check_identity; | 464 Label check_identity; |
471 __ cmpq(Address(RSP, 0 * kWordSize), raw_null); | 465 __ LoadObjectFromPool(TMP, Object::Handle(), PP); |
466 __ cmpq(Address(RSP, 0 * kWordSize), TMP); | |
472 __ j(EQUAL, &check_identity); | 467 __ j(EQUAL, &check_identity); |
473 __ cmpq(Address(RSP, 1 * kWordSize), raw_null); | 468 __ cmpq(Address(RSP, 1 * kWordSize), TMP); |
474 __ j(EQUAL, &check_identity); | 469 __ j(EQUAL, &check_identity); |
475 | 470 |
476 ICData& equality_ic_data = ICData::ZoneHandle(original_ic_data.raw()); | 471 ICData& equality_ic_data = ICData::ZoneHandle(original_ic_data.raw()); |
477 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { | 472 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { |
478 ASSERT(!original_ic_data.IsNull()); | 473 ASSERT(!original_ic_data.IsNull()); |
479 if (original_ic_data.NumberOfChecks() == 0) { | 474 if (original_ic_data.NumberOfChecks() == 0) { |
480 // IC call for reoptimization populates original ICData. | 475 // IC call for reoptimization populates original ICData. |
481 equality_ic_data = original_ic_data.raw(); | 476 equality_ic_data = original_ic_data.raw(); |
482 } else { | 477 } else { |
483 // Megamorphic call. | 478 // Megamorphic call. |
(...skipping 20 matching lines...) Expand all Loading... | |
504 | 499 |
505 __ Bind(&check_identity); | 500 __ Bind(&check_identity); |
506 Label equality_done; | 501 Label equality_done; |
507 if (compiler->is_optimizing()) { | 502 if (compiler->is_optimizing()) { |
508 // No need to update IC data. | 503 // No need to update IC data. |
509 Label is_true; | 504 Label is_true; |
510 __ popq(RAX); | 505 __ popq(RAX); |
511 __ popq(RDX); | 506 __ popq(RDX); |
512 __ cmpq(RAX, RDX); | 507 __ cmpq(RAX, RDX); |
513 __ j(EQUAL, &is_true); | 508 __ j(EQUAL, &is_true); |
514 __ LoadObject(RAX, Bool::Get(kind != Token::kEQ)); | 509 __ LoadObjectFromPool(RAX, Bool::Get(kind != Token::kEQ), PP); |
Florian Schneider
2013/09/05 10:57:45
If you require an extra parameter there is no need
zra
2013/09/05 20:29:26
Using LoadObject everywhere the pool pointer is PP
| |
515 __ jmp(&equality_done); | 510 __ jmp(&equality_done); |
516 __ Bind(&is_true); | 511 __ Bind(&is_true); |
517 __ LoadObject(RAX, Bool::Get(kind == Token::kEQ)); | 512 __ LoadObjectFromPool(RAX, Bool::Get(kind == Token::kEQ), PP); |
518 if (kind == Token::kNE) { | 513 if (kind == Token::kNE) { |
519 // Skip not-equal result conversion. | 514 // Skip not-equal result conversion. |
520 __ jmp(&equality_done); | 515 __ jmp(&equality_done); |
521 } | 516 } |
522 } else { | 517 } else { |
523 // Call stub, load IC data in register. The stub will update ICData if | 518 // Call stub, load IC data in register. The stub will update ICData if |
524 // necessary. | 519 // necessary. |
525 Register ic_data_reg = locs->temp(0).reg(); | 520 Register ic_data_reg = locs->temp(0).reg(); |
526 ASSERT(ic_data_reg == RBX); // Stub depends on it. | 521 ASSERT(ic_data_reg == RBX); // Stub depends on it. |
527 __ LoadObject(ic_data_reg, equality_ic_data); | 522 __ LoadObject(ic_data_reg, equality_ic_data); |
Florian Schneider
2013/09/05 10:57:45
What about this LoadObject?
zra
2013/09/05 20:29:26
Done.
| |
528 compiler->GenerateCall(token_pos, | 523 compiler->GenerateCall(token_pos, |
529 &StubCode::EqualityWithNullArgLabel(), | 524 &StubCode::EqualityWithNullArgLabel(), |
530 PcDescriptors::kRuntimeCall, | 525 PcDescriptors::kRuntimeCall, |
531 locs); | 526 locs); |
532 __ Drop(2); | 527 __ Drop(2); |
533 } | 528 } |
534 __ Bind(&check_ne); | 529 __ Bind(&check_ne); |
535 if (kind == Token::kNE) { | 530 if (kind == Token::kNE) { |
536 Label true_label, done; | 531 Label true_label, done; |
537 // Negate the condition: true label returns false and vice versa. | 532 // Negate the condition: true label returns false and vice versa. |
538 __ CompareObject(RAX, Bool::True()); | 533 __ CompareObject(RAX, Bool::True()); |
539 __ j(EQUAL, &true_label, Assembler::kNearJump); | 534 __ j(EQUAL, &true_label, Assembler::kNearJump); |
540 __ LoadObject(RAX, Bool::True()); | 535 __ LoadObjectFromPool(RAX, Bool::True(), PP); |
541 __ jmp(&done, Assembler::kNearJump); | 536 __ jmp(&done, Assembler::kNearJump); |
542 __ Bind(&true_label); | 537 __ Bind(&true_label); |
543 __ LoadObject(RAX, Bool::False()); | 538 __ LoadObjectFromPool(RAX, Bool::False(), PP); |
544 __ Bind(&done); | 539 __ Bind(&done); |
545 } | 540 } |
546 __ Bind(&equality_done); | 541 __ Bind(&equality_done); |
547 } | 542 } |
548 | 543 |
549 | 544 |
550 static void LoadValueCid(FlowGraphCompiler* compiler, | 545 static void LoadValueCid(FlowGraphCompiler* compiler, |
551 Register value_cid_reg, | 546 Register value_cid_reg, |
552 Register value_reg, | 547 Register value_reg, |
553 Label* value_is_smi = NULL) { | 548 Label* value_is_smi = NULL) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
603 // Object.== is same as ===. | 598 // Object.== is same as ===. |
604 __ Drop(2); | 599 __ Drop(2); |
605 __ cmpq(left, right); | 600 __ cmpq(left, right); |
606 if (branch != NULL) { | 601 if (branch != NULL) { |
607 branch->EmitBranchOnCondition(compiler, cond); | 602 branch->EmitBranchOnCondition(compiler, cond); |
608 } else { | 603 } else { |
609 // This case should be rare. | 604 // This case should be rare. |
610 Register result = locs->out().reg(); | 605 Register result = locs->out().reg(); |
611 Label load_true; | 606 Label load_true; |
612 __ j(cond, &load_true, Assembler::kNearJump); | 607 __ j(cond, &load_true, Assembler::kNearJump); |
613 __ LoadObject(result, Bool::False()); | 608 __ LoadObjectFromPool(result, Bool::False(), PP); |
614 __ jmp(&done); | 609 __ jmp(&done); |
615 __ Bind(&load_true); | 610 __ Bind(&load_true); |
616 __ LoadObject(result, Bool::True()); | 611 __ LoadObjectFromPool(result, Bool::True(), PP); |
617 } | 612 } |
618 } else { | 613 } else { |
619 const int kNumberOfArguments = 2; | 614 const int kNumberOfArguments = 2; |
620 const Array& kNoArgumentNames = Object::null_array(); | 615 const Array& kNoArgumentNames = Object::null_array(); |
621 compiler->GenerateStaticCall(deopt_id, | 616 compiler->GenerateStaticCall(deopt_id, |
622 token_pos, | 617 token_pos, |
623 target, | 618 target, |
624 kNumberOfArguments, | 619 kNumberOfArguments, |
625 kNoArgumentNames, | 620 kNoArgumentNames, |
626 locs); | 621 locs); |
627 if (branch == NULL) { | 622 if (branch == NULL) { |
628 if (kind == Token::kNE) { | 623 if (kind == Token::kNE) { |
629 Label false_label; | 624 Label false_label; |
630 __ CompareObject(RAX, Bool::True()); | 625 __ CompareObject(RAX, Bool::True()); |
631 __ j(EQUAL, &false_label, Assembler::kNearJump); | 626 __ j(EQUAL, &false_label, Assembler::kNearJump); |
632 __ LoadObject(RAX, Bool::True()); | 627 __ LoadObjectFromPool(RAX, Bool::True(), PP); |
633 __ jmp(&done); | 628 __ jmp(&done); |
634 __ Bind(&false_label); | 629 __ Bind(&false_label); |
635 __ LoadObject(RAX, Bool::False()); | 630 __ LoadObjectFromPool(RAX, Bool::False(), PP); |
636 } | 631 } |
637 } else { | 632 } else { |
638 if (branch->is_checked()) { | 633 if (branch->is_checked()) { |
639 EmitAssertBoolean(RAX, token_pos, deopt_id, locs, compiler); | 634 EmitAssertBoolean(RAX, token_pos, deopt_id, locs, compiler); |
640 } | 635 } |
641 __ CompareObject(RAX, Bool::True()); | 636 __ CompareObject(RAX, Bool::True()); |
642 branch->EmitBranchOnCondition(compiler, cond); | 637 branch->EmitBranchOnCondition(compiler, cond); |
643 } | 638 } |
644 } | 639 } |
645 if (i < len - 1) { | 640 if (i < len - 1) { |
(...skipping 13 matching lines...) Expand all Loading... | |
659 BranchInstr* branch, | 654 BranchInstr* branch, |
660 intptr_t deopt_id) { | 655 intptr_t deopt_id) { |
661 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 656 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
662 Register left = locs.in(0).reg(); | 657 Register left = locs.in(0).reg(); |
663 Register right = locs.in(1).reg(); | 658 Register right = locs.in(1).reg(); |
664 Register temp = locs.temp(0).reg(); | 659 Register temp = locs.temp(0).reg(); |
665 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); | 660 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); |
666 __ testq(left, Immediate(kSmiTagMask)); | 661 __ testq(left, Immediate(kSmiTagMask)); |
667 __ j(ZERO, deopt); | 662 __ j(ZERO, deopt); |
668 // 'left' is not Smi. | 663 // 'left' is not Smi. |
669 const Immediate& raw_null = | 664 |
670 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
671 Label identity_compare; | 665 Label identity_compare; |
672 __ cmpq(right, raw_null); | 666 __ CompareObject(right, Object::Handle()); |
673 __ j(EQUAL, &identity_compare); | 667 __ j(EQUAL, &identity_compare); |
674 __ cmpq(left, raw_null); | 668 __ CompareObject(left, Object::Handle()); |
675 __ j(EQUAL, &identity_compare); | 669 __ j(EQUAL, &identity_compare); |
676 | 670 |
677 __ LoadClassId(temp, left); | 671 __ LoadClassId(temp, left); |
678 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); | 672 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); |
679 const intptr_t len = ic_data.NumberOfChecks(); | 673 const intptr_t len = ic_data.NumberOfChecks(); |
680 for (intptr_t i = 0; i < len; i++) { | 674 for (intptr_t i = 0; i < len; i++) { |
681 __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); | 675 __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); |
682 if (i == (len - 1)) { | 676 if (i == (len - 1)) { |
683 __ j(NOT_EQUAL, deopt); | 677 __ j(NOT_EQUAL, deopt); |
684 } else { | 678 } else { |
685 __ j(EQUAL, &identity_compare); | 679 __ j(EQUAL, &identity_compare); |
686 } | 680 } |
687 } | 681 } |
688 __ Bind(&identity_compare); | 682 __ Bind(&identity_compare); |
689 __ cmpq(left, right); | 683 __ cmpq(left, right); |
690 if (branch == NULL) { | 684 if (branch == NULL) { |
691 Label done, is_equal; | 685 Label done, is_equal; |
692 Register result = locs.out().reg(); | 686 Register result = locs.out().reg(); |
693 __ j(EQUAL, &is_equal, Assembler::kNearJump); | 687 __ j(EQUAL, &is_equal, Assembler::kNearJump); |
694 // Not equal. | 688 // Not equal. |
695 __ LoadObject(result, Bool::Get(kind != Token::kEQ)); | 689 __ LoadObjectFromPool(result, Bool::Get(kind != Token::kEQ), PP); |
696 __ jmp(&done, Assembler::kNearJump); | 690 __ jmp(&done, Assembler::kNearJump); |
697 __ Bind(&is_equal); | 691 __ Bind(&is_equal); |
698 __ LoadObject(result, Bool::Get(kind == Token::kEQ)); | 692 __ LoadObjectFromPool(result, Bool::Get(kind == Token::kEQ), PP); |
699 __ Bind(&done); | 693 __ Bind(&done); |
700 } else { | 694 } else { |
701 Condition cond = TokenKindToSmiCondition(kind); | 695 Condition cond = TokenKindToSmiCondition(kind); |
702 branch->EmitBranchOnCondition(compiler, cond); | 696 branch->EmitBranchOnCondition(compiler, cond); |
703 } | 697 } |
704 } | 698 } |
705 | 699 |
706 | 700 |
707 // First test if receiver is NULL, in which case === is applied. | 701 // First test if receiver is NULL, in which case === is applied. |
708 // If type feedback was provided (lists of <class-id, target>), do a | 702 // If type feedback was provided (lists of <class-id, target>), do a |
709 // type by type check (either === or static call to the operator. | 703 // type by type check (either === or static call to the operator. |
710 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, | 704 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
711 LocationSummary* locs, | 705 LocationSummary* locs, |
712 Token::Kind kind, | 706 Token::Kind kind, |
713 BranchInstr* branch, | 707 BranchInstr* branch, |
714 const ICData& ic_data, | 708 const ICData& ic_data, |
715 intptr_t deopt_id, | 709 intptr_t deopt_id, |
716 intptr_t token_pos) { | 710 intptr_t token_pos) { |
717 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 711 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
718 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 712 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
719 Register left = locs->in(0).reg(); | 713 Register left = locs->in(0).reg(); |
720 Register right = locs->in(1).reg(); | 714 Register right = locs->in(1).reg(); |
721 const Immediate& raw_null = | 715 |
722 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
723 Label done, identity_compare, non_null_compare; | 716 Label done, identity_compare, non_null_compare; |
724 __ cmpq(right, raw_null); | 717 __ CompareObject(right, Object::Handle()); |
725 __ j(EQUAL, &identity_compare, Assembler::kNearJump); | 718 __ j(EQUAL, &identity_compare, Assembler::kNearJump); |
726 __ cmpq(left, raw_null); | 719 __ CompareObject(left, Object::Handle()); |
727 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); | 720 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); |
728 // Comparison with NULL is "===". | 721 // Comparison with NULL is "===". |
729 __ Bind(&identity_compare); | 722 __ Bind(&identity_compare); |
730 __ cmpq(left, right); | 723 __ cmpq(left, right); |
731 Condition cond = TokenKindToSmiCondition(kind); | 724 Condition cond = TokenKindToSmiCondition(kind); |
732 if (branch != NULL) { | 725 if (branch != NULL) { |
733 branch->EmitBranchOnCondition(compiler, cond); | 726 branch->EmitBranchOnCondition(compiler, cond); |
734 } else { | 727 } else { |
735 Register result = locs->out().reg(); | 728 Register result = locs->out().reg(); |
736 Label load_true; | 729 Label load_true; |
737 __ j(cond, &load_true, Assembler::kNearJump); | 730 __ j(cond, &load_true, Assembler::kNearJump); |
738 __ LoadObject(result, Bool::False()); | 731 __ LoadObjectFromPool(result, Bool::False(), PP); |
739 __ jmp(&done); | 732 __ jmp(&done); |
740 __ Bind(&load_true); | 733 __ Bind(&load_true); |
741 __ LoadObject(result, Bool::True()); | 734 __ LoadObjectFromPool(result, Bool::True(), PP); |
742 } | 735 } |
743 __ jmp(&done); | 736 __ jmp(&done); |
744 __ Bind(&non_null_compare); // Receiver is not null. | 737 __ Bind(&non_null_compare); // Receiver is not null. |
745 __ pushq(left); | 738 __ pushq(left); |
746 __ pushq(right); | 739 __ pushq(right); |
747 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 740 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
748 deopt_id, token_pos); | 741 deopt_id, token_pos); |
749 __ Bind(&done); | 742 __ Bind(&done); |
750 } | 743 } |
751 | 744 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
789 } else { | 782 } else { |
790 __ cmpq(left.reg(), right.reg()); | 783 __ cmpq(left.reg(), right.reg()); |
791 } | 784 } |
792 | 785 |
793 if (branch != NULL) { | 786 if (branch != NULL) { |
794 branch->EmitBranchOnCondition(compiler, true_condition); | 787 branch->EmitBranchOnCondition(compiler, true_condition); |
795 } else { | 788 } else { |
796 Register result = locs.out().reg(); | 789 Register result = locs.out().reg(); |
797 Label done, is_true; | 790 Label done, is_true; |
798 __ j(true_condition, &is_true); | 791 __ j(true_condition, &is_true); |
799 __ LoadObject(result, Bool::False()); | 792 __ LoadObjectFromPool(result, Bool::False(), PP); |
800 __ jmp(&done); | 793 __ jmp(&done); |
801 __ Bind(&is_true); | 794 __ Bind(&is_true); |
802 __ LoadObject(result, Bool::True()); | 795 __ LoadObjectFromPool(result, Bool::True(), PP); |
803 __ Bind(&done); | 796 __ Bind(&done); |
804 } | 797 } |
805 } | 798 } |
806 | 799 |
807 | 800 |
808 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 801 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
809 switch (kind) { | 802 switch (kind) { |
810 case Token::kEQ: return EQUAL; | 803 case Token::kEQ: return EQUAL; |
811 case Token::kNE: return NOT_EQUAL; | 804 case Token::kNE: return NOT_EQUAL; |
812 case Token::kLT: return BELOW; | 805 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)) { | 1513 if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) { |
1521 if (!compiler->is_optimizing() && (field_reg == kNoRegister)) { | 1514 if (!compiler->is_optimizing() && (field_reg == kNoRegister)) { |
1522 // Currently we can't have different location summaries for optimized | 1515 // Currently we can't have different location summaries for optimized |
1523 // and non-optimized code. So instead we manually pick up a register | 1516 // 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 | 1517 // that is known to be free because we know how non-optimizing compiler |
1525 // allocates registers. | 1518 // allocates registers. |
1526 field_reg = RBX; | 1519 field_reg = RBX; |
1527 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg)); | 1520 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg)); |
1528 } | 1521 } |
1529 | 1522 |
1530 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); | 1523 __ LoadObjectFromPool(field_reg, Field::ZoneHandle(field().raw()), PP); |
1531 | 1524 |
1532 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); | 1525 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); |
1533 FieldAddress field_nullability_operand( | 1526 FieldAddress field_nullability_operand( |
1534 field_reg, Field::is_nullable_offset()); | 1527 field_reg, Field::is_nullable_offset()); |
1535 FieldAddress field_length_operand( | 1528 FieldAddress field_length_operand( |
1536 field_reg, Field::guarded_list_length_offset()); | 1529 field_reg, Field::guarded_list_length_offset()); |
1537 | 1530 |
1538 if (value_cid == kDynamicCid) { | 1531 if (value_cid == kDynamicCid) { |
1539 if (value_cid_reg == kNoRegister) { | 1532 if (value_cid_reg == kNoRegister) { |
1540 ASSERT(!compiler->is_optimizing()); | 1533 ASSERT(!compiler->is_optimizing()); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1666 } else { | 1659 } else { |
1667 __ movq(field_length_operand, Immediate(Field::kNoFixedLength)); | 1660 __ movq(field_length_operand, Immediate(Field::kNoFixedLength)); |
1668 } | 1661 } |
1669 } | 1662 } |
1670 | 1663 |
1671 if (!ok_is_fall_through) { | 1664 if (!ok_is_fall_through) { |
1672 __ jmp(&ok); | 1665 __ jmp(&ok); |
1673 } | 1666 } |
1674 } else { | 1667 } else { |
1675 if (field_reg != kNoRegister) { | 1668 if (field_reg != kNoRegister) { |
1676 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); | 1669 __ LoadObjectFromPool(field_reg, Field::ZoneHandle(field().raw()), PP); |
1677 } | 1670 } |
1678 | 1671 |
1679 if (value_cid == kDynamicCid) { | 1672 if (value_cid == kDynamicCid) { |
1680 // Field's guarded class id is fixed but value's class id is not known. | 1673 // Field's guarded class id is fixed but value's class id is not known. |
1681 __ testq(value_reg, Immediate(kSmiTagMask)); | 1674 __ testq(value_reg, Immediate(kSmiTagMask)); |
1682 | 1675 |
1683 if (field_cid != kSmiCid) { | 1676 if (field_cid != kSmiCid) { |
1684 __ j(ZERO, fail); | 1677 __ j(ZERO, fail); |
1685 __ LoadClassId(value_cid_reg, value_reg); | 1678 __ LoadClassId(value_cid_reg, value_reg); |
1686 __ cmpq(value_cid_reg, Immediate(field_cid)); | 1679 __ cmpq(value_cid_reg, Immediate(field_cid)); |
(...skipping 15 matching lines...) Expand all Loading... | |
1702 } else if (RawObject::IsTypedDataClassId(field_cid)) { | 1695 } else if (RawObject::IsTypedDataClassId(field_cid)) { |
1703 // Destroy value_cid_reg (safe because we are finished with it). | 1696 // Destroy value_cid_reg (safe because we are finished with it). |
1704 __ movq(value_cid_reg, | 1697 __ movq(value_cid_reg, |
1705 FieldAddress(value_reg, TypedData::length_offset())); | 1698 FieldAddress(value_reg, TypedData::length_offset())); |
1706 } | 1699 } |
1707 __ cmpq(value_cid_reg, field_length_operand); | 1700 __ cmpq(value_cid_reg, field_length_operand); |
1708 } | 1701 } |
1709 | 1702 |
1710 if (field().is_nullable() && (field_cid != kNullCid)) { | 1703 if (field().is_nullable() && (field_cid != kNullCid)) { |
1711 __ j(EQUAL, &ok); | 1704 __ j(EQUAL, &ok); |
1712 const Immediate& raw_null = | 1705 __ CompareObject(value_reg, Object::Handle()); |
1713 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
1714 __ cmpq(value_reg, raw_null); | |
1715 } | 1706 } |
1716 | 1707 |
1717 if (ok_is_fall_through) { | 1708 if (ok_is_fall_through) { |
1718 __ j(NOT_EQUAL, fail); | 1709 __ j(NOT_EQUAL, fail); |
1719 } else { | 1710 } else { |
1720 __ j(EQUAL, &ok); | 1711 __ j(EQUAL, &ok); |
1721 } | 1712 } |
1722 } else { | 1713 } else { |
1723 // Both value's and field's class id is known. | 1714 // Both value's and field's class id is known. |
1724 if ((value_cid != field_cid) && (value_cid != nullability)) { | 1715 if ((value_cid != field_cid) && (value_cid != nullability)) { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1829 : Location::RequiresRegister()); | 1820 : Location::RequiresRegister()); |
1830 locs->set_temp(0, Location::RequiresRegister()); | 1821 locs->set_temp(0, Location::RequiresRegister()); |
1831 return locs; | 1822 return locs; |
1832 } | 1823 } |
1833 | 1824 |
1834 | 1825 |
1835 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1826 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1836 Register value = locs()->in(0).reg(); | 1827 Register value = locs()->in(0).reg(); |
1837 Register temp = locs()->temp(0).reg(); | 1828 Register temp = locs()->temp(0).reg(); |
1838 | 1829 |
1839 __ LoadObject(temp, field()); | 1830 __ LoadObjectFromPool(temp, field(), PP); |
1840 if (this->value()->NeedsStoreBuffer()) { | 1831 if (this->value()->NeedsStoreBuffer()) { |
1841 __ StoreIntoObject(temp, | 1832 __ StoreIntoObject(temp, |
1842 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi()); | 1833 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi()); |
1843 } else { | 1834 } else { |
1844 __ StoreIntoObjectNoBarrier( | 1835 __ StoreIntoObjectNoBarrier( |
1845 temp, FieldAddress(temp, Field::value_offset()), value); | 1836 temp, FieldAddress(temp, Field::value_offset()), value); |
1846 } | 1837 } |
1847 } | 1838 } |
1848 | 1839 |
1849 | 1840 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1983 // (or null). | 1974 // (or null). |
1984 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 1975 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
1985 !type_arguments().CanShareInstantiatorTypeArguments( | 1976 !type_arguments().CanShareInstantiatorTypeArguments( |
1986 instantiator_class())); | 1977 instantiator_class())); |
1987 // If the instantiator is null and if the type argument vector | 1978 // If the instantiator is null and if the type argument vector |
1988 // instantiated from null becomes a vector of dynamic, then use null as | 1979 // instantiated from null becomes a vector of dynamic, then use null as |
1989 // the type arguments. | 1980 // the type arguments. |
1990 Label type_arguments_instantiated; | 1981 Label type_arguments_instantiated; |
1991 const intptr_t len = type_arguments().Length(); | 1982 const intptr_t len = type_arguments().Length(); |
1992 if (type_arguments().IsRawInstantiatedRaw(len)) { | 1983 if (type_arguments().IsRawInstantiatedRaw(len)) { |
1993 const Immediate& raw_null = | 1984 __ CompareObject(instantiator_reg, Object::Handle()); |
1994 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
1995 __ cmpq(instantiator_reg, raw_null); | |
1996 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1985 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1997 } | 1986 } |
1998 // Instantiate non-null type arguments. | 1987 // Instantiate non-null type arguments. |
1999 // A runtime call to instantiate the type arguments is required. | 1988 // A runtime call to instantiate the type arguments is required. |
2000 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1989 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
2001 __ PushObject(type_arguments()); | 1990 __ PushObject(type_arguments()); |
2002 __ pushq(instantiator_reg); // Push instantiator type arguments. | 1991 __ pushq(instantiator_reg); // Push instantiator type arguments. |
2003 compiler->GenerateCallRuntime(token_pos(), | 1992 compiler->GenerateCallRuntime(token_pos(), |
2004 deopt_id(), | 1993 deopt_id(), |
2005 kInstantiateTypeArgumentsRuntimeEntry, | 1994 kInstantiateTypeArgumentsRuntimeEntry, |
(...skipping 27 matching lines...) Expand all Loading... | |
2033 // instantiator_reg is the instantiator type argument vector, i.e. an | 2022 // instantiator_reg is the instantiator type argument vector, i.e. an |
2034 // AbstractTypeArguments object (or null). | 2023 // AbstractTypeArguments object (or null). |
2035 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 2024 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
2036 !type_arguments().CanShareInstantiatorTypeArguments( | 2025 !type_arguments().CanShareInstantiatorTypeArguments( |
2037 instantiator_class())); | 2026 instantiator_class())); |
2038 // If the instantiator is null and if the type argument vector | 2027 // If the instantiator is null and if the type argument vector |
2039 // instantiated from null becomes a vector of dynamic, then use null as | 2028 // instantiated from null becomes a vector of dynamic, then use null as |
2040 // the type arguments. | 2029 // the type arguments. |
2041 Label type_arguments_instantiated; | 2030 Label type_arguments_instantiated; |
2042 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); | 2031 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); |
2043 const Immediate& raw_null = | 2032 |
2044 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 2033 __ CompareObject(instantiator_reg, Object::Handle()); |
2045 __ cmpq(instantiator_reg, raw_null); | |
2046 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2034 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
2047 // Instantiate non-null type arguments. | 2035 // Instantiate non-null type arguments. |
2048 // In the non-factory case, we rely on the allocation stub to | 2036 // In the non-factory case, we rely on the allocation stub to |
2049 // instantiate the type arguments. | 2037 // instantiate the type arguments. |
2050 __ LoadObject(result_reg, type_arguments()); | 2038 __ LoadObjectFromPool(result_reg, type_arguments(), PP); |
2051 // result_reg: uninstantiated type arguments. | 2039 // result_reg: uninstantiated type arguments. |
2052 | 2040 |
2053 __ Bind(&type_arguments_instantiated); | 2041 __ Bind(&type_arguments_instantiated); |
2054 // result_reg: uninstantiated or instantiated type arguments. | 2042 // result_reg: uninstantiated or instantiated type arguments. |
2055 } | 2043 } |
2056 | 2044 |
2057 | 2045 |
2058 LocationSummary* | 2046 LocationSummary* |
2059 ExtractConstructorInstantiatorInstr::MakeLocationSummary() const { | 2047 ExtractConstructorInstantiatorInstr::MakeLocationSummary() const { |
2060 const intptr_t kNumInputs = 1; | 2048 const intptr_t kNumInputs = 1; |
(...skipping 14 matching lines...) Expand all Loading... | |
2075 // instantiator_reg is the instantiator AbstractTypeArguments object | 2063 // instantiator_reg is the instantiator AbstractTypeArguments object |
2076 // (or null). | 2064 // (or null). |
2077 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 2065 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
2078 !type_arguments().CanShareInstantiatorTypeArguments( | 2066 !type_arguments().CanShareInstantiatorTypeArguments( |
2079 instantiator_class())); | 2067 instantiator_class())); |
2080 | 2068 |
2081 // If the instantiator is null and if the type argument vector | 2069 // If the instantiator is null and if the type argument vector |
2082 // instantiated from null becomes a vector of dynamic, then use null as | 2070 // instantiated from null becomes a vector of dynamic, then use null as |
2083 // the type arguments and do not pass the instantiator. | 2071 // the type arguments and do not pass the instantiator. |
2084 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); | 2072 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); |
2085 const Immediate& raw_null = | 2073 |
2086 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
2087 Label instantiator_not_null; | 2074 Label instantiator_not_null; |
2088 __ cmpq(instantiator_reg, raw_null); | 2075 __ CompareObject(instantiator_reg, Object::Handle()); |
2089 __ j(NOT_EQUAL, &instantiator_not_null, Assembler::kNearJump); | 2076 __ j(NOT_EQUAL, &instantiator_not_null, Assembler::kNearJump); |
2090 // Null was used in VisitExtractConstructorTypeArguments as the | 2077 // Null was used in VisitExtractConstructorTypeArguments as the |
2091 // instantiated type arguments, no proper instantiator needed. | 2078 // instantiated type arguments, no proper instantiator needed. |
2092 __ movq(instantiator_reg, | 2079 __ movq(instantiator_reg, |
2093 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 2080 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
2094 __ Bind(&instantiator_not_null); | 2081 __ Bind(&instantiator_not_null); |
2095 // instantiator_reg: instantiator or kNoInstantiator. | 2082 // instantiator_reg: instantiator or kNoInstantiator. |
2096 } | 2083 } |
2097 | 2084 |
2098 | 2085 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2154 } | 2141 } |
2155 | 2142 |
2156 | 2143 |
2157 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2144 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2158 __ Bind(compiler->GetJumpLabel(this)); | 2145 __ Bind(compiler->GetJumpLabel(this)); |
2159 compiler->AddExceptionHandler(catch_try_index(), | 2146 compiler->AddExceptionHandler(catch_try_index(), |
2160 try_index(), | 2147 try_index(), |
2161 compiler->assembler()->CodeSize(), | 2148 compiler->assembler()->CodeSize(), |
2162 catch_handler_types_, | 2149 catch_handler_types_, |
2163 needs_stacktrace()); | 2150 needs_stacktrace()); |
2151 | |
2152 // Restore the pool pointer. | |
2153 __ LoadPoolPointer(PP); | |
2154 | |
2164 if (HasParallelMove()) { | 2155 if (HasParallelMove()) { |
2165 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 2156 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
2166 } | 2157 } |
2167 | 2158 |
2168 // Restore RSP from RBP as we are coming from a throw and the code for | 2159 // Restore RSP from RBP as we are coming from a throw and the code for |
2169 // popping arguments has not been run. | 2160 // popping arguments has not been run. |
2170 const intptr_t fp_sp_dist = | 2161 const intptr_t fp_sp_dist = |
2171 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 2162 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
2172 ASSERT(fp_sp_dist <= 0); | 2163 ASSERT(fp_sp_dist <= 0); |
2173 __ leaq(RSP, Address(RBP, fp_sp_dist)); | 2164 __ leaq(RSP, Address(RBP, fp_sp_dist)); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2234 | 2225 |
2235 Register temp = locs()->temp(0).reg(); | 2226 Register temp = locs()->temp(0).reg(); |
2236 // Generate stack overflow check. | 2227 // Generate stack overflow check. |
2237 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); | 2228 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); |
2238 __ cmpq(RSP, Address(temp, 0)); | 2229 __ cmpq(RSP, Address(temp, 0)); |
2239 __ j(BELOW_EQUAL, slow_path->entry_label()); | 2230 __ j(BELOW_EQUAL, slow_path->entry_label()); |
2240 if (compiler->CanOSRFunction() && in_loop()) { | 2231 if (compiler->CanOSRFunction() && in_loop()) { |
2241 // In unoptimized code check the usage counter to trigger OSR at loop | 2232 // In unoptimized code check the usage counter to trigger OSR at loop |
2242 // stack checks. Use progressively higher thresholds for more deeply | 2233 // stack checks. Use progressively higher thresholds for more deeply |
2243 // nested loops to attempt to hit outer loops with OSR when possible. | 2234 // nested loops to attempt to hit outer loops with OSR when possible. |
2244 __ LoadObject(temp, compiler->parsed_function().function()); | 2235 __ LoadObjectFromPool(temp, compiler->parsed_function().function(), PP); |
2245 intptr_t threshold = | 2236 intptr_t threshold = |
2246 FLAG_optimization_counter_threshold * (loop_depth() + 1); | 2237 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
2247 __ cmpq(FieldAddress(temp, Function::usage_counter_offset()), | 2238 __ cmpq(FieldAddress(temp, Function::usage_counter_offset()), |
2248 Immediate(threshold)); | 2239 Immediate(threshold)); |
2249 __ j(GREATER_EQUAL, slow_path->entry_label()); | 2240 __ j(GREATER_EQUAL, slow_path->entry_label()); |
2250 } | 2241 } |
2251 __ Bind(slow_path->exit_label()); | 2242 __ Bind(slow_path->exit_label()); |
2252 } | 2243 } |
2253 | 2244 |
2254 | 2245 |
(...skipping 1426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3681 __ movl(result, Address(RSP, 8)); | 3672 __ movl(result, Address(RSP, 8)); |
3682 break; | 3673 break; |
3683 case MethodRecognizer::kUint32x4GetFlagW: | 3674 case MethodRecognizer::kUint32x4GetFlagW: |
3684 __ movl(result, Address(RSP, 12)); | 3675 __ movl(result, Address(RSP, 12)); |
3685 break; | 3676 break; |
3686 default: UNREACHABLE(); | 3677 default: UNREACHABLE(); |
3687 } | 3678 } |
3688 __ addq(RSP, Immediate(16)); | 3679 __ addq(RSP, Immediate(16)); |
3689 __ testl(result, result); | 3680 __ testl(result, result); |
3690 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); | 3681 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); |
3691 __ LoadObject(result, Bool::False()); | 3682 __ LoadObjectFromPool(result, Bool::False(), PP); |
3692 __ jmp(&done); | 3683 __ jmp(&done); |
3693 __ Bind(&non_zero); | 3684 __ Bind(&non_zero); |
3694 __ LoadObject(result, Bool::True()); | 3685 __ LoadObjectFromPool(result, Bool::True(), PP); |
3695 __ Bind(&done); | 3686 __ Bind(&done); |
3696 } | 3687 } |
3697 | 3688 |
3698 | 3689 |
3699 LocationSummary* Uint32x4SelectInstr::MakeLocationSummary() const { | 3690 LocationSummary* Uint32x4SelectInstr::MakeLocationSummary() const { |
3700 const intptr_t kNumInputs = 3; | 3691 const intptr_t kNumInputs = 3; |
3701 const intptr_t kNumTemps = 1; | 3692 const intptr_t kNumTemps = 1; |
3702 LocationSummary* summary = | 3693 LocationSummary* summary = |
3703 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3694 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3704 summary->set_in(0, Location::RequiresFpuRegister()); | 3695 summary->set_in(0, Location::RequiresFpuRegister()); |
(...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4198 // return double.NAN; | 4189 // return double.NAN; |
4199 // } | 4190 // } |
4200 XmmRegister base = locs()->in(0).fpu_reg(); | 4191 XmmRegister base = locs()->in(0).fpu_reg(); |
4201 XmmRegister exp = locs()->in(1).fpu_reg(); | 4192 XmmRegister exp = locs()->in(1).fpu_reg(); |
4202 XmmRegister result = locs()->out().fpu_reg(); | 4193 XmmRegister result = locs()->out().fpu_reg(); |
4203 Register temp = locs()->temp(0).reg(); | 4194 Register temp = locs()->temp(0).reg(); |
4204 XmmRegister zero_temp = locs()->temp(1).fpu_reg(); | 4195 XmmRegister zero_temp = locs()->temp(1).fpu_reg(); |
4205 | 4196 |
4206 Label check_base_is_one; | 4197 Label check_base_is_one; |
4207 // Check if exponent is 0.0 -> return 1.0; | 4198 // Check if exponent is 0.0 -> return 1.0; |
4208 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0))); | 4199 __ LoadObjectFromPool(temp, Double::ZoneHandle(Double::NewCanonical(0)), |
4200 PP); | |
4209 __ movsd(zero_temp, FieldAddress(temp, Double::value_offset())); | 4201 __ movsd(zero_temp, FieldAddress(temp, Double::value_offset())); |
4210 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1))); | 4202 __ LoadObjectFromPool(temp, Double::ZoneHandle(Double::NewCanonical(1)), |
4203 PP); | |
4211 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 4204 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
4212 // 'result' contains 1.0. | 4205 // 'result' contains 1.0. |
4213 __ comisd(exp, zero_temp); | 4206 __ comisd(exp, zero_temp); |
4214 __ j(PARITY_EVEN, &check_base_is_one, Assembler::kNearJump); // NaN. | 4207 __ j(PARITY_EVEN, &check_base_is_one, Assembler::kNearJump); // NaN. |
4215 __ j(EQUAL, &skip_call, Assembler::kNearJump); // exp is 0, result is 1.0. | 4208 __ j(EQUAL, &skip_call, Assembler::kNearJump); // exp is 0, result is 1.0. |
4216 | 4209 |
4217 Label base_is_nan; | 4210 Label base_is_nan; |
4218 __ Bind(&check_base_is_one); | 4211 __ Bind(&check_base_is_one); |
4219 // Checks if base == 1.0. | 4212 // Checks if base == 1.0. |
4220 __ comisd(base, result); | 4213 __ comisd(base, result); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4298 summary->AddTemp(Location::RequiresRegister()); | 4291 summary->AddTemp(Location::RequiresRegister()); |
4299 } | 4292 } |
4300 return summary; | 4293 return summary; |
4301 } | 4294 } |
4302 | 4295 |
4303 | 4296 |
4304 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4297 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4305 if (IsNullCheck()) { | 4298 if (IsNullCheck()) { |
4306 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 4299 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
4307 kDeoptCheckClass); | 4300 kDeoptCheckClass); |
4308 const Immediate& raw_null = | 4301 __ CompareObject(locs()->in(0).reg(), |
4309 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 4302 Object::Handle()); |
4310 __ cmpq(locs()->in(0).reg(), raw_null); | |
4311 __ j(EQUAL, deopt); | 4303 __ j(EQUAL, deopt); |
4312 return; | 4304 return; |
4313 } | 4305 } |
4314 | 4306 |
4315 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 4307 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
4316 (unary_checks().NumberOfChecks() > 1)); | 4308 (unary_checks().NumberOfChecks() > 1)); |
4317 Register value = locs()->in(0).reg(); | 4309 Register value = locs()->in(0).reg(); |
4318 Register temp = locs()->temp(0).reg(); | 4310 Register temp = locs()->temp(0).reg(); |
4319 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 4311 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
4320 kDeoptCheckClass); | 4312 kDeoptCheckClass); |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4510 __ Bind(compiler->GetJumpLabel(this)); | 4502 __ Bind(compiler->GetJumpLabel(this)); |
4511 if (!compiler->is_optimizing()) { | 4503 if (!compiler->is_optimizing()) { |
4512 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 4504 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
4513 deopt_id_, | 4505 deopt_id_, |
4514 Scanner::kDummyTokenIndex); | 4506 Scanner::kDummyTokenIndex); |
4515 // Add an edge counter. | 4507 // Add an edge counter. |
4516 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); | 4508 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); |
4517 counter.SetAt(0, Smi::Handle(Smi::New(0))); | 4509 counter.SetAt(0, Smi::Handle(Smi::New(0))); |
4518 Label done; | 4510 Label done; |
4519 __ Comment("Edge counter"); | 4511 __ Comment("Edge counter"); |
4520 __ LoadObject(RAX, counter); | 4512 __ LoadObjectFromPool(RAX, counter, PP); |
4521 __ addq(FieldAddress(RAX, Array::element_offset(0)), | 4513 __ addq(FieldAddress(RAX, Array::element_offset(0)), |
4522 Immediate(Smi::RawValue(1))); | 4514 Immediate(Smi::RawValue(1))); |
4523 __ j(NO_OVERFLOW, &done); | 4515 __ j(NO_OVERFLOW, &done); |
4524 __ movq(FieldAddress(RAX, Array::element_offset(0)), | 4516 __ movq(FieldAddress(RAX, Array::element_offset(0)), |
4525 Immediate(Smi::RawValue(Smi::kMaxValue))); | 4517 Immediate(Smi::RawValue(Smi::kMaxValue))); |
4526 __ Bind(&done); | 4518 __ Bind(&done); |
4527 } | 4519 } |
4528 if (HasParallelMove()) { | 4520 if (HasParallelMove()) { |
4529 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 4521 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
4530 } | 4522 } |
(...skipping 10 matching lines...) Expand all Loading... | |
4541 // Add deoptimization descriptor for deoptimizing instructions that may | 4533 // Add deoptimization descriptor for deoptimizing instructions that may |
4542 // be inserted before this instruction. | 4534 // be inserted before this instruction. |
4543 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 4535 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
4544 GetDeoptId(), | 4536 GetDeoptId(), |
4545 0); // No token position. | 4537 0); // No token position. |
4546 // Add an edge counter. | 4538 // Add an edge counter. |
4547 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); | 4539 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); |
4548 counter.SetAt(0, Smi::Handle(Smi::New(0))); | 4540 counter.SetAt(0, Smi::Handle(Smi::New(0))); |
4549 Label done; | 4541 Label done; |
4550 __ Comment("Edge counter"); | 4542 __ Comment("Edge counter"); |
4551 __ LoadObject(RAX, counter); | 4543 __ LoadObjectFromPool(RAX, counter, PP); |
4552 __ addq(FieldAddress(RAX, Array::element_offset(0)), | 4544 __ addq(FieldAddress(RAX, Array::element_offset(0)), |
4553 Immediate(Smi::RawValue(1))); | 4545 Immediate(Smi::RawValue(1))); |
4554 __ j(NO_OVERFLOW, &done); | 4546 __ j(NO_OVERFLOW, &done); |
4555 __ movq(FieldAddress(RAX, Array::element_offset(0)), | 4547 __ movq(FieldAddress(RAX, Array::element_offset(0)), |
4556 Immediate(Smi::RawValue(Smi::kMaxValue))); | 4548 Immediate(Smi::RawValue(Smi::kMaxValue))); |
4557 __ Bind(&done); | 4549 __ Bind(&done); |
4558 } | 4550 } |
4559 if (HasParallelMove()) { | 4551 if (HasParallelMove()) { |
4560 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 4552 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
4561 } | 4553 } |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4624 // Special code for numbers (compare values instead of references.) | 4616 // Special code for numbers (compare values instead of references.) |
4625 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4617 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4626 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4618 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
4627 Location left = locs()->in(0); | 4619 Location left = locs()->in(0); |
4628 Location right = locs()->in(1); | 4620 Location right = locs()->in(1); |
4629 if (left.IsConstant() && right.IsConstant()) { | 4621 if (left.IsConstant() && right.IsConstant()) { |
4630 // TODO(vegorov): should be eliminated earlier by constant propagation. | 4622 // TODO(vegorov): should be eliminated earlier by constant propagation. |
4631 const bool result = (kind() == Token::kEQ_STRICT) ? | 4623 const bool result = (kind() == Token::kEQ_STRICT) ? |
4632 left.constant().raw() == right.constant().raw() : | 4624 left.constant().raw() == right.constant().raw() : |
4633 left.constant().raw() != right.constant().raw(); | 4625 left.constant().raw() != right.constant().raw(); |
4634 __ LoadObject(locs()->out().reg(), Bool::Get(result)); | 4626 __ LoadObjectFromPool(locs()->out().reg(), Bool::Get(result), PP); |
4635 return; | 4627 return; |
4636 } | 4628 } |
4637 if (left.IsConstant()) { | 4629 if (left.IsConstant()) { |
4638 compiler->EmitEqualityRegConstCompare(right.reg(), | 4630 compiler->EmitEqualityRegConstCompare(right.reg(), |
4639 left.constant(), | 4631 left.constant(), |
4640 needs_number_check(), | 4632 needs_number_check(), |
4641 token_pos()); | 4633 token_pos()); |
4642 } else if (right.IsConstant()) { | 4634 } else if (right.IsConstant()) { |
4643 compiler->EmitEqualityRegConstCompare(left.reg(), | 4635 compiler->EmitEqualityRegConstCompare(left.reg(), |
4644 right.constant(), | 4636 right.constant(), |
4645 needs_number_check(), | 4637 needs_number_check(), |
4646 token_pos()); | 4638 token_pos()); |
4647 } else { | 4639 } else { |
4648 compiler->EmitEqualityRegRegCompare(left.reg(), | 4640 compiler->EmitEqualityRegRegCompare(left.reg(), |
4649 right.reg(), | 4641 right.reg(), |
4650 needs_number_check(), | 4642 needs_number_check(), |
4651 token_pos()); | 4643 token_pos()); |
4652 } | 4644 } |
4653 | 4645 |
4654 Register result = locs()->out().reg(); | 4646 Register result = locs()->out().reg(); |
4655 Label load_true, done; | 4647 Label load_true, done; |
4656 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 4648 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
4657 __ j(true_condition, &load_true, Assembler::kNearJump); | 4649 __ j(true_condition, &load_true, Assembler::kNearJump); |
4658 __ LoadObject(result, Bool::False()); | 4650 __ LoadObjectFromPool(result, Bool::False(), PP); |
4659 __ jmp(&done, Assembler::kNearJump); | 4651 __ jmp(&done, Assembler::kNearJump); |
4660 __ Bind(&load_true); | 4652 __ Bind(&load_true); |
4661 __ LoadObject(result, Bool::True()); | 4653 __ LoadObjectFromPool(result, Bool::True(), PP); |
4662 __ Bind(&done); | 4654 __ Bind(&done); |
4663 } | 4655 } |
4664 | 4656 |
4665 | 4657 |
4666 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 4658 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
4667 BranchInstr* branch) { | 4659 BranchInstr* branch) { |
4668 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4660 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
4669 Location left = locs()->in(0); | 4661 Location left = locs()->in(0); |
4670 Location right = locs()->in(1); | 4662 Location right = locs()->in(1); |
4671 if (left.IsConstant() && right.IsConstant()) { | 4663 if (left.IsConstant() && right.IsConstant()) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4710 | 4702 |
4711 | 4703 |
4712 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4704 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4713 // The arguments to the stub include the closure, as does the arguments | 4705 // The arguments to the stub include the closure, as does the arguments |
4714 // descriptor. | 4706 // descriptor. |
4715 Register temp_reg = locs()->temp(0).reg(); | 4707 Register temp_reg = locs()->temp(0).reg(); |
4716 int argument_count = ArgumentCount(); | 4708 int argument_count = ArgumentCount(); |
4717 const Array& arguments_descriptor = | 4709 const Array& arguments_descriptor = |
4718 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 4710 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
4719 argument_names())); | 4711 argument_names())); |
4720 __ LoadObject(temp_reg, arguments_descriptor); | 4712 __ LoadObjectFromPool(temp_reg, arguments_descriptor, PP); |
4721 ASSERT(temp_reg == R10); | 4713 ASSERT(temp_reg == R10); |
4722 compiler->GenerateDartCall(deopt_id(), | 4714 compiler->GenerateDartCall(deopt_id(), |
4723 token_pos(), | 4715 token_pos(), |
4724 &StubCode::CallClosureFunctionLabel(), | 4716 &StubCode::CallClosureFunctionLabel(), |
4725 PcDescriptors::kClosureCall, | 4717 PcDescriptors::kClosureCall, |
4726 locs()); | 4718 locs()); |
4727 __ Drop(argument_count); | 4719 __ Drop(argument_count); |
4728 } | 4720 } |
4729 | 4721 |
4730 | 4722 |
4731 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { | 4723 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { |
4732 return LocationSummary::Make(1, | 4724 return LocationSummary::Make(1, |
4733 Location::RequiresRegister(), | 4725 Location::RequiresRegister(), |
4734 LocationSummary::kNoCall); | 4726 LocationSummary::kNoCall); |
4735 } | 4727 } |
4736 | 4728 |
4737 | 4729 |
4738 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4730 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4739 Register value = locs()->in(0).reg(); | 4731 Register value = locs()->in(0).reg(); |
4740 Register result = locs()->out().reg(); | 4732 Register result = locs()->out().reg(); |
4741 | 4733 |
4742 Label done; | 4734 Label done; |
4743 __ LoadObject(result, Bool::True()); | 4735 __ LoadObjectFromPool(result, Bool::True(), PP); |
4744 __ CompareRegisters(result, value); | 4736 __ CompareRegisters(result, value); |
4745 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 4737 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
4746 __ LoadObject(result, Bool::False()); | 4738 __ LoadObjectFromPool(result, Bool::False(), PP); |
4747 __ Bind(&done); | 4739 __ Bind(&done); |
4748 } | 4740 } |
4749 | 4741 |
4750 | 4742 |
4751 LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const { | 4743 LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const { |
4752 const intptr_t kNumInputs = 2; | 4744 const intptr_t kNumInputs = 2; |
4753 const intptr_t kNumTemps = 0; | 4745 const intptr_t kNumTemps = 0; |
4754 LocationSummary* locs = | 4746 LocationSummary* locs = |
4755 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4747 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4756 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 4748 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4806 PcDescriptors::kOther, | 4798 PcDescriptors::kOther, |
4807 locs()); | 4799 locs()); |
4808 __ Drop(2); // Discard type arguments and receiver. | 4800 __ Drop(2); // Discard type arguments and receiver. |
4809 } | 4801 } |
4810 | 4802 |
4811 } // namespace dart | 4803 } // namespace dart |
4812 | 4804 |
4813 #undef __ | 4805 #undef __ |
4814 | 4806 |
4815 #endif // defined TARGET_ARCH_X64 | 4807 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |