OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 case Token::kGTE: return GREATER_EQUAL; | 243 case Token::kGTE: return GREATER_EQUAL; |
244 default: | 244 default: |
245 UNREACHABLE(); | 245 UNREACHABLE(); |
246 return OVERFLOW; | 246 return OVERFLOW; |
247 } | 247 } |
248 } | 248 } |
249 | 249 |
250 | 250 |
251 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { | 251 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { |
252 const intptr_t kNumInputs = 2; | 252 const intptr_t kNumInputs = 2; |
253 if (receiver_class_id() != kObject) { | 253 if (receiver_class_id() != kObjectCid) { |
254 ASSERT((receiver_class_id() == kSmi) || (receiver_class_id() == kDouble)); | 254 ASSERT((receiver_class_id() == kSmiCid) || |
| 255 (receiver_class_id() == kDoubleCid)); |
255 const intptr_t kNumTemps = 1; | 256 const intptr_t kNumTemps = 1; |
256 LocationSummary* locs = | 257 LocationSummary* locs = |
257 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 258 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
258 locs->set_in(0, Location::RequiresRegister()); | 259 locs->set_in(0, Location::RequiresRegister()); |
259 locs->set_in(1, Location::RequiresRegister()); | 260 locs->set_in(1, Location::RequiresRegister()); |
260 locs->set_temp(0, Location::RequiresRegister()); | 261 locs->set_temp(0, Location::RequiresRegister()); |
261 locs->set_out(Location::RequiresRegister()); | 262 locs->set_out(Location::RequiresRegister()); |
262 return locs; | 263 return locs; |
263 } | 264 } |
264 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 265 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 ASSERT(ic_data.NumberOfChecks() > 0); | 327 ASSERT(ic_data.NumberOfChecks() > 0); |
327 ASSERT(ic_data.num_args_tested() == 1); | 328 ASSERT(ic_data.num_args_tested() == 1); |
328 Label* deopt = compiler->AddDeoptStub(deopt_id, | 329 Label* deopt = compiler->AddDeoptStub(deopt_id, |
329 token_pos, | 330 token_pos, |
330 try_index, | 331 try_index, |
331 kDeoptEquality); | 332 kDeoptEquality); |
332 Register left = locs.in(0).reg(); | 333 Register left = locs.in(0).reg(); |
333 Register right = locs.in(1).reg(); | 334 Register right = locs.in(1).reg(); |
334 __ testq(left, Immediate(kSmiTagMask)); | 335 __ testq(left, Immediate(kSmiTagMask)); |
335 Register temp = locs.temp(0).reg(); | 336 Register temp = locs.temp(0).reg(); |
336 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { | 337 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { |
337 Label done, load_class_id; | 338 Label done, load_class_id; |
338 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 339 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
339 __ movq(temp, Immediate(kSmi)); | 340 __ movq(temp, Immediate(kSmiCid)); |
340 __ jmp(&done, Assembler::kNearJump); | 341 __ jmp(&done, Assembler::kNearJump); |
341 __ Bind(&load_class_id); | 342 __ Bind(&load_class_id); |
342 __ LoadClassId(temp, left); | 343 __ LoadClassId(temp, left); |
343 __ Bind(&done); | 344 __ Bind(&done); |
344 } else { | 345 } else { |
345 __ j(ZERO, deopt); // Smi deopts. | 346 __ j(ZERO, deopt); // Smi deopts. |
346 __ LoadClassId(temp, left); | 347 __ LoadClassId(temp, left); |
347 } | 348 } |
348 Condition cond = TokenKindToSmiCondition(kind); | 349 Condition cond = TokenKindToSmiCondition(kind); |
349 Label done; | 350 Label done; |
350 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 351 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
351 ASSERT((ic_data.GetReceiverClassIdAt(i) != kSmi) || (i == 0)); | 352 ASSERT((ic_data.GetReceiverClassIdAt(i) != kSmiCid) || (i == 0)); |
352 Label next_test; | 353 Label next_test; |
353 __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); | 354 __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); |
354 __ j(NOT_EQUAL, &next_test); | 355 __ j(NOT_EQUAL, &next_test); |
355 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); | 356 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); |
356 ObjectStore* object_store = Isolate::Current()->object_store(); | 357 ObjectStore* object_store = Isolate::Current()->object_store(); |
357 if (target.owner() == object_store->object_class()) { | 358 if (target.owner() == object_store->object_class()) { |
358 // Object.== is same as ===. | 359 // Object.== is same as ===. |
359 __ Drop(2); | 360 __ Drop(2); |
360 __ cmpq(left, right); | 361 __ cmpq(left, right); |
361 if (branch != NULL) { | 362 if (branch != NULL) { |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 compiler->EmitDoubleCompareBranch( | 528 compiler->EmitDoubleCompareBranch( |
528 true_condition, XMM0, XMM1, branch); | 529 true_condition, XMM0, XMM1, branch); |
529 } else { | 530 } else { |
530 compiler->EmitDoubleCompareBool( | 531 compiler->EmitDoubleCompareBool( |
531 true_condition, XMM0, XMM1, locs.out().reg()); | 532 true_condition, XMM0, XMM1, locs.out().reg()); |
532 } | 533 } |
533 } | 534 } |
534 | 535 |
535 | 536 |
536 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 537 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
537 if (receiver_class_id() == kSmi) { | 538 if (receiver_class_id() == kSmiCid) { |
538 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. | 539 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. |
539 deopt_id(), token_pos(), try_index()); | 540 deopt_id(), token_pos(), try_index()); |
540 return; | 541 return; |
541 } | 542 } |
542 if (receiver_class_id() == kDouble) { | 543 if (receiver_class_id() == kDoubleCid) { |
543 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. | 544 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. |
544 deopt_id(), token_pos(), try_index()); | 545 deopt_id(), token_pos(), try_index()); |
545 return; | 546 return; |
546 } | 547 } |
547 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 548 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
548 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, *ic_data(), | 549 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, *ic_data(), |
549 deopt_id(), token_pos(), try_index()); | 550 deopt_id(), token_pos(), try_index()); |
550 } else { | 551 } else { |
551 Register left = locs()->in(0).reg(); | 552 Register left = locs()->in(0).reg(); |
552 Register right = locs()->in(1).reg(); | 553 Register right = locs()->in(1).reg(); |
553 __ pushq(left); | 554 __ pushq(left); |
554 __ pushq(right); | 555 __ pushq(right); |
555 EmitEqualityAsInstanceCall(compiler, this); | 556 EmitEqualityAsInstanceCall(compiler, this); |
556 } | 557 } |
557 } | 558 } |
558 | 559 |
559 | 560 |
560 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 561 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
561 if (operands_class_id() == kSmi || operands_class_id() == kDouble) { | 562 if (operands_class_id() == kSmiCid || operands_class_id() == kDoubleCid) { |
562 const intptr_t kNumInputs = 2; | 563 const intptr_t kNumInputs = 2; |
563 const intptr_t kNumTemps = 1; | 564 const intptr_t kNumTemps = 1; |
564 LocationSummary* summary = | 565 LocationSummary* summary = |
565 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 566 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
566 summary->set_in(0, Location::RequiresRegister()); | 567 summary->set_in(0, Location::RequiresRegister()); |
567 summary->set_in(1, Location::RequiresRegister()); | 568 summary->set_in(1, Location::RequiresRegister()); |
568 summary->set_out(Location::RequiresRegister()); | 569 summary->set_out(Location::RequiresRegister()); |
569 summary->set_temp(0, Location::RequiresRegister()); | 570 summary->set_temp(0, Location::RequiresRegister()); |
570 return summary; | 571 return summary; |
571 } | 572 } |
572 ASSERT(operands_class_id() == kObject); | 573 ASSERT(operands_class_id() == kObjectCid); |
573 return MakeCallSummary(); | 574 return MakeCallSummary(); |
574 } | 575 } |
575 | 576 |
576 | 577 |
577 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 578 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
578 if (operands_class_id() == kSmi) { | 579 if (operands_class_id() == kSmiCid) { |
579 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, | 580 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, |
580 deopt_id(), token_pos(), try_index()); | 581 deopt_id(), token_pos(), try_index()); |
581 return; | 582 return; |
582 } | 583 } |
583 if (operands_class_id() == kDouble) { | 584 if (operands_class_id() == kDoubleCid) { |
584 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, | 585 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, |
585 deopt_id(), token_pos(), try_index()); | 586 deopt_id(), token_pos(), try_index()); |
586 return; | 587 return; |
587 } | 588 } |
588 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 589 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
589 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 590 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
590 token_pos(), | 591 token_pos(), |
591 try_index(), | 592 try_index(), |
592 kDeoptRelationalOp); | 593 kDeoptRelationalOp); |
593 // Load receiver into RAX, class into RDI. | 594 // Load receiver into RAX, class into RDI. |
594 Label done; | 595 Label done; |
595 const intptr_t kNumArguments = 2; | 596 const intptr_t kNumArguments = 2; |
596 __ movq(RDI, Immediate(kSmi)); | 597 __ movq(RDI, Immediate(kSmiCid)); |
597 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 598 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
598 __ testq(RAX, Immediate(kSmiTagMask)); | 599 __ testq(RAX, Immediate(kSmiTagMask)); |
599 __ j(ZERO, &done); | 600 __ j(ZERO, &done); |
600 __ LoadClassId(RDI, RAX); | 601 __ LoadClassId(RDI, RAX); |
601 __ Bind(&done); | 602 __ Bind(&done); |
602 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), | 603 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), |
603 RDI, // Class id register. | 604 RDI, // Class id register. |
604 kNumArguments, | 605 kNumArguments, |
605 Array::Handle(), // No named arguments. | 606 Array::Handle(), // No named arguments. |
606 deopt, // Deoptimize target. | 607 deopt, // Deoptimize target. |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
666 compiler->GenerateCall(token_pos(), | 667 compiler->GenerateCall(token_pos(), |
667 try_index(), | 668 try_index(), |
668 &StubCode::CallNativeCFunctionLabel(), | 669 &StubCode::CallNativeCFunctionLabel(), |
669 PcDescriptors::kOther); | 670 PcDescriptors::kOther); |
670 __ popq(result); | 671 __ popq(result); |
671 } | 672 } |
672 | 673 |
673 | 674 |
674 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 675 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { |
675 const intptr_t kNumInputs = 2; | 676 const intptr_t kNumInputs = 2; |
676 if (receiver_type() == kGrowableObjectArray) { | 677 if (receiver_type() == kGrowableObjectArrayCid) { |
677 const intptr_t kNumTemps = 1; | 678 const intptr_t kNumTemps = 1; |
678 LocationSummary* locs = | 679 LocationSummary* locs = |
679 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 680 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
680 locs->set_in(0, Location::RequiresRegister()); | 681 locs->set_in(0, Location::RequiresRegister()); |
681 locs->set_in(1, Location::RequiresRegister()); | 682 locs->set_in(1, Location::RequiresRegister()); |
682 locs->set_temp(0, Location::RequiresRegister()); | 683 locs->set_temp(0, Location::RequiresRegister()); |
683 locs->set_out(Location::RequiresRegister()); | 684 locs->set_out(Location::RequiresRegister()); |
684 return locs; | 685 return locs; |
685 } else if ((receiver_type() == kArray) || | 686 } else if ((receiver_type() == kArrayCid) || |
686 (receiver_type() == kImmutableArray)) { | 687 (receiver_type() == kImmutableArrayCid)) { |
687 return LocationSummary::Make(kNumInputs, | 688 return LocationSummary::Make(kNumInputs, |
688 Location::RequiresRegister(), | 689 Location::RequiresRegister(), |
689 LocationSummary::kNoCall); | 690 LocationSummary::kNoCall); |
690 } else { | 691 } else { |
691 ASSERT(receiver_type() == kIllegalObjectKind); | 692 ASSERT(receiver_type() == kIllegalCid); |
692 return MakeCallSummary(); | 693 return MakeCallSummary(); |
693 } | 694 } |
694 } | 695 } |
695 | 696 |
696 | 697 |
697 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, | 698 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, |
698 LoadIndexedComp* comp) { | 699 LoadIndexedComp* comp) { |
699 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), | 700 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
700 comp->token_pos(), | 701 comp->token_pos(), |
701 comp->try_index(), | 702 comp->try_index(), |
702 kDeoptLoadIndexedPolymorphic); | 703 kDeoptLoadIndexedPolymorphic); |
703 ASSERT(comp->ic_data()->NumberOfChecks() > 0); | 704 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
704 ASSERT(comp->HasICData()); | 705 ASSERT(comp->HasICData()); |
705 const ICData& ic_data = *comp->ic_data(); | 706 const ICData& ic_data = *comp->ic_data(); |
706 ASSERT(ic_data.num_args_tested() == 1); | 707 ASSERT(ic_data.num_args_tested() == 1); |
707 // No indexed access on Smi. | 708 // No indexed access on Smi. |
708 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 709 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmiCid); |
709 // Load receiver into RAX. | 710 // Load receiver into RAX. |
710 const intptr_t kNumArguments = 2; | 711 const intptr_t kNumArguments = 2; |
711 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 712 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
712 __ testq(RAX, Immediate(kSmiTagMask)); | 713 __ testq(RAX, Immediate(kSmiTagMask)); |
713 __ j(ZERO, deopt); | 714 __ j(ZERO, deopt); |
714 __ LoadClassId(RDI, RAX); | 715 __ LoadClassId(RDI, RAX); |
715 compiler->EmitTestAndCall(ic_data, | 716 compiler->EmitTestAndCall(ic_data, |
716 RDI, // Class id register. | 717 RDI, // Class id register. |
717 kNumArguments, | 718 kNumArguments, |
718 Array::Handle(), // No named arguments. | 719 Array::Handle(), // No named arguments. |
719 deopt, // Deoptimize target. | 720 deopt, // Deoptimize target. |
720 NULL, // Fallthrough when done. | 721 NULL, // Fallthrough when done. |
721 comp->deopt_id(), | 722 comp->deopt_id(), |
722 comp->token_pos(), | 723 comp->token_pos(), |
723 comp->try_index()); | 724 comp->try_index()); |
724 } | 725 } |
725 | 726 |
726 | 727 |
727 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 728 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
728 if (receiver_type() == kIllegalObjectKind) { | 729 if (receiver_type() == kIllegalCid) { |
729 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 730 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
730 EmitLoadIndexedPolymorphic(compiler, this); | 731 EmitLoadIndexedPolymorphic(compiler, this); |
731 } else { | 732 } else { |
732 compiler->EmitLoadIndexedGeneric(this); | 733 compiler->EmitLoadIndexedGeneric(this); |
733 } | 734 } |
734 ASSERT(locs()->out().reg() == RAX); | 735 ASSERT(locs()->out().reg() == RAX); |
735 return; | 736 return; |
736 } | 737 } |
737 | 738 |
738 Register receiver = locs()->in(0).reg(); | 739 Register receiver = locs()->in(0).reg(); |
739 Register index = locs()->in(1).reg(); | 740 Register index = locs()->in(1).reg(); |
740 Register result = locs()->out().reg(); | 741 Register result = locs()->out().reg(); |
741 | 742 |
742 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? | 743 const DeoptReasonId deopt_reason = |
| 744 (receiver_type() == kGrowableObjectArrayCid) ? |
743 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 745 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
744 | 746 |
745 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 747 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
746 token_pos(), | 748 token_pos(), |
747 try_index(), | 749 try_index(), |
748 deopt_reason, | 750 deopt_reason, |
749 receiver, | 751 receiver, |
750 index); | 752 index); |
751 | 753 |
752 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 754 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
753 __ j(ZERO, deopt); | 755 __ j(ZERO, deopt); |
754 __ CompareClassId(receiver, receiver_type()); | 756 __ CompareClassId(receiver, receiver_type()); |
755 __ j(NOT_EQUAL, deopt); | 757 __ j(NOT_EQUAL, deopt); |
756 | 758 |
757 __ testq(index, Immediate(kSmiTagMask)); | 759 __ testq(index, Immediate(kSmiTagMask)); |
758 __ j(NOT_ZERO, deopt); | 760 __ j(NOT_ZERO, deopt); |
759 | 761 |
760 switch (receiver_type()) { | 762 switch (receiver_type()) { |
761 case kArray: | 763 case kArrayCid: |
762 case kImmutableArray: | 764 case kImmutableArrayCid: |
763 __ cmpq(index, FieldAddress(receiver, Array::length_offset())); | 765 __ cmpq(index, FieldAddress(receiver, Array::length_offset())); |
764 __ j(ABOVE_EQUAL, deopt); | 766 __ j(ABOVE_EQUAL, deopt); |
765 // Note that index is Smi, i.e, times 4. | 767 // Note that index is Smi, i.e, times 4. |
766 ASSERT(kSmiTagShift == 1); | 768 ASSERT(kSmiTagShift == 1); |
767 __ movq(result, FieldAddress(receiver, index, TIMES_4, sizeof(RawArray))); | 769 __ movq(result, FieldAddress(receiver, index, TIMES_4, sizeof(RawArray))); |
768 break; | 770 break; |
769 | 771 |
770 case kGrowableObjectArray: { | 772 case kGrowableObjectArrayCid: { |
771 Register temp = locs()->temp(0).reg(); | 773 Register temp = locs()->temp(0).reg(); |
772 | 774 |
773 __ cmpq(index, | 775 __ cmpq(index, |
774 FieldAddress(receiver, GrowableObjectArray::length_offset())); | 776 FieldAddress(receiver, GrowableObjectArray::length_offset())); |
775 __ j(ABOVE_EQUAL, deopt); | 777 __ j(ABOVE_EQUAL, deopt); |
776 __ movq(temp, FieldAddress(receiver, GrowableObjectArray::data_offset())); | 778 __ movq(temp, FieldAddress(receiver, GrowableObjectArray::data_offset())); |
777 // Note that index is Smi, i.e, times 4. | 779 // Note that index is Smi, i.e, times 4. |
778 ASSERT(kSmiTagShift == 1); | 780 ASSERT(kSmiTagShift == 1); |
779 __ movq(result, FieldAddress(temp, index, TIMES_4, sizeof(RawArray))); | 781 __ movq(result, FieldAddress(temp, index, TIMES_4, sizeof(RawArray))); |
780 break; | 782 break; |
781 } | 783 } |
782 | 784 |
783 default: | 785 default: |
784 UNREACHABLE(); | 786 UNREACHABLE(); |
785 break; | 787 break; |
786 } | 788 } |
787 } | 789 } |
788 | 790 |
789 | 791 |
790 LocationSummary* StoreIndexedComp::MakeLocationSummary() const { | 792 LocationSummary* StoreIndexedComp::MakeLocationSummary() const { |
791 const intptr_t kNumInputs = 3; | 793 const intptr_t kNumInputs = 3; |
792 if (receiver_type() == kGrowableObjectArray) { | 794 if (receiver_type() == kGrowableObjectArrayCid) { |
793 const intptr_t kNumTemps = 1; | 795 const intptr_t kNumTemps = 1; |
794 LocationSummary* locs = | 796 LocationSummary* locs = |
795 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 797 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
796 locs->set_in(0, Location::RequiresRegister()); | 798 locs->set_in(0, Location::RequiresRegister()); |
797 locs->set_in(1, Location::RequiresRegister()); | 799 locs->set_in(1, Location::RequiresRegister()); |
798 locs->set_in(2, Location::RequiresRegister()); | 800 locs->set_in(2, Location::RequiresRegister()); |
799 locs->set_temp(0, Location::RequiresRegister()); | 801 locs->set_temp(0, Location::RequiresRegister()); |
800 locs->set_out(Location::NoLocation()); | 802 locs->set_out(Location::NoLocation()); |
801 return locs; | 803 return locs; |
802 } else if (receiver_type() == kArray) { | 804 } else if (receiver_type() == kArrayCid) { |
803 return LocationSummary::Make(kNumInputs, | 805 return LocationSummary::Make(kNumInputs, |
804 Location::NoLocation(), | 806 Location::NoLocation(), |
805 LocationSummary::kNoCall); | 807 LocationSummary::kNoCall); |
806 } else { | 808 } else { |
807 ASSERT(receiver_type() == kIllegalObjectKind); | 809 ASSERT(receiver_type() == kIllegalCid); |
808 return MakeCallSummary(); | 810 return MakeCallSummary(); |
809 } | 811 } |
810 } | 812 } |
811 | 813 |
812 | 814 |
813 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, | 815 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, |
814 StoreIndexedComp* comp) { | 816 StoreIndexedComp* comp) { |
815 const String& function_name = | 817 const String& function_name = |
816 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); | 818 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); |
817 | 819 |
(...skipping 18 matching lines...) Expand all Loading... |
836 StoreIndexedComp* comp) { | 838 StoreIndexedComp* comp) { |
837 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), | 839 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
838 comp->token_pos(), | 840 comp->token_pos(), |
839 comp->try_index(), | 841 comp->try_index(), |
840 kDeoptStoreIndexedPolymorphic); | 842 kDeoptStoreIndexedPolymorphic); |
841 ASSERT(comp->ic_data()->NumberOfChecks() > 0); | 843 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
842 ASSERT(comp->HasICData()); | 844 ASSERT(comp->HasICData()); |
843 const ICData& ic_data = *comp->ic_data(); | 845 const ICData& ic_data = *comp->ic_data(); |
844 ASSERT(ic_data.num_args_tested() == 1); | 846 ASSERT(ic_data.num_args_tested() == 1); |
845 // No indexed access on Smi. | 847 // No indexed access on Smi. |
846 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 848 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmiCid); |
847 // Load receiver into RAX. | 849 // Load receiver into RAX. |
848 const intptr_t kNumArguments = 3; | 850 const intptr_t kNumArguments = 3; |
849 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 851 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
850 __ testq(RAX, Immediate(kSmiTagMask)); | 852 __ testq(RAX, Immediate(kSmiTagMask)); |
851 __ j(ZERO, deopt); | 853 __ j(ZERO, deopt); |
852 __ LoadClassId(RDI, RAX); | 854 __ LoadClassId(RDI, RAX); |
853 compiler->EmitTestAndCall(ic_data, | 855 compiler->EmitTestAndCall(ic_data, |
854 RDI, // Class id register. | 856 RDI, // Class id register. |
855 kNumArguments, | 857 kNumArguments, |
856 Array::Handle(), // No named arguments. | 858 Array::Handle(), // No named arguments. |
857 deopt, // deoptimize label. | 859 deopt, // deoptimize label. |
858 NULL, // fallthrough when done. | 860 NULL, // fallthrough when done. |
859 comp->deopt_id(), | 861 comp->deopt_id(), |
860 comp->token_pos(), | 862 comp->token_pos(), |
861 comp->try_index()); | 863 comp->try_index()); |
862 } | 864 } |
863 | 865 |
864 | 866 |
865 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 867 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
866 if (receiver_type() == kIllegalObjectKind) { | 868 if (receiver_type() == kIllegalCid) { |
867 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 869 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
868 EmitStoreIndexedPolymorphic(compiler, this); | 870 EmitStoreIndexedPolymorphic(compiler, this); |
869 } else { | 871 } else { |
870 EmitStoreIndexedGeneric(compiler, this); | 872 EmitStoreIndexedGeneric(compiler, this); |
871 } | 873 } |
872 return; | 874 return; |
873 } | 875 } |
874 | 876 |
875 Register receiver = locs()->in(0).reg(); | 877 Register receiver = locs()->in(0).reg(); |
876 Register index = locs()->in(1).reg(); | 878 Register index = locs()->in(1).reg(); |
877 Register value = locs()->in(2).reg(); | 879 Register value = locs()->in(2).reg(); |
878 | 880 |
879 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 881 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
880 token_pos(), | 882 token_pos(), |
881 try_index(), | 883 try_index(), |
882 kDeoptStoreIndexed, | 884 kDeoptStoreIndexed, |
883 receiver, | 885 receiver, |
884 index, | 886 index, |
885 value); | 887 value); |
886 | 888 |
887 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 889 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
888 __ j(ZERO, deopt); | 890 __ j(ZERO, deopt); |
889 __ CompareClassId(receiver, receiver_type()); | 891 __ CompareClassId(receiver, receiver_type()); |
890 __ j(NOT_EQUAL, deopt); | 892 __ j(NOT_EQUAL, deopt); |
891 | 893 |
892 __ testq(index, Immediate(kSmiTagMask)); | 894 __ testq(index, Immediate(kSmiTagMask)); |
893 __ j(NOT_ZERO, deopt); | 895 __ j(NOT_ZERO, deopt); |
894 | 896 |
895 switch (receiver_type()) { | 897 switch (receiver_type()) { |
896 case kArray: | 898 case kArrayCid: |
897 case kImmutableArray: | 899 case kImmutableArrayCid: |
898 __ cmpq(index, FieldAddress(receiver, Array::length_offset())); | 900 __ cmpq(index, FieldAddress(receiver, Array::length_offset())); |
899 __ j(ABOVE_EQUAL, deopt); | 901 __ j(ABOVE_EQUAL, deopt); |
900 // Note that index is Smi, i.e, times 4. | 902 // Note that index is Smi, i.e, times 4. |
901 ASSERT(kSmiTagShift == 1); | 903 ASSERT(kSmiTagShift == 1); |
902 __ StoreIntoObject(receiver, | 904 __ StoreIntoObject(receiver, |
903 FieldAddress(receiver, index, TIMES_4, sizeof(RawArray)), | 905 FieldAddress(receiver, index, TIMES_4, sizeof(RawArray)), |
904 value); | 906 value); |
905 break; | 907 break; |
906 | 908 |
907 case kGrowableObjectArray: { | 909 case kGrowableObjectArrayCid: { |
908 Register temp = locs()->temp(0).reg(); | 910 Register temp = locs()->temp(0).reg(); |
909 __ cmpq(index, | 911 __ cmpq(index, |
910 FieldAddress(receiver, GrowableObjectArray::length_offset())); | 912 FieldAddress(receiver, GrowableObjectArray::length_offset())); |
911 __ j(ABOVE_EQUAL, deopt); | 913 __ j(ABOVE_EQUAL, deopt); |
912 __ movq(temp, FieldAddress(receiver, GrowableObjectArray::data_offset())); | 914 __ movq(temp, FieldAddress(receiver, GrowableObjectArray::data_offset())); |
913 // Note that index is Smi, i.e, times 4. | 915 // Note that index is Smi, i.e, times 4. |
914 ASSERT(kSmiTagShift == 1); | 916 ASSERT(kSmiTagShift == 1); |
915 __ StoreIntoObject(temp, | 917 __ StoreIntoObject(temp, |
916 FieldAddress(temp, index, TIMES_4, sizeof(RawArray)), | 918 FieldAddress(temp, index, TIMES_4, sizeof(RawArray)), |
917 value); | 919 value); |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1121 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1123 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1122 } | 1124 } |
1123 // Instantiate non-null type arguments. | 1125 // Instantiate non-null type arguments. |
1124 if (type_arguments().IsUninstantiatedIdentity()) { | 1126 if (type_arguments().IsUninstantiatedIdentity()) { |
1125 // Check if the instantiator type argument vector is a TypeArguments of a | 1127 // Check if the instantiator type argument vector is a TypeArguments of a |
1126 // matching length and, if so, use it as the instantiated type_arguments. | 1128 // matching length and, if so, use it as the instantiated type_arguments. |
1127 // No need to check the instantiator ('instantiator_reg') for null here, | 1129 // No need to check the instantiator ('instantiator_reg') for null here, |
1128 // because a null instantiator will have the wrong class (Null instead of | 1130 // because a null instantiator will have the wrong class (Null instead of |
1129 // TypeArguments). | 1131 // TypeArguments). |
1130 Label type_arguments_uninstantiated; | 1132 Label type_arguments_uninstantiated; |
1131 __ CompareClassId(instantiator_reg, kTypeArguments); | 1133 __ CompareClassId(instantiator_reg, kTypeArgumentsCid); |
1132 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1134 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
1133 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1135 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
1134 Immediate(Smi::RawValue(len))); | 1136 Immediate(Smi::RawValue(len))); |
1135 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1137 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1136 __ Bind(&type_arguments_uninstantiated); | 1138 __ Bind(&type_arguments_uninstantiated); |
1137 } | 1139 } |
1138 // A runtime call to instantiate the type arguments is required. | 1140 // A runtime call to instantiate the type arguments is required. |
1139 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1141 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1140 __ PushObject(type_arguments()); | 1142 __ PushObject(type_arguments()); |
1141 __ pushq(instantiator_reg); // Push instantiator type arguments. | 1143 __ pushq(instantiator_reg); // Push instantiator type arguments. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1182 __ cmpq(instantiator_reg, raw_null); | 1184 __ cmpq(instantiator_reg, raw_null); |
1183 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1185 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1184 } | 1186 } |
1185 // Instantiate non-null type arguments. | 1187 // Instantiate non-null type arguments. |
1186 if (type_arguments().IsUninstantiatedIdentity()) { | 1188 if (type_arguments().IsUninstantiatedIdentity()) { |
1187 // Check if the instantiator type argument vector is a TypeArguments of a | 1189 // Check if the instantiator type argument vector is a TypeArguments of a |
1188 // matching length and, if so, use it as the instantiated type_arguments. | 1190 // matching length and, if so, use it as the instantiated type_arguments. |
1189 // No need to check instantiator_reg for null here, because a null | 1191 // No need to check instantiator_reg for null here, because a null |
1190 // instantiator will have the wrong class (Null instead of TypeArguments). | 1192 // instantiator will have the wrong class (Null instead of TypeArguments). |
1191 Label type_arguments_uninstantiated; | 1193 Label type_arguments_uninstantiated; |
1192 __ CompareClassId(instantiator_reg, kTypeArguments); | 1194 __ CompareClassId(instantiator_reg, kTypeArgumentsCid); |
1193 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1195 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
1194 Immediate arguments_length = | 1196 Immediate arguments_length = |
1195 Immediate(Smi::RawValue(type_arguments().Length())); | 1197 Immediate(Smi::RawValue(type_arguments().Length())); |
1196 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1198 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
1197 arguments_length); | 1199 arguments_length); |
1198 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1200 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1199 __ Bind(&type_arguments_uninstantiated); | 1201 __ Bind(&type_arguments_uninstantiated); |
1200 } | 1202 } |
1201 // In the non-factory case, we rely on the allocation stub to | 1203 // In the non-factory case, we rely on the allocation stub to |
1202 // instantiate the type arguments. | 1204 // instantiate the type arguments. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1249 // TODO(regis): The following emitted code is duplicated in | 1251 // TODO(regis): The following emitted code is duplicated in |
1250 // VisitExtractConstructorTypeArguments above. The reason is that the code | 1252 // VisitExtractConstructorTypeArguments above. The reason is that the code |
1251 // is split between two computations, so that each one produces a | 1253 // is split between two computations, so that each one produces a |
1252 // single value, rather than producing a pair of values. | 1254 // single value, rather than producing a pair of values. |
1253 // If this becomes an issue, we should expose these tests at the IL level. | 1255 // If this becomes an issue, we should expose these tests at the IL level. |
1254 | 1256 |
1255 // Check if the instantiator type argument vector is a TypeArguments of a | 1257 // Check if the instantiator type argument vector is a TypeArguments of a |
1256 // matching length and, if so, use it as the instantiated type_arguments. | 1258 // matching length and, if so, use it as the instantiated type_arguments. |
1257 // No need to check the instantiator (RAX) for null here, because a null | 1259 // No need to check the instantiator (RAX) for null here, because a null |
1258 // instantiator will have the wrong class (Null instead of TypeArguments). | 1260 // instantiator will have the wrong class (Null instead of TypeArguments). |
1259 __ CompareClassId(instantiator_reg, kTypeArguments); | 1261 __ CompareClassId(instantiator_reg, kTypeArgumentsCid); |
1260 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1262 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
1261 Immediate arguments_length = | 1263 Immediate arguments_length = |
1262 Immediate(Smi::RawValue(type_arguments().Length())); | 1264 Immediate(Smi::RawValue(type_arguments().Length())); |
1263 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1265 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
1264 arguments_length); | 1266 arguments_length); |
1265 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1267 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
1266 // The instantiator was used in VisitExtractConstructorTypeArguments as the | 1268 // The instantiator was used in VisitExtractConstructorTypeArguments as the |
1267 // instantiated type arguments, no proper instantiator needed. | 1269 // instantiated type arguments, no proper instantiator needed. |
1268 __ movq(instantiator_reg, | 1270 __ movq(instantiator_reg, |
1269 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 1271 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1548 __ shlq(left, right_temp); | 1550 __ shlq(left, right_temp); |
1549 __ sarq(left, right_temp); | 1551 __ sarq(left, right_temp); |
1550 __ cmpq(left, temp); | 1552 __ cmpq(left, temp); |
1551 __ j(NOT_EQUAL, &call_method, Assembler::kNearJump); // Overflow. | 1553 __ j(NOT_EQUAL, &call_method, Assembler::kNearJump); // Overflow. |
1552 // Shift for result now we know there is no overflow. | 1554 // Shift for result now we know there is no overflow. |
1553 __ shlq(left, right_temp); | 1555 __ shlq(left, right_temp); |
1554 __ jmp(&done); | 1556 __ jmp(&done); |
1555 { | 1557 { |
1556 __ Bind(&call_method); | 1558 __ Bind(&call_method); |
1557 Function& target = Function::ZoneHandle( | 1559 Function& target = Function::ZoneHandle( |
1558 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1560 comp->ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
1559 ASSERT(!target.IsNull()); | 1561 ASSERT(!target.IsNull()); |
1560 const intptr_t kArgumentCount = 2; | 1562 const intptr_t kArgumentCount = 2; |
1561 __ pushq(temp); | 1563 __ pushq(temp); |
1562 __ pushq(right); | 1564 __ pushq(right); |
1563 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), | 1565 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
1564 comp->instance_call()->token_pos(), | 1566 comp->instance_call()->token_pos(), |
1565 comp->instance_call()->try_index(), | 1567 comp->instance_call()->try_index(), |
1566 target, | 1568 target, |
1567 kArgumentCount, | 1569 kArgumentCount, |
1568 Array::Handle()); // No argument names. | 1570 Array::Handle()); // No argument names. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1610 comp->instance_call()->token_pos(), | 1612 comp->instance_call()->token_pos(), |
1611 comp->instance_call()->try_index(), | 1613 comp->instance_call()->try_index(), |
1612 kDeoptMintBinaryOp, | 1614 kDeoptMintBinaryOp, |
1613 left, | 1615 left, |
1614 right); | 1616 right); |
1615 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1617 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
1616 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1618 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
1617 __ j(NOT_ZERO, &non_smi); | 1619 __ j(NOT_ZERO, &non_smi); |
1618 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1620 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
1619 __ j(ZERO, &smi_smi); | 1621 __ j(ZERO, &smi_smi); |
1620 __ CompareClassId(right, kMint); // Is argument Mint? | 1622 __ CompareClassId(right, kMintCid); // Is argument Mint? |
1621 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. | 1623 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. |
1622 __ cmpq(left, Immediate(0)); | 1624 __ cmpq(left, Immediate(0)); |
1623 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. | 1625 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. |
1624 | 1626 |
1625 // Positive Smi receiver, Mint argument. | 1627 // Positive Smi receiver, Mint argument. |
1626 // Load lower argument Mint word, convert to Smi. It is OK to loose bits. | 1628 // Load lower argument Mint word, convert to Smi. It is OK to loose bits. |
1627 __ movq(right, FieldAddress(right, Mint::value_offset())); | 1629 __ movq(right, FieldAddress(right, Mint::value_offset())); |
1628 __ SmiTag(right); | 1630 __ SmiTag(right); |
1629 __ andq(result, right); | 1631 __ andq(result, right); |
1630 __ jmp(&done); | 1632 __ jmp(&done); |
1631 | 1633 |
1632 __ Bind(&non_smi); // Receiver is non-Smi. | 1634 __ Bind(&non_smi); // Receiver is non-Smi. |
1633 __ CompareClassId(left, kMint); // Is receiver Mint? | 1635 __ CompareClassId(left, kMintCid); // Is receiver Mint? |
1634 __ j(NOT_EQUAL, deopt); // Receiver neither Smi nor Mint. | 1636 __ j(NOT_EQUAL, deopt); // Receiver neither Smi nor Mint. |
1635 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1637 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
1636 __ j(NOT_ZERO, &mint_static_call); // Mint receiver, non-Smi argument. | 1638 __ j(NOT_ZERO, &mint_static_call); // Mint receiver, non-Smi argument. |
1637 __ cmpq(right, Immediate(0)); | 1639 __ cmpq(right, Immediate(0)); |
1638 __ j(LESS, &mint_static_call); // Mint receiver, negative Smi argument. | 1640 __ j(LESS, &mint_static_call); // Mint receiver, negative Smi argument. |
1639 | 1641 |
1640 // Mint receiver, positive Smi argument. | 1642 // Mint receiver, positive Smi argument. |
1641 // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. | 1643 // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. |
1642 __ movq(result, FieldAddress(left, Mint::value_offset())); | 1644 __ movq(result, FieldAddress(left, Mint::value_offset())); |
1643 __ SmiTag(result); | 1645 __ SmiTag(result); |
1644 __ Bind(&smi_smi); | 1646 __ Bind(&smi_smi); |
1645 __ andq(result, right); | 1647 __ andq(result, right); |
1646 __ jmp(&done); | 1648 __ jmp(&done); |
1647 | 1649 |
1648 __ Bind(&smi_static_call); | 1650 __ Bind(&smi_static_call); |
1649 { | 1651 { |
1650 Function& target = Function::ZoneHandle( | 1652 Function& target = Function::ZoneHandle( |
1651 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1653 comp->ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
1652 if (target.IsNull()) { | 1654 if (target.IsNull()) { |
1653 __ jmp(deopt); | 1655 __ jmp(deopt); |
1654 } else { | 1656 } else { |
1655 __ pushq(left); | 1657 __ pushq(left); |
1656 __ pushq(right); | 1658 __ pushq(right); |
1657 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), | 1659 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
1658 comp->instance_call()->token_pos(), | 1660 comp->instance_call()->token_pos(), |
1659 comp->instance_call()->try_index(), | 1661 comp->instance_call()->try_index(), |
1660 target, | 1662 target, |
1661 comp->instance_call()->ArgumentCount(), | 1663 comp->instance_call()->ArgumentCount(), |
1662 comp->instance_call()->argument_names()); | 1664 comp->instance_call()->argument_names()); |
1663 ASSERT(result == RAX); | 1665 ASSERT(result == RAX); |
1664 __ jmp(&done); | 1666 __ jmp(&done); |
1665 } | 1667 } |
1666 } | 1668 } |
1667 | 1669 |
1668 __ Bind(&mint_static_call); | 1670 __ Bind(&mint_static_call); |
1669 { | 1671 { |
1670 Function& target = Function::ZoneHandle( | 1672 Function& target = Function::ZoneHandle( |
1671 comp->ic_data()->GetTargetForReceiverClassId(kMint)); | 1673 comp->ic_data()->GetTargetForReceiverClassId(kMintCid)); |
1672 if (target.IsNull()) { | 1674 if (target.IsNull()) { |
1673 __ jmp(deopt); | 1675 __ jmp(deopt); |
1674 } else { | 1676 } else { |
1675 __ pushq(left); | 1677 __ pushq(left); |
1676 __ pushq(right); | 1678 __ pushq(right); |
1677 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), | 1679 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
1678 comp->instance_call()->token_pos(), | 1680 comp->instance_call()->token_pos(), |
1679 comp->instance_call()->try_index(), | 1681 comp->instance_call()->try_index(), |
1680 target, | 1682 target, |
1681 comp->instance_call()->ArgumentCount(), | 1683 comp->instance_call()->ArgumentCount(), |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1777 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1779 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
1778 | 1780 |
1779 Register value = locs()->in(0).reg(); | 1781 Register value = locs()->in(0).reg(); |
1780 Register result = locs()->out().reg(); | 1782 Register result = locs()->out().reg(); |
1781 ASSERT(value == result); | 1783 ASSERT(value == result); |
1782 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1784 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1783 instance_call()->token_pos(), | 1785 instance_call()->token_pos(), |
1784 instance_call()->try_index(), | 1786 instance_call()->try_index(), |
1785 kDeoptUnaryOp, | 1787 kDeoptUnaryOp, |
1786 value); | 1788 value); |
1787 if (test_class_id == kSmi) { | 1789 if (test_class_id == kSmiCid) { |
1788 __ testq(value, Immediate(kSmiTagMask)); | 1790 __ testq(value, Immediate(kSmiTagMask)); |
1789 __ j(NOT_ZERO, deopt); | 1791 __ j(NOT_ZERO, deopt); |
1790 switch (op_kind()) { | 1792 switch (op_kind()) { |
1791 case Token::kNEGATE: | 1793 case Token::kNEGATE: |
1792 __ negq(value); | 1794 __ negq(value); |
1793 __ j(OVERFLOW, deopt); | 1795 __ j(OVERFLOW, deopt); |
1794 break; | 1796 break; |
1795 case Token::kBIT_NOT: | 1797 case Token::kBIT_NOT: |
1796 __ notq(value); | 1798 __ notq(value); |
1797 __ andq(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. | 1799 __ andq(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1829 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1831 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
1830 | 1832 |
1831 Register value = locs()->in(0).reg(); | 1833 Register value = locs()->in(0).reg(); |
1832 Register result = locs()->out().reg(); | 1834 Register result = locs()->out().reg(); |
1833 ASSERT(value == result); | 1835 ASSERT(value == result); |
1834 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1836 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1835 instance_call()->token_pos(), | 1837 instance_call()->token_pos(), |
1836 instance_call()->try_index(), | 1838 instance_call()->try_index(), |
1837 kDeoptUnaryOp, | 1839 kDeoptUnaryOp, |
1838 value); | 1840 value); |
1839 if (test_class_id == kDouble) { | 1841 if (test_class_id == kDoubleCid) { |
1840 Register temp = locs()->temp(0).reg(); | 1842 Register temp = locs()->temp(0).reg(); |
1841 __ testq(value, Immediate(kSmiTagMask)); | 1843 __ testq(value, Immediate(kSmiTagMask)); |
1842 __ j(ZERO, deopt); // Smi. | 1844 __ j(ZERO, deopt); // Smi. |
1843 __ CompareClassId(value, kDouble); | 1845 __ CompareClassId(value, kDoubleCid); |
1844 __ j(NOT_EQUAL, deopt); | 1846 __ j(NOT_EQUAL, deopt); |
1845 // Allocate result object. | 1847 // Allocate result object. |
1846 const Class& double_class = compiler->double_class(); | 1848 const Class& double_class = compiler->double_class(); |
1847 const Code& stub = | 1849 const Code& stub = |
1848 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1850 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1849 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1851 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1850 __ pushq(value); | 1852 __ pushq(value); |
1851 compiler->GenerateCall(instance_call()->token_pos(), | 1853 compiler->GenerateCall(instance_call()->token_pos(), |
1852 instance_call()->try_index(), | 1854 instance_call()->try_index(), |
1853 &label, | 1855 &label, |
1854 PcDescriptors::kOther); | 1856 PcDescriptors::kOther); |
1855 // Result is in RAX. | 1857 // Result is in RAX. |
1856 ASSERT(result != temp); | 1858 ASSERT(result != temp); |
1857 __ movq(result, RAX); | 1859 __ movq(result, RAX); |
1858 __ popq(temp); | 1860 __ popq(temp); |
1859 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 1861 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
1860 __ DoubleNegate(XMM0); | 1862 __ DoubleNegate(XMM0); |
1861 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1863 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
1862 } else { | 1864 } else { |
1863 UNREACHABLE(); | 1865 UNREACHABLE(); |
1864 } | 1866 } |
1865 } | 1867 } |
1866 | 1868 |
1867 | 1869 |
1868 LocationSummary* ToDoubleComp::MakeLocationSummary() const { | 1870 LocationSummary* ToDoubleComp::MakeLocationSummary() const { |
1869 const intptr_t kNumInputs = 1; | 1871 const intptr_t kNumInputs = 1; |
1870 if (from() == kDouble) { | 1872 if (from() == kDoubleCid) { |
1871 const intptr_t kNumTemps = 0; | 1873 const intptr_t kNumTemps = 0; |
1872 LocationSummary* locs = | 1874 LocationSummary* locs = |
1873 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1875 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1874 locs->set_in(0, Location::RequiresRegister()); | 1876 locs->set_in(0, Location::RequiresRegister()); |
1875 locs->set_out(Location::SameAsFirstInput()); | 1877 locs->set_out(Location::SameAsFirstInput()); |
1876 return locs; | 1878 return locs; |
1877 } else { | 1879 } else { |
1878 ASSERT(from() == kSmi); | 1880 ASSERT(from() == kSmiCid); |
1879 return MakeCallSummary(); // Calls a stub to allocate result. | 1881 return MakeCallSummary(); // Calls a stub to allocate result. |
1880 } | 1882 } |
1881 } | 1883 } |
1882 | 1884 |
1883 | 1885 |
1884 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1886 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1885 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; | 1887 Register value = (from() == kDoubleCid) ? locs()->in(0).reg() : RBX; |
1886 Register result = locs()->out().reg(); | 1888 Register result = locs()->out().reg(); |
1887 | 1889 |
1888 const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1890 const DeoptReasonId deopt_reason = (from() == kDoubleCid) ? |
1889 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1891 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
1890 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1892 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1891 instance_call()->token_pos(), | 1893 instance_call()->token_pos(), |
1892 instance_call()->try_index(), | 1894 instance_call()->try_index(), |
1893 deopt_reason, | 1895 deopt_reason, |
1894 value); | 1896 value); |
1895 | 1897 |
1896 if (from() == kDouble) { | 1898 if (from() == kDoubleCid) { |
1897 __ testq(value, Immediate(kSmiTagMask)); | 1899 __ testq(value, Immediate(kSmiTagMask)); |
1898 __ j(ZERO, deopt); // Deoptimize if Smi. | 1900 __ j(ZERO, deopt); // Deoptimize if Smi. |
1899 __ CompareClassId(value, kDouble); | 1901 __ CompareClassId(value, kDoubleCid); |
1900 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 1902 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
1901 ASSERT(value == result); | 1903 ASSERT(value == result); |
1902 return; | 1904 return; |
1903 } | 1905 } |
1904 | 1906 |
1905 ASSERT(from() == kSmi); | 1907 ASSERT(from() == kSmiCid); |
1906 | 1908 |
1907 const Class& double_class = compiler->double_class(); | 1909 const Class& double_class = compiler->double_class(); |
1908 const Code& stub = | 1910 const Code& stub = |
1909 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1911 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1910 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1912 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1911 | 1913 |
1912 // TODO(vegorov): allocate box in the driver loop to avoid spilling. | 1914 // TODO(vegorov): allocate box in the driver loop to avoid spilling. |
1913 compiler->GenerateCall(instance_call()->token_pos(), | 1915 compiler->GenerateCall(instance_call()->token_pos(), |
1914 instance_call()->try_index(), | 1916 instance_call()->try_index(), |
1915 &label, | 1917 &label, |
(...skipping 20 matching lines...) Expand all Loading... |
1936 instance_call()->try_index(), | 1938 instance_call()->try_index(), |
1937 kDeoptPolymorphicInstanceCallTestFail); | 1939 kDeoptPolymorphicInstanceCallTestFail); |
1938 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 1940 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
1939 __ jmp(deopt); | 1941 __ jmp(deopt); |
1940 return; | 1942 return; |
1941 } | 1943 } |
1942 ASSERT(HasICData()); | 1944 ASSERT(HasICData()); |
1943 ASSERT(ic_data()->num_args_tested() == 1); | 1945 ASSERT(ic_data()->num_args_tested() == 1); |
1944 Label handle_smi; | 1946 Label handle_smi; |
1945 Label* is_smi_label = | 1947 Label* is_smi_label = |
1946 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; | 1948 ic_data()->GetReceiverClassIdAt(0) == kSmiCid ? &handle_smi : deopt; |
1947 | 1949 |
1948 // Load receiver into RAX. | 1950 // Load receiver into RAX. |
1949 __ movq(RAX, | 1951 __ movq(RAX, |
1950 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 1952 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
1951 __ testq(RAX, Immediate(kSmiTagMask)); | 1953 __ testq(RAX, Immediate(kSmiTagMask)); |
1952 __ j(ZERO, is_smi_label); | 1954 __ j(ZERO, is_smi_label); |
1953 Label done; | 1955 Label done; |
1954 __ LoadClassId(RDI, RAX); | 1956 __ LoadClassId(RDI, RAX); |
1955 compiler->EmitTestAndCall(*ic_data(), | 1957 compiler->EmitTestAndCall(*ic_data(), |
1956 RDI, // Class id register. | 1958 RDI, // Class id register. |
1957 instance_call()->ArgumentCount(), | 1959 instance_call()->ArgumentCount(), |
1958 instance_call()->argument_names(), | 1960 instance_call()->argument_names(), |
1959 deopt, | 1961 deopt, |
1960 (is_smi_label == &handle_smi) ? &done : NULL, | 1962 (is_smi_label == &handle_smi) ? &done : NULL, |
1961 instance_call()->deopt_id(), | 1963 instance_call()->deopt_id(), |
1962 instance_call()->token_pos(), | 1964 instance_call()->token_pos(), |
1963 instance_call()->try_index()); | 1965 instance_call()->try_index()); |
1964 if (is_smi_label == &handle_smi) { | 1966 if (is_smi_label == &handle_smi) { |
1965 __ Bind(&handle_smi); | 1967 __ Bind(&handle_smi); |
1966 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); | 1968 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmiCid); |
1967 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1969 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
1968 compiler->GenerateStaticCall(instance_call()->deopt_id(), | 1970 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
1969 instance_call()->token_pos(), | 1971 instance_call()->token_pos(), |
1970 instance_call()->try_index(), | 1972 instance_call()->try_index(), |
1971 target, | 1973 target, |
1972 instance_call()->ArgumentCount(), | 1974 instance_call()->ArgumentCount(), |
1973 instance_call()->argument_names()); | 1975 instance_call()->argument_names()); |
1974 } | 1976 } |
1975 __ Bind(&done); | 1977 __ Bind(&done); |
1976 } | 1978 } |
(...skipping 14 matching lines...) Expand all Loading... |
1991 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) { | 1993 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) { |
1992 const int kNumInputs = 2; | 1994 const int kNumInputs = 2; |
1993 const int kNumTemps = 0; | 1995 const int kNumTemps = 0; |
1994 LocationSummary* locs = | 1996 LocationSummary* locs = |
1995 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1997 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1996 locs->set_in(0, Location::RequiresRegister()); | 1998 locs->set_in(0, Location::RequiresRegister()); |
1997 locs->set_in(1, Location::RequiresRegister()); | 1999 locs->set_in(1, Location::RequiresRegister()); |
1998 return locs; | 2000 return locs; |
1999 } | 2001 } |
2000 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 2002 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
2001 if (ICDataWithBothClassIds(*ic_data(), kSmi) || | 2003 if (ICDataWithBothClassIds(*ic_data(), kSmiCid) || |
2002 ICDataWithBothClassIds(*ic_data(), kDouble)) { | 2004 ICDataWithBothClassIds(*ic_data(), kDoubleCid)) { |
2003 const intptr_t kNumInputs = 2; | 2005 const intptr_t kNumInputs = 2; |
2004 const intptr_t kNumTemps = 1; | 2006 const intptr_t kNumTemps = 1; |
2005 LocationSummary* summary = | 2007 LocationSummary* summary = |
2006 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2008 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2007 summary->set_in(0, Location::RequiresRegister()); | 2009 summary->set_in(0, Location::RequiresRegister()); |
2008 summary->set_in(1, Location::RequiresRegister()); | 2010 summary->set_in(1, Location::RequiresRegister()); |
2009 summary->set_temp(0, Location::RequiresRegister()); | 2011 summary->set_temp(0, Location::RequiresRegister()); |
2010 return summary; | 2012 return summary; |
2011 } | 2013 } |
2012 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { | 2014 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { |
(...skipping 17 matching lines...) Expand all Loading... |
2030 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) { | 2032 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) { |
2031 Register left = locs()->in(0).reg(); | 2033 Register left = locs()->in(0).reg(); |
2032 Register right = locs()->in(1).reg(); | 2034 Register right = locs()->in(1).reg(); |
2033 __ cmpq(left, right); | 2035 __ cmpq(left, right); |
2034 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 2036 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
2035 EmitBranchOnCondition(compiler, cond); | 2037 EmitBranchOnCondition(compiler, cond); |
2036 return; | 2038 return; |
2037 } | 2039 } |
2038 // Relational or equality. | 2040 // Relational or equality. |
2039 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 2041 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
2040 if (ICDataWithBothClassIds(*ic_data(), kSmi)) { | 2042 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) { |
2041 EmitSmiComparisonOp(compiler, *locs(), kind(), this, | 2043 EmitSmiComparisonOp(compiler, *locs(), kind(), this, |
2042 deopt_id(), token_pos(), try_index()); | 2044 deopt_id(), token_pos(), try_index()); |
2043 return; | 2045 return; |
2044 } | 2046 } |
2045 if (ICDataWithBothClassIds(*ic_data(), kDouble)) { | 2047 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) { |
2046 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, | 2048 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, |
2047 deopt_id(), token_pos(), try_index()); | 2049 deopt_id(), token_pos(), try_index()); |
2048 return; | 2050 return; |
2049 } | 2051 } |
2050 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. | 2052 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. |
2051 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { | 2053 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { |
2052 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), | 2054 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), |
2053 deopt_id(), token_pos(), try_index()); | 2055 deopt_id(), token_pos(), try_index()); |
2054 return; | 2056 return; |
2055 } | 2057 } |
(...skipping 20 matching lines...) Expand all Loading... |
2076 ASSERT(locs()->out().reg() == RAX); | 2078 ASSERT(locs()->out().reg() == RAX); |
2077 __ CompareObject(locs()->out().reg(), compiler->bool_true()); | 2079 __ CompareObject(locs()->out().reg(), compiler->bool_true()); |
2078 EmitBranchOnCondition(compiler, branch_condition); | 2080 EmitBranchOnCondition(compiler, branch_condition); |
2079 } | 2081 } |
2080 | 2082 |
2081 } // namespace dart | 2083 } // namespace dart |
2082 | 2084 |
2083 #undef __ | 2085 #undef __ |
2084 | 2086 |
2085 #endif // defined TARGET_ARCH_X64 | 2087 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |