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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
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 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 case Token::kGTE: return GREATER_EQUAL; | 235 case Token::kGTE: return GREATER_EQUAL; |
236 default: | 236 default: |
237 UNREACHABLE(); | 237 UNREACHABLE(); |
238 return OVERFLOW; | 238 return OVERFLOW; |
239 } | 239 } |
240 } | 240 } |
241 | 241 |
242 | 242 |
243 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { | 243 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { |
244 const intptr_t kNumInputs = 2; | 244 const intptr_t kNumInputs = 2; |
245 if (receiver_class_id() != kObject) { | 245 if (receiver_class_id() != kObjectCid) { |
246 ASSERT((receiver_class_id() == kSmi) || (receiver_class_id() == kDouble)); | 246 ASSERT((receiver_class_id() == kSmiCid) || |
| 247 (receiver_class_id() == kDoubleCid)); |
247 const intptr_t kNumTemps = 1; | 248 const intptr_t kNumTemps = 1; |
248 LocationSummary* locs = | 249 LocationSummary* locs = |
249 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 250 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
250 locs->set_in(0, Location::RequiresRegister()); | 251 locs->set_in(0, Location::RequiresRegister()); |
251 locs->set_in(1, Location::RequiresRegister()); | 252 locs->set_in(1, Location::RequiresRegister()); |
252 locs->set_temp(0, Location::RequiresRegister()); | 253 locs->set_temp(0, Location::RequiresRegister()); |
253 locs->set_out(Location::RequiresRegister()); | 254 locs->set_out(Location::RequiresRegister()); |
254 return locs; | 255 return locs; |
255 } | 256 } |
256 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 257 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 ASSERT(ic_data.NumberOfChecks() > 0); | 319 ASSERT(ic_data.NumberOfChecks() > 0); |
319 ASSERT(ic_data.num_args_tested() == 1); | 320 ASSERT(ic_data.num_args_tested() == 1); |
320 Label* deopt = compiler->AddDeoptStub(deopt_id, | 321 Label* deopt = compiler->AddDeoptStub(deopt_id, |
321 token_pos, | 322 token_pos, |
322 try_index, | 323 try_index, |
323 kDeoptEquality); | 324 kDeoptEquality); |
324 Register left = locs.in(0).reg(); | 325 Register left = locs.in(0).reg(); |
325 Register right = locs.in(1).reg(); | 326 Register right = locs.in(1).reg(); |
326 __ testl(left, Immediate(kSmiTagMask)); | 327 __ testl(left, Immediate(kSmiTagMask)); |
327 Register temp = locs.temp(0).reg(); | 328 Register temp = locs.temp(0).reg(); |
328 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { | 329 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { |
329 Label done, load_class_id; | 330 Label done, load_class_id; |
330 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 331 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
331 __ movl(temp, Immediate(kSmi)); | 332 __ movl(temp, Immediate(kSmiCid)); |
332 __ jmp(&done, Assembler::kNearJump); | 333 __ jmp(&done, Assembler::kNearJump); |
333 __ Bind(&load_class_id); | 334 __ Bind(&load_class_id); |
334 __ LoadClassId(temp, left); | 335 __ LoadClassId(temp, left); |
335 __ Bind(&done); | 336 __ Bind(&done); |
336 } else { | 337 } else { |
337 __ j(ZERO, deopt); // Smi deopts. | 338 __ j(ZERO, deopt); // Smi deopts. |
338 __ LoadClassId(temp, left); | 339 __ LoadClassId(temp, left); |
339 } | 340 } |
340 Condition cond = TokenKindToSmiCondition(kind); | 341 Condition cond = TokenKindToSmiCondition(kind); |
341 Label done; | 342 Label done; |
342 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 343 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
343 ASSERT((ic_data.GetReceiverClassIdAt(i) != kSmi) || (i == 0)); | 344 ASSERT((ic_data.GetReceiverClassIdAt(i) != kSmiCid) || (i == 0)); |
344 Label next_test; | 345 Label next_test; |
345 __ cmpl(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); | 346 __ cmpl(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); |
346 __ j(NOT_EQUAL, &next_test); | 347 __ j(NOT_EQUAL, &next_test); |
347 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); | 348 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); |
348 ObjectStore* object_store = Isolate::Current()->object_store(); | 349 ObjectStore* object_store = Isolate::Current()->object_store(); |
349 if (target.owner() == object_store->object_class()) { | 350 if (target.owner() == object_store->object_class()) { |
350 // Object.== is same as ===. | 351 // Object.== is same as ===. |
351 __ Drop(2); | 352 __ Drop(2); |
352 __ cmpl(left, right); | 353 __ cmpl(left, right); |
353 if (branch != NULL) { | 354 if (branch != NULL) { |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 compiler->EmitDoubleCompareBranch( | 520 compiler->EmitDoubleCompareBranch( |
520 true_condition, XMM0, XMM1, branch); | 521 true_condition, XMM0, XMM1, branch); |
521 } else { | 522 } else { |
522 compiler->EmitDoubleCompareBool( | 523 compiler->EmitDoubleCompareBool( |
523 true_condition, XMM0, XMM1, locs.out().reg()); | 524 true_condition, XMM0, XMM1, locs.out().reg()); |
524 } | 525 } |
525 } | 526 } |
526 | 527 |
527 | 528 |
528 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 529 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
529 if (receiver_class_id() == kSmi) { | 530 if (receiver_class_id() == kSmiCid) { |
530 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. | 531 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. |
531 deopt_id(), token_pos(), try_index()); | 532 deopt_id(), token_pos(), try_index()); |
532 return; | 533 return; |
533 } | 534 } |
534 if (receiver_class_id() == kDouble) { | 535 if (receiver_class_id() == kDoubleCid) { |
535 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. | 536 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. |
536 deopt_id(), token_pos(), try_index()); | 537 deopt_id(), token_pos(), try_index()); |
537 return; | 538 return; |
538 } | 539 } |
539 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 540 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
540 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, *ic_data(), | 541 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, *ic_data(), |
541 deopt_id(), token_pos(), try_index()); | 542 deopt_id(), token_pos(), try_index()); |
542 } else { | 543 } else { |
543 Register left = locs()->in(0).reg(); | 544 Register left = locs()->in(0).reg(); |
544 Register right = locs()->in(1).reg(); | 545 Register right = locs()->in(1).reg(); |
545 __ pushl(left); | 546 __ pushl(left); |
546 __ pushl(right); | 547 __ pushl(right); |
547 EmitEqualityAsInstanceCall(compiler, this); | 548 EmitEqualityAsInstanceCall(compiler, this); |
548 } | 549 } |
549 } | 550 } |
550 | 551 |
551 | 552 |
552 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 553 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
553 if ((operands_class_id() == kSmi) || (operands_class_id() == kDouble)) { | 554 if ((operands_class_id() == kSmiCid) || (operands_class_id() == kDoubleCid)) { |
554 const intptr_t kNumInputs = 2; | 555 const intptr_t kNumInputs = 2; |
555 const intptr_t kNumTemps = 1; | 556 const intptr_t kNumTemps = 1; |
556 LocationSummary* summary = | 557 LocationSummary* summary = |
557 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 558 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
558 summary->set_in(0, Location::RequiresRegister()); | 559 summary->set_in(0, Location::RequiresRegister()); |
559 summary->set_in(1, Location::RequiresRegister()); | 560 summary->set_in(1, Location::RequiresRegister()); |
560 summary->set_out(Location::RequiresRegister()); | 561 summary->set_out(Location::RequiresRegister()); |
561 summary->set_temp(0, Location::RequiresRegister()); | 562 summary->set_temp(0, Location::RequiresRegister()); |
562 return summary; | 563 return summary; |
563 } | 564 } |
564 ASSERT(operands_class_id() == kObject); | 565 ASSERT(operands_class_id() == kObjectCid); |
565 return MakeCallSummary(); | 566 return MakeCallSummary(); |
566 } | 567 } |
567 | 568 |
568 | 569 |
569 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 570 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
570 if (operands_class_id() == kSmi) { | 571 if (operands_class_id() == kSmiCid) { |
571 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, | 572 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, |
572 deopt_id(), token_pos(), try_index()); | 573 deopt_id(), token_pos(), try_index()); |
573 return; | 574 return; |
574 } | 575 } |
575 if (operands_class_id() == kDouble) { | 576 if (operands_class_id() == kDoubleCid) { |
576 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, | 577 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, |
577 deopt_id(), token_pos(), try_index()); | 578 deopt_id(), token_pos(), try_index()); |
578 return; | 579 return; |
579 } | 580 } |
580 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 581 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
581 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 582 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
582 token_pos(), | 583 token_pos(), |
583 try_index(), | 584 try_index(), |
584 kDeoptRelationalOp); | 585 kDeoptRelationalOp); |
585 // Load receiver into EAX, class into EDI. | 586 // Load receiver into EAX, class into EDI. |
586 Label done; | 587 Label done; |
587 const intptr_t kNumArguments = 2; | 588 const intptr_t kNumArguments = 2; |
588 __ movl(EDI, Immediate(kSmi)); | 589 __ movl(EDI, Immediate(kSmiCid)); |
589 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); | 590 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
590 __ testl(EAX, Immediate(kSmiTagMask)); | 591 __ testl(EAX, Immediate(kSmiTagMask)); |
591 __ j(ZERO, &done); | 592 __ j(ZERO, &done); |
592 __ LoadClassId(EDI, EAX); | 593 __ LoadClassId(EDI, EAX); |
593 __ Bind(&done); | 594 __ Bind(&done); |
594 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), | 595 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), |
595 EDI, // Class id register. | 596 EDI, // Class id register. |
596 kNumArguments, | 597 kNumArguments, |
597 Array::Handle(), // No named arguments. | 598 Array::Handle(), // No named arguments. |
598 deopt, // Deoptimize target. | 599 deopt, // Deoptimize target. |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
658 compiler->GenerateCall(token_pos(), | 659 compiler->GenerateCall(token_pos(), |
659 try_index(), | 660 try_index(), |
660 &StubCode::CallNativeCFunctionLabel(), | 661 &StubCode::CallNativeCFunctionLabel(), |
661 PcDescriptors::kOther); | 662 PcDescriptors::kOther); |
662 __ popl(result); | 663 __ popl(result); |
663 } | 664 } |
664 | 665 |
665 | 666 |
666 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 667 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { |
667 const intptr_t kNumInputs = 2; | 668 const intptr_t kNumInputs = 2; |
668 if ((receiver_type() == kGrowableObjectArray) || | 669 if ((receiver_type() == kGrowableObjectArrayCid) || |
669 (receiver_type() == kArray) || | 670 (receiver_type() == kArrayCid) || |
670 (receiver_type() == kImmutableArray)) { | 671 (receiver_type() == kImmutableArrayCid)) { |
671 const intptr_t kNumTemps = 1; | 672 const intptr_t kNumTemps = 1; |
672 LocationSummary* locs = | 673 LocationSummary* locs = |
673 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 674 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
674 locs->set_in(0, Location::RequiresRegister()); | 675 locs->set_in(0, Location::RequiresRegister()); |
675 locs->set_in(1, Location::RequiresRegister()); | 676 locs->set_in(1, Location::RequiresRegister()); |
676 locs->set_temp(0, Location::RequiresRegister()); | 677 locs->set_temp(0, Location::RequiresRegister()); |
677 locs->set_out(Location::RequiresRegister()); | 678 locs->set_out(Location::RequiresRegister()); |
678 return locs; | 679 return locs; |
679 } else { | 680 } else { |
680 ASSERT(receiver_type() == kIllegalObjectKind); | 681 ASSERT(receiver_type() == kIllegalCid); |
681 return MakeCallSummary(); | 682 return MakeCallSummary(); |
682 } | 683 } |
683 } | 684 } |
684 | 685 |
685 | 686 |
686 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, | 687 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, |
687 LoadIndexedComp* comp) { | 688 LoadIndexedComp* comp) { |
688 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), | 689 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
689 comp->token_pos(), | 690 comp->token_pos(), |
690 comp->try_index(), | 691 comp->try_index(), |
691 kDeoptLoadIndexedPolymorphic); | 692 kDeoptLoadIndexedPolymorphic); |
692 ASSERT(comp->ic_data()->NumberOfChecks() > 0); | 693 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
693 ASSERT(comp->HasICData()); | 694 ASSERT(comp->HasICData()); |
694 const ICData& ic_data = *comp->ic_data(); | 695 const ICData& ic_data = *comp->ic_data(); |
695 ASSERT(ic_data.num_args_tested() == 1); | 696 ASSERT(ic_data.num_args_tested() == 1); |
696 // No indexed access on Smi. | 697 // No indexed access on Smi. |
697 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 698 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmiCid); |
698 // Load receiver into EAX. | 699 // Load receiver into EAX. |
699 const intptr_t kNumArguments = 2; | 700 const intptr_t kNumArguments = 2; |
700 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); | 701 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
701 __ testl(EAX, Immediate(kSmiTagMask)); | 702 __ testl(EAX, Immediate(kSmiTagMask)); |
702 __ j(ZERO, deopt); | 703 __ j(ZERO, deopt); |
703 __ LoadClassId(EDI, EAX); | 704 __ LoadClassId(EDI, EAX); |
704 compiler->EmitTestAndCall(ic_data, | 705 compiler->EmitTestAndCall(ic_data, |
705 EDI, // Class id register. | 706 EDI, // Class id register. |
706 kNumArguments, | 707 kNumArguments, |
707 Array::Handle(), // No named arguments. | 708 Array::Handle(), // No named arguments. |
708 deopt, // Deoptimize target. | 709 deopt, // Deoptimize target. |
709 NULL, // Fallthrough when done. | 710 NULL, // Fallthrough when done. |
710 comp->deopt_id(), | 711 comp->deopt_id(), |
711 comp->token_pos(), | 712 comp->token_pos(), |
712 comp->try_index()); | 713 comp->try_index()); |
713 } | 714 } |
714 | 715 |
715 | 716 |
716 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 717 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
717 if (receiver_type() == kIllegalObjectKind) { | 718 if (receiver_type() == kIllegalCid) { |
718 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 719 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
719 EmitLoadIndexedPolymorphic(compiler, this); | 720 EmitLoadIndexedPolymorphic(compiler, this); |
720 } else { | 721 } else { |
721 compiler->EmitLoadIndexedGeneric(this); | 722 compiler->EmitLoadIndexedGeneric(this); |
722 } | 723 } |
723 ASSERT(locs()->out().reg() == EAX); | 724 ASSERT(locs()->out().reg() == EAX); |
724 return; | 725 return; |
725 } | 726 } |
726 | 727 |
727 Register receiver = locs()->in(0).reg(); | 728 Register receiver = locs()->in(0).reg(); |
728 Register index = locs()->in(1).reg(); | 729 Register index = locs()->in(1).reg(); |
729 Register result = locs()->out().reg(); | 730 Register result = locs()->out().reg(); |
730 Register temp = locs()->temp(0).reg(); | 731 Register temp = locs()->temp(0).reg(); |
731 | 732 |
732 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? | 733 const DeoptReasonId deopt_reason = |
| 734 (receiver_type() == kGrowableObjectArrayCid) ? |
733 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 735 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
734 | 736 |
735 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 737 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
736 token_pos(), | 738 token_pos(), |
737 try_index(), | 739 try_index(), |
738 deopt_reason, | 740 deopt_reason, |
739 receiver, | 741 receiver, |
740 index); | 742 index); |
741 | 743 |
742 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 744 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
743 __ j(ZERO, deopt); | 745 __ j(ZERO, deopt); |
744 __ CompareClassId(receiver, receiver_type(), temp); | 746 __ CompareClassId(receiver, receiver_type(), temp); |
745 __ j(NOT_EQUAL, deopt); | 747 __ j(NOT_EQUAL, deopt); |
746 | 748 |
747 __ testl(index, Immediate(kSmiTagMask)); | 749 __ testl(index, Immediate(kSmiTagMask)); |
748 __ j(NOT_ZERO, deopt); | 750 __ j(NOT_ZERO, deopt); |
749 | 751 |
750 switch (receiver_type()) { | 752 switch (receiver_type()) { |
751 case kArray: | 753 case kArrayCid: |
752 case kImmutableArray: | 754 case kImmutableArrayCid: |
753 __ cmpl(index, FieldAddress(receiver, Array::length_offset())); | 755 __ cmpl(index, FieldAddress(receiver, Array::length_offset())); |
754 __ j(ABOVE_EQUAL, deopt); | 756 __ j(ABOVE_EQUAL, deopt); |
755 // Note that index is Smi, i.e, times 2. | 757 // Note that index is Smi, i.e, times 2. |
756 ASSERT(kSmiTagShift == 1); | 758 ASSERT(kSmiTagShift == 1); |
757 __ movl(result, FieldAddress(receiver, index, TIMES_2, sizeof(RawArray))); | 759 __ movl(result, FieldAddress(receiver, index, TIMES_2, sizeof(RawArray))); |
758 break; | 760 break; |
759 | 761 |
760 case kGrowableObjectArray: { | 762 case kGrowableObjectArrayCid: { |
761 Register temp = locs()->temp(0).reg(); | 763 Register temp = locs()->temp(0).reg(); |
762 | 764 |
763 __ cmpl(index, | 765 __ cmpl(index, |
764 FieldAddress(receiver, GrowableObjectArray::length_offset())); | 766 FieldAddress(receiver, GrowableObjectArray::length_offset())); |
765 __ j(ABOVE_EQUAL, deopt); | 767 __ j(ABOVE_EQUAL, deopt); |
766 __ movl(temp, FieldAddress(receiver, GrowableObjectArray::data_offset())); | 768 __ movl(temp, FieldAddress(receiver, GrowableObjectArray::data_offset())); |
767 // Note that index is Smi, i.e, times 2. | 769 // Note that index is Smi, i.e, times 2. |
768 ASSERT(kSmiTagShift == 1); | 770 ASSERT(kSmiTagShift == 1); |
769 __ movl(result, FieldAddress(temp, index, TIMES_2, sizeof(RawArray))); | 771 __ movl(result, FieldAddress(temp, index, TIMES_2, sizeof(RawArray))); |
770 break; | 772 break; |
771 } | 773 } |
772 | 774 |
773 default: | 775 default: |
774 UNREACHABLE(); | 776 UNREACHABLE(); |
775 break; | 777 break; |
776 } | 778 } |
777 } | 779 } |
778 | 780 |
779 | 781 |
780 LocationSummary* StoreIndexedComp::MakeLocationSummary() const { | 782 LocationSummary* StoreIndexedComp::MakeLocationSummary() const { |
781 const intptr_t kNumInputs = 3; | 783 const intptr_t kNumInputs = 3; |
782 if ((receiver_type() == kGrowableObjectArray) || | 784 if ((receiver_type() == kGrowableObjectArrayCid) || |
783 (receiver_type() == kArray)) { | 785 (receiver_type() == kArrayCid)) { |
784 const intptr_t kNumTemps = 1; | 786 const intptr_t kNumTemps = 1; |
785 LocationSummary* locs = | 787 LocationSummary* locs = |
786 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 788 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
787 locs->set_in(0, Location::RequiresRegister()); | 789 locs->set_in(0, Location::RequiresRegister()); |
788 locs->set_in(1, Location::RequiresRegister()); | 790 locs->set_in(1, Location::RequiresRegister()); |
789 locs->set_in(2, Location::RequiresRegister()); | 791 locs->set_in(2, Location::RequiresRegister()); |
790 locs->set_temp(0, Location::RequiresRegister()); | 792 locs->set_temp(0, Location::RequiresRegister()); |
791 locs->set_out(Location::NoLocation()); | 793 locs->set_out(Location::NoLocation()); |
792 return locs; | 794 return locs; |
793 } else { | 795 } else { |
794 ASSERT(receiver_type() == kIllegalObjectKind); | 796 ASSERT(receiver_type() == kIllegalCid); |
795 return MakeCallSummary(); | 797 return MakeCallSummary(); |
796 } | 798 } |
797 } | 799 } |
798 | 800 |
799 | 801 |
800 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, | 802 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, |
801 StoreIndexedComp* comp) { | 803 StoreIndexedComp* comp) { |
802 const String& function_name = | 804 const String& function_name = |
803 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); | 805 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); |
804 | 806 |
(...skipping 18 matching lines...) Expand all Loading... |
823 StoreIndexedComp* comp) { | 825 StoreIndexedComp* comp) { |
824 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), | 826 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
825 comp->token_pos(), | 827 comp->token_pos(), |
826 comp->try_index(), | 828 comp->try_index(), |
827 kDeoptStoreIndexedPolymorphic); | 829 kDeoptStoreIndexedPolymorphic); |
828 ASSERT(comp->ic_data()->NumberOfChecks() > 0); | 830 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
829 ASSERT(comp->HasICData()); | 831 ASSERT(comp->HasICData()); |
830 const ICData& ic_data = *comp->ic_data(); | 832 const ICData& ic_data = *comp->ic_data(); |
831 ASSERT(ic_data.num_args_tested() == 1); | 833 ASSERT(ic_data.num_args_tested() == 1); |
832 // No indexed access on Smi. | 834 // No indexed access on Smi. |
833 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 835 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmiCid); |
834 // Load receiver into EAX. | 836 // Load receiver into EAX. |
835 const intptr_t kNumArguments = 3; | 837 const intptr_t kNumArguments = 3; |
836 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); | 838 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
837 __ testl(EAX, Immediate(kSmiTagMask)); | 839 __ testl(EAX, Immediate(kSmiTagMask)); |
838 __ j(ZERO, deopt); | 840 __ j(ZERO, deopt); |
839 __ LoadClassId(EDI, EAX); | 841 __ LoadClassId(EDI, EAX); |
840 compiler->EmitTestAndCall(ic_data, | 842 compiler->EmitTestAndCall(ic_data, |
841 EDI, // Class id register. | 843 EDI, // Class id register. |
842 kNumArguments, | 844 kNumArguments, |
843 Array::Handle(), // No named arguments. | 845 Array::Handle(), // No named arguments. |
844 deopt, // Deoptimize target. | 846 deopt, // Deoptimize target. |
845 NULL, // Fallthrough when done. | 847 NULL, // Fallthrough when done. |
846 comp->deopt_id(), | 848 comp->deopt_id(), |
847 comp->token_pos(), | 849 comp->token_pos(), |
848 comp->try_index()); | 850 comp->try_index()); |
849 } | 851 } |
850 | 852 |
851 | 853 |
852 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 854 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
853 if (receiver_type() == kIllegalObjectKind) { | 855 if (receiver_type() == kIllegalCid) { |
854 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 856 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
855 EmitStoreIndexedPolymorphic(compiler, this); | 857 EmitStoreIndexedPolymorphic(compiler, this); |
856 } else { | 858 } else { |
857 EmitStoreIndexedGeneric(compiler, this); | 859 EmitStoreIndexedGeneric(compiler, this); |
858 } | 860 } |
859 return; | 861 return; |
860 } | 862 } |
861 | 863 |
862 Register receiver = locs()->in(0).reg(); | 864 Register receiver = locs()->in(0).reg(); |
863 Register index = locs()->in(1).reg(); | 865 Register index = locs()->in(1).reg(); |
(...skipping 10 matching lines...) Expand all Loading... |
874 | 876 |
875 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 877 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
876 __ j(ZERO, deopt); | 878 __ j(ZERO, deopt); |
877 __ CompareClassId(receiver, receiver_type(), temp); | 879 __ CompareClassId(receiver, receiver_type(), temp); |
878 __ j(NOT_EQUAL, deopt); | 880 __ j(NOT_EQUAL, deopt); |
879 | 881 |
880 __ testl(index, Immediate(kSmiTagMask)); | 882 __ testl(index, Immediate(kSmiTagMask)); |
881 __ j(NOT_ZERO, deopt); | 883 __ j(NOT_ZERO, deopt); |
882 | 884 |
883 switch (receiver_type()) { | 885 switch (receiver_type()) { |
884 case kArray: | 886 case kArrayCid: |
885 case kImmutableArray: | 887 case kImmutableArrayCid: |
886 __ cmpl(index, FieldAddress(receiver, Array::length_offset())); | 888 __ cmpl(index, FieldAddress(receiver, Array::length_offset())); |
887 __ j(ABOVE_EQUAL, deopt); | 889 __ j(ABOVE_EQUAL, deopt); |
888 // Note that index is Smi, i.e, times 2. | 890 // Note that index is Smi, i.e, times 2. |
889 ASSERT(kSmiTagShift == 1); | 891 ASSERT(kSmiTagShift == 1); |
890 __ StoreIntoObject(receiver, | 892 __ StoreIntoObject(receiver, |
891 FieldAddress(receiver, index, TIMES_2, sizeof(RawArray)), | 893 FieldAddress(receiver, index, TIMES_2, sizeof(RawArray)), |
892 value); | 894 value); |
893 break; | 895 break; |
894 | 896 |
895 case kGrowableObjectArray: { | 897 case kGrowableObjectArrayCid: { |
896 __ cmpl(index, | 898 __ cmpl(index, |
897 FieldAddress(receiver, GrowableObjectArray::length_offset())); | 899 FieldAddress(receiver, GrowableObjectArray::length_offset())); |
898 __ j(ABOVE_EQUAL, deopt); | 900 __ j(ABOVE_EQUAL, deopt); |
899 __ movl(temp, FieldAddress(receiver, GrowableObjectArray::data_offset())); | 901 __ movl(temp, FieldAddress(receiver, GrowableObjectArray::data_offset())); |
900 // Note that index is Smi, i.e, times 2. | 902 // Note that index is Smi, i.e, times 2. |
901 ASSERT(kSmiTagShift == 1); | 903 ASSERT(kSmiTagShift == 1); |
902 __ StoreIntoObject(temp, | 904 __ StoreIntoObject(temp, |
903 FieldAddress(temp, index, TIMES_2, sizeof(RawArray)), | 905 FieldAddress(temp, index, TIMES_2, sizeof(RawArray)), |
904 value); | 906 value); |
905 break; | 907 break; |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1111 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1113 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1112 } | 1114 } |
1113 // Instantiate non-null type arguments. | 1115 // Instantiate non-null type arguments. |
1114 if (type_arguments().IsUninstantiatedIdentity()) { | 1116 if (type_arguments().IsUninstantiatedIdentity()) { |
1115 // Check if the instantiator type argument vector is a TypeArguments of a | 1117 // Check if the instantiator type argument vector is a TypeArguments of a |
1116 // matching length and, if so, use it as the instantiated type_arguments. | 1118 // matching length and, if so, use it as the instantiated type_arguments. |
1117 // No need to check the instantiator ('instantiator_reg') for null here, | 1119 // No need to check the instantiator ('instantiator_reg') for null here, |
1118 // because a null instantiator will have the wrong class (Null instead of | 1120 // because a null instantiator will have the wrong class (Null instead of |
1119 // TypeArguments). | 1121 // TypeArguments). |
1120 Label type_arguments_uninstantiated; | 1122 Label type_arguments_uninstantiated; |
1121 __ CompareClassId(instantiator_reg, kTypeArguments, temp); | 1123 __ CompareClassId(instantiator_reg, kTypeArgumentsCid, temp); |
1122 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1124 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
1123 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1125 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
1124 Immediate(Smi::RawValue(len))); | 1126 Immediate(Smi::RawValue(len))); |
1125 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1127 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1126 __ Bind(&type_arguments_uninstantiated); | 1128 __ Bind(&type_arguments_uninstantiated); |
1127 } | 1129 } |
1128 // A runtime call to instantiate the type arguments is required. | 1130 // A runtime call to instantiate the type arguments is required. |
1129 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1131 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1130 __ PushObject(type_arguments()); | 1132 __ PushObject(type_arguments()); |
1131 __ pushl(instantiator_reg); // Push instantiator type arguments. | 1133 __ pushl(instantiator_reg); // Push instantiator type arguments. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1174 __ cmpl(instantiator_reg, raw_null); | 1176 __ cmpl(instantiator_reg, raw_null); |
1175 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1177 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1176 } | 1178 } |
1177 // Instantiate non-null type arguments. | 1179 // Instantiate non-null type arguments. |
1178 if (type_arguments().IsUninstantiatedIdentity()) { | 1180 if (type_arguments().IsUninstantiatedIdentity()) { |
1179 // Check if the instantiator type argument vector is a TypeArguments of a | 1181 // Check if the instantiator type argument vector is a TypeArguments of a |
1180 // matching length and, if so, use it as the instantiated type_arguments. | 1182 // matching length and, if so, use it as the instantiated type_arguments. |
1181 // No need to check instantiator_reg for null here, because a null | 1183 // No need to check instantiator_reg for null here, because a null |
1182 // instantiator will have the wrong class (Null instead of TypeArguments). | 1184 // instantiator will have the wrong class (Null instead of TypeArguments). |
1183 Label type_arguments_uninstantiated; | 1185 Label type_arguments_uninstantiated; |
1184 __ CompareClassId(instantiator_reg, kTypeArguments, temp_reg); | 1186 __ CompareClassId(instantiator_reg, kTypeArgumentsCid, temp_reg); |
1185 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1187 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
1186 Immediate arguments_length = | 1188 Immediate arguments_length = |
1187 Immediate(Smi::RawValue(type_arguments().Length())); | 1189 Immediate(Smi::RawValue(type_arguments().Length())); |
1188 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1190 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
1189 arguments_length); | 1191 arguments_length); |
1190 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1192 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1191 __ Bind(&type_arguments_uninstantiated); | 1193 __ Bind(&type_arguments_uninstantiated); |
1192 } | 1194 } |
1193 // In the non-factory case, we rely on the allocation stub to | 1195 // In the non-factory case, we rely on the allocation stub to |
1194 // instantiate the type arguments. | 1196 // instantiate the type arguments. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1243 // TODO(regis): The following emitted code is duplicated in | 1245 // TODO(regis): The following emitted code is duplicated in |
1244 // VisitExtractConstructorTypeArguments above. The reason is that the code | 1246 // VisitExtractConstructorTypeArguments above. The reason is that the code |
1245 // is split between two computations, so that each one produces a | 1247 // is split between two computations, so that each one produces a |
1246 // single value, rather than producing a pair of values. | 1248 // single value, rather than producing a pair of values. |
1247 // If this becomes an issue, we should expose these tests at the IL level. | 1249 // If this becomes an issue, we should expose these tests at the IL level. |
1248 | 1250 |
1249 // Check if the instantiator type argument vector is a TypeArguments of a | 1251 // Check if the instantiator type argument vector is a TypeArguments of a |
1250 // matching length and, if so, use it as the instantiated type_arguments. | 1252 // matching length and, if so, use it as the instantiated type_arguments. |
1251 // No need to check the instantiator (RAX) for null here, because a null | 1253 // No need to check the instantiator (RAX) for null here, because a null |
1252 // instantiator will have the wrong class (Null instead of TypeArguments). | 1254 // instantiator will have the wrong class (Null instead of TypeArguments). |
1253 __ CompareClassId(instantiator_reg, kTypeArguments, temp_reg); | 1255 __ CompareClassId(instantiator_reg, kTypeArgumentsCid, temp_reg); |
1254 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1256 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
1255 Immediate arguments_length = | 1257 Immediate arguments_length = |
1256 Immediate(Smi::RawValue(type_arguments().Length())); | 1258 Immediate(Smi::RawValue(type_arguments().Length())); |
1257 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1259 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
1258 arguments_length); | 1260 arguments_length); |
1259 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1261 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
1260 // The instantiator was used in VisitExtractConstructorTypeArguments as the | 1262 // The instantiator was used in VisitExtractConstructorTypeArguments as the |
1261 // instantiated type arguments, no proper instantiator needed. | 1263 // instantiated type arguments, no proper instantiator needed. |
1262 __ movl(instantiator_reg, | 1264 __ movl(instantiator_reg, |
1263 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 1265 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1538 __ shll(left, right_temp); | 1540 __ shll(left, right_temp); |
1539 __ sarl(left, right_temp); | 1541 __ sarl(left, right_temp); |
1540 __ cmpl(left, temp); | 1542 __ cmpl(left, temp); |
1541 __ j(NOT_EQUAL, &call_method, Assembler::kNearJump); // Overflow. | 1543 __ j(NOT_EQUAL, &call_method, Assembler::kNearJump); // Overflow. |
1542 // Shift for result now we know there is no overflow. | 1544 // Shift for result now we know there is no overflow. |
1543 __ shll(left, right_temp); | 1545 __ shll(left, right_temp); |
1544 __ jmp(&done); | 1546 __ jmp(&done); |
1545 { | 1547 { |
1546 __ Bind(&call_method); | 1548 __ Bind(&call_method); |
1547 Function& target = Function::ZoneHandle( | 1549 Function& target = Function::ZoneHandle( |
1548 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1550 comp->ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
1549 ASSERT(!target.IsNull()); | 1551 ASSERT(!target.IsNull()); |
1550 const intptr_t kArgumentCount = 2; | 1552 const intptr_t kArgumentCount = 2; |
1551 __ pushl(temp); | 1553 __ pushl(temp); |
1552 __ pushl(right); | 1554 __ pushl(right); |
1553 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), | 1555 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
1554 comp->instance_call()->token_pos(), | 1556 comp->instance_call()->token_pos(), |
1555 comp->instance_call()->try_index(), | 1557 comp->instance_call()->try_index(), |
1556 target, | 1558 target, |
1557 kArgumentCount, | 1559 kArgumentCount, |
1558 Array::Handle()); // No argument names. | 1560 Array::Handle()); // No argument names. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1601 comp->instance_call()->token_pos(), | 1603 comp->instance_call()->token_pos(), |
1602 comp->instance_call()->try_index(), | 1604 comp->instance_call()->try_index(), |
1603 kDeoptMintBinaryOp, | 1605 kDeoptMintBinaryOp, |
1604 left, | 1606 left, |
1605 right); | 1607 right); |
1606 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1608 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
1607 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1609 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
1608 __ j(NOT_ZERO, &non_smi); | 1610 __ j(NOT_ZERO, &non_smi); |
1609 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1611 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? |
1610 __ j(ZERO, &smi_smi); | 1612 __ j(ZERO, &smi_smi); |
1611 __ CompareClassId(right, kMint, temp); // Is argument Mint? | 1613 __ CompareClassId(right, kMintCid, temp); // Is argument Mint? |
1612 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. | 1614 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. |
1613 __ cmpl(left, Immediate(0)); | 1615 __ cmpl(left, Immediate(0)); |
1614 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. | 1616 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. |
1615 | 1617 |
1616 // Positive Smi receiver, Mint argument. | 1618 // Positive Smi receiver, Mint argument. |
1617 // Load lower argument Mint word, convert to Smi. It is OK to loose bits. | 1619 // Load lower argument Mint word, convert to Smi. It is OK to loose bits. |
1618 __ movl(right, FieldAddress(right, Mint::value_offset())); | 1620 __ movl(right, FieldAddress(right, Mint::value_offset())); |
1619 __ SmiTag(right); | 1621 __ SmiTag(right); |
1620 __ andl(result, right); | 1622 __ andl(result, right); |
1621 __ jmp(&done); | 1623 __ jmp(&done); |
1622 | 1624 |
1623 __ Bind(&non_smi); // Receiver is non-Smi. | 1625 __ Bind(&non_smi); // Receiver is non-Smi. |
1624 __ CompareClassId(left, kMint, temp); // Is receiver Mint? | 1626 __ CompareClassId(left, kMintCid, temp); // Is receiver Mint? |
1625 __ j(NOT_EQUAL, deopt); // Receiver neither Smi nor Mint. | 1627 __ j(NOT_EQUAL, deopt); // Receiver neither Smi nor Mint. |
1626 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1628 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? |
1627 __ j(NOT_ZERO, &mint_static_call); // Mint receiver, non-Smi argument. | 1629 __ j(NOT_ZERO, &mint_static_call); // Mint receiver, non-Smi argument. |
1628 __ cmpl(right, Immediate(0)); | 1630 __ cmpl(right, Immediate(0)); |
1629 __ j(LESS, &mint_static_call); // Mint receiver, negative Smi argument. | 1631 __ j(LESS, &mint_static_call); // Mint receiver, negative Smi argument. |
1630 | 1632 |
1631 // Mint receiver, positive Smi argument. | 1633 // Mint receiver, positive Smi argument. |
1632 // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. | 1634 // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. |
1633 __ movl(result, FieldAddress(left, Mint::value_offset())); | 1635 __ movl(result, FieldAddress(left, Mint::value_offset())); |
1634 __ SmiTag(result); | 1636 __ SmiTag(result); |
1635 __ Bind(&smi_smi); | 1637 __ Bind(&smi_smi); |
1636 __ andl(result, right); | 1638 __ andl(result, right); |
1637 __ jmp(&done); | 1639 __ jmp(&done); |
1638 | 1640 |
1639 __ Bind(&smi_static_call); | 1641 __ Bind(&smi_static_call); |
1640 { | 1642 { |
1641 Function& target = Function::ZoneHandle( | 1643 Function& target = Function::ZoneHandle( |
1642 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1644 comp->ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
1643 if (target.IsNull()) { | 1645 if (target.IsNull()) { |
1644 __ jmp(deopt); | 1646 __ jmp(deopt); |
1645 } else { | 1647 } else { |
1646 __ pushl(left); | 1648 __ pushl(left); |
1647 __ pushl(right); | 1649 __ pushl(right); |
1648 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), | 1650 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
1649 comp->instance_call()->token_pos(), | 1651 comp->instance_call()->token_pos(), |
1650 comp->instance_call()->try_index(), | 1652 comp->instance_call()->try_index(), |
1651 target, | 1653 target, |
1652 comp->instance_call()->ArgumentCount(), | 1654 comp->instance_call()->ArgumentCount(), |
1653 comp->instance_call()->argument_names()); | 1655 comp->instance_call()->argument_names()); |
1654 ASSERT(result == EAX); | 1656 ASSERT(result == EAX); |
1655 __ jmp(&done); | 1657 __ jmp(&done); |
1656 } | 1658 } |
1657 } | 1659 } |
1658 | 1660 |
1659 __ Bind(&mint_static_call); | 1661 __ Bind(&mint_static_call); |
1660 { | 1662 { |
1661 Function& target = Function::ZoneHandle( | 1663 Function& target = Function::ZoneHandle( |
1662 comp->ic_data()->GetTargetForReceiverClassId(kMint)); | 1664 comp->ic_data()->GetTargetForReceiverClassId(kMintCid)); |
1663 if (target.IsNull()) { | 1665 if (target.IsNull()) { |
1664 __ jmp(deopt); | 1666 __ jmp(deopt); |
1665 } else { | 1667 } else { |
1666 __ pushl(left); | 1668 __ pushl(left); |
1667 __ pushl(right); | 1669 __ pushl(right); |
1668 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), | 1670 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
1669 comp->instance_call()->token_pos(), | 1671 comp->instance_call()->token_pos(), |
1670 comp->instance_call()->try_index(), | 1672 comp->instance_call()->try_index(), |
1671 target, | 1673 target, |
1672 comp->instance_call()->ArgumentCount(), | 1674 comp->instance_call()->ArgumentCount(), |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1768 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1770 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
1769 | 1771 |
1770 Register value = locs()->in(0).reg(); | 1772 Register value = locs()->in(0).reg(); |
1771 Register result = locs()->out().reg(); | 1773 Register result = locs()->out().reg(); |
1772 ASSERT(value == result); | 1774 ASSERT(value == result); |
1773 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1775 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1774 instance_call()->token_pos(), | 1776 instance_call()->token_pos(), |
1775 instance_call()->try_index(), | 1777 instance_call()->try_index(), |
1776 kDeoptUnaryOp, | 1778 kDeoptUnaryOp, |
1777 value); | 1779 value); |
1778 if (test_class_id == kSmi) { | 1780 if (test_class_id == kSmiCid) { |
1779 __ testl(value, Immediate(kSmiTagMask)); | 1781 __ testl(value, Immediate(kSmiTagMask)); |
1780 __ j(NOT_ZERO, deopt); | 1782 __ j(NOT_ZERO, deopt); |
1781 switch (op_kind()) { | 1783 switch (op_kind()) { |
1782 case Token::kNEGATE: | 1784 case Token::kNEGATE: |
1783 __ negl(value); | 1785 __ negl(value); |
1784 __ j(OVERFLOW, deopt); | 1786 __ j(OVERFLOW, deopt); |
1785 break; | 1787 break; |
1786 case Token::kBIT_NOT: | 1788 case Token::kBIT_NOT: |
1787 __ notl(value); | 1789 __ notl(value); |
1788 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. | 1790 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1820 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1822 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
1821 | 1823 |
1822 Register value = locs()->in(0).reg(); | 1824 Register value = locs()->in(0).reg(); |
1823 Register result = locs()->out().reg(); | 1825 Register result = locs()->out().reg(); |
1824 ASSERT(value == result); | 1826 ASSERT(value == result); |
1825 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1827 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1826 instance_call()->token_pos(), | 1828 instance_call()->token_pos(), |
1827 instance_call()->try_index(), | 1829 instance_call()->try_index(), |
1828 kDeoptUnaryOp, | 1830 kDeoptUnaryOp, |
1829 value); | 1831 value); |
1830 if (test_class_id == kDouble) { | 1832 if (test_class_id == kDoubleCid) { |
1831 Register temp = locs()->temp(0).reg(); | 1833 Register temp = locs()->temp(0).reg(); |
1832 __ testl(value, Immediate(kSmiTagMask)); | 1834 __ testl(value, Immediate(kSmiTagMask)); |
1833 __ j(ZERO, deopt); // Smi. | 1835 __ j(ZERO, deopt); // Smi. |
1834 __ CompareClassId(value, kDouble, temp); | 1836 __ CompareClassId(value, kDoubleCid, temp); |
1835 __ j(NOT_EQUAL, deopt); | 1837 __ j(NOT_EQUAL, deopt); |
1836 // Allocate result object. | 1838 // Allocate result object. |
1837 const Class& double_class = compiler->double_class(); | 1839 const Class& double_class = compiler->double_class(); |
1838 const Code& stub = | 1840 const Code& stub = |
1839 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1841 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1840 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1842 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1841 __ pushl(value); | 1843 __ pushl(value); |
1842 compiler->GenerateCall(instance_call()->token_pos(), | 1844 compiler->GenerateCall(instance_call()->token_pos(), |
1843 instance_call()->try_index(), | 1845 instance_call()->try_index(), |
1844 &label, | 1846 &label, |
1845 PcDescriptors::kOther); | 1847 PcDescriptors::kOther); |
1846 // Result is in EAX. | 1848 // Result is in EAX. |
1847 ASSERT(result != temp); | 1849 ASSERT(result != temp); |
1848 __ movl(result, EAX); | 1850 __ movl(result, EAX); |
1849 __ popl(temp); | 1851 __ popl(temp); |
1850 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 1852 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
1851 __ DoubleNegate(XMM0); | 1853 __ DoubleNegate(XMM0); |
1852 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1854 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
1853 } else { | 1855 } else { |
1854 UNREACHABLE(); | 1856 UNREACHABLE(); |
1855 } | 1857 } |
1856 } | 1858 } |
1857 | 1859 |
1858 | 1860 |
1859 LocationSummary* ToDoubleComp::MakeLocationSummary() const { | 1861 LocationSummary* ToDoubleComp::MakeLocationSummary() const { |
1860 const intptr_t kNumInputs = 1; | 1862 const intptr_t kNumInputs = 1; |
1861 if (from() == kDouble) { | 1863 if (from() == kDoubleCid) { |
1862 const intptr_t kNumTemps = 1; | 1864 const intptr_t kNumTemps = 1; |
1863 LocationSummary* locs = | 1865 LocationSummary* locs = |
1864 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1866 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1865 locs->set_in(0, Location::RequiresRegister()); | 1867 locs->set_in(0, Location::RequiresRegister()); |
1866 locs->set_temp(0, Location::RequiresRegister()); | 1868 locs->set_temp(0, Location::RequiresRegister()); |
1867 locs->set_out(Location::SameAsFirstInput()); | 1869 locs->set_out(Location::SameAsFirstInput()); |
1868 locs->set_temp(0, Location::RequiresRegister()); | 1870 locs->set_temp(0, Location::RequiresRegister()); |
1869 return locs; | 1871 return locs; |
1870 } else { | 1872 } else { |
1871 ASSERT(from() == kSmi); | 1873 ASSERT(from() == kSmiCid); |
1872 return MakeCallSummary(); // Calls a stub to allocate result. | 1874 return MakeCallSummary(); // Calls a stub to allocate result. |
1873 } | 1875 } |
1874 } | 1876 } |
1875 | 1877 |
1876 | 1878 |
1877 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1879 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1878 Register value = (from() == kDouble) ? locs()->in(0).reg() : EBX; | 1880 Register value = (from() == kDoubleCid) ? locs()->in(0).reg() : EBX; |
1879 Register result = locs()->out().reg(); | 1881 Register result = locs()->out().reg(); |
1880 | 1882 |
1881 const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1883 const DeoptReasonId deopt_reason = (from() == kDoubleCid) ? |
1882 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1884 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
1883 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1885 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1884 instance_call()->token_pos(), | 1886 instance_call()->token_pos(), |
1885 instance_call()->try_index(), | 1887 instance_call()->try_index(), |
1886 deopt_reason, | 1888 deopt_reason, |
1887 value); | 1889 value); |
1888 | 1890 |
1889 if (from() == kDouble) { | 1891 if (from() == kDoubleCid) { |
1890 Register temp = locs()->temp(0).reg(); | 1892 Register temp = locs()->temp(0).reg(); |
1891 __ testl(value, Immediate(kSmiTagMask)); | 1893 __ testl(value, Immediate(kSmiTagMask)); |
1892 __ j(ZERO, deopt); // Deoptimize if Smi. | 1894 __ j(ZERO, deopt); // Deoptimize if Smi. |
1893 __ CompareClassId(value, kDouble, temp); | 1895 __ CompareClassId(value, kDoubleCid, temp); |
1894 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 1896 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
1895 ASSERT(value == result); | 1897 ASSERT(value == result); |
1896 return; | 1898 return; |
1897 } | 1899 } |
1898 | 1900 |
1899 ASSERT(from() == kSmi); | 1901 ASSERT(from() == kSmiCid); |
1900 | 1902 |
1901 const Class& double_class = compiler->double_class(); | 1903 const Class& double_class = compiler->double_class(); |
1902 const Code& stub = | 1904 const Code& stub = |
1903 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1905 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1904 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1906 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1905 | 1907 |
1906 // TODO(vegorov): allocate box in the driver loop to avoid spilling. | 1908 // TODO(vegorov): allocate box in the driver loop to avoid spilling. |
1907 compiler->GenerateCall(instance_call()->token_pos(), | 1909 compiler->GenerateCall(instance_call()->token_pos(), |
1908 instance_call()->try_index(), | 1910 instance_call()->try_index(), |
1909 &label, | 1911 &label, |
(...skipping 20 matching lines...) Expand all Loading... |
1930 instance_call()->try_index(), | 1932 instance_call()->try_index(), |
1931 kDeoptPolymorphicInstanceCallTestFail); | 1933 kDeoptPolymorphicInstanceCallTestFail); |
1932 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 1934 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
1933 __ jmp(deopt); | 1935 __ jmp(deopt); |
1934 return; | 1936 return; |
1935 } | 1937 } |
1936 ASSERT(HasICData()); | 1938 ASSERT(HasICData()); |
1937 ASSERT(ic_data()->num_args_tested() == 1); | 1939 ASSERT(ic_data()->num_args_tested() == 1); |
1938 Label handle_smi; | 1940 Label handle_smi; |
1939 Label* is_smi_label = | 1941 Label* is_smi_label = |
1940 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; | 1942 ic_data()->GetReceiverClassIdAt(0) == kSmiCid ? &handle_smi : deopt; |
1941 | 1943 |
1942 // Load receiver into EAX. | 1944 // Load receiver into EAX. |
1943 __ movl(EAX, | 1945 __ movl(EAX, |
1944 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 1946 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
1945 __ testl(EAX, Immediate(kSmiTagMask)); | 1947 __ testl(EAX, Immediate(kSmiTagMask)); |
1946 __ j(ZERO, is_smi_label); | 1948 __ j(ZERO, is_smi_label); |
1947 Label done; | 1949 Label done; |
1948 __ LoadClassId(EDI, EAX); | 1950 __ LoadClassId(EDI, EAX); |
1949 compiler->EmitTestAndCall(*ic_data(), | 1951 compiler->EmitTestAndCall(*ic_data(), |
1950 EDI, // Class id register. | 1952 EDI, // Class id register. |
1951 instance_call()->ArgumentCount(), | 1953 instance_call()->ArgumentCount(), |
1952 instance_call()->argument_names(), | 1954 instance_call()->argument_names(), |
1953 deopt, | 1955 deopt, |
1954 (is_smi_label == &handle_smi) ? &done : NULL, | 1956 (is_smi_label == &handle_smi) ? &done : NULL, |
1955 instance_call()->deopt_id(), | 1957 instance_call()->deopt_id(), |
1956 instance_call()->token_pos(), | 1958 instance_call()->token_pos(), |
1957 instance_call()->try_index()); | 1959 instance_call()->try_index()); |
1958 if (is_smi_label == &handle_smi) { | 1960 if (is_smi_label == &handle_smi) { |
1959 __ Bind(&handle_smi); | 1961 __ Bind(&handle_smi); |
1960 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); | 1962 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmiCid); |
1961 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1963 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
1962 compiler->GenerateStaticCall(instance_call()->deopt_id(), | 1964 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
1963 instance_call()->token_pos(), | 1965 instance_call()->token_pos(), |
1964 instance_call()->try_index(), | 1966 instance_call()->try_index(), |
1965 target, | 1967 target, |
1966 instance_call()->ArgumentCount(), | 1968 instance_call()->ArgumentCount(), |
1967 instance_call()->argument_names()); | 1969 instance_call()->argument_names()); |
1968 } | 1970 } |
1969 __ Bind(&done); | 1971 __ Bind(&done); |
1970 } | 1972 } |
(...skipping 14 matching lines...) Expand all Loading... |
1985 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) { | 1987 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) { |
1986 const int kNumInputs = 2; | 1988 const int kNumInputs = 2; |
1987 const int kNumTemps = 0; | 1989 const int kNumTemps = 0; |
1988 LocationSummary* locs = | 1990 LocationSummary* locs = |
1989 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1991 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1990 locs->set_in(0, Location::RequiresRegister()); | 1992 locs->set_in(0, Location::RequiresRegister()); |
1991 locs->set_in(1, Location::RequiresRegister()); | 1993 locs->set_in(1, Location::RequiresRegister()); |
1992 return locs; | 1994 return locs; |
1993 } | 1995 } |
1994 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 1996 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
1995 if (ICDataWithBothClassIds(*ic_data(), kSmi) || | 1997 if (ICDataWithBothClassIds(*ic_data(), kSmiCid) || |
1996 ICDataWithBothClassIds(*ic_data(), kDouble)) { | 1998 ICDataWithBothClassIds(*ic_data(), kDoubleCid)) { |
1997 const intptr_t kNumInputs = 2; | 1999 const intptr_t kNumInputs = 2; |
1998 const intptr_t kNumTemps = 1; | 2000 const intptr_t kNumTemps = 1; |
1999 LocationSummary* summary = | 2001 LocationSummary* summary = |
2000 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2002 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2001 summary->set_in(0, Location::RequiresRegister()); | 2003 summary->set_in(0, Location::RequiresRegister()); |
2002 summary->set_in(1, Location::RequiresRegister()); | 2004 summary->set_in(1, Location::RequiresRegister()); |
2003 summary->set_temp(0, Location::RequiresRegister()); | 2005 summary->set_temp(0, Location::RequiresRegister()); |
2004 return summary; | 2006 return summary; |
2005 } | 2007 } |
2006 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { | 2008 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { |
(...skipping 17 matching lines...) Expand all Loading... |
2024 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) { | 2026 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) { |
2025 Register left = locs()->in(0).reg(); | 2027 Register left = locs()->in(0).reg(); |
2026 Register right = locs()->in(1).reg(); | 2028 Register right = locs()->in(1).reg(); |
2027 __ cmpl(left, right); | 2029 __ cmpl(left, right); |
2028 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 2030 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
2029 EmitBranchOnCondition(compiler, cond); | 2031 EmitBranchOnCondition(compiler, cond); |
2030 return; | 2032 return; |
2031 } | 2033 } |
2032 // Relational or equality. | 2034 // Relational or equality. |
2033 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 2035 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
2034 if (ICDataWithBothClassIds(*ic_data(), kSmi)) { | 2036 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) { |
2035 EmitSmiComparisonOp(compiler, *locs(), kind(), this, | 2037 EmitSmiComparisonOp(compiler, *locs(), kind(), this, |
2036 deopt_id(), token_pos(), try_index()); | 2038 deopt_id(), token_pos(), try_index()); |
2037 return; | 2039 return; |
2038 } | 2040 } |
2039 if (ICDataWithBothClassIds(*ic_data(), kDouble)) { | 2041 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) { |
2040 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, | 2042 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, |
2041 deopt_id(), token_pos(), try_index()); | 2043 deopt_id(), token_pos(), try_index()); |
2042 return; | 2044 return; |
2043 } | 2045 } |
2044 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. | 2046 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. |
2045 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { | 2047 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { |
2046 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), | 2048 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), |
2047 deopt_id(), token_pos(), try_index()); | 2049 deopt_id(), token_pos(), try_index()); |
2048 return; | 2050 return; |
2049 } | 2051 } |
(...skipping 20 matching lines...) Expand all Loading... |
2070 ASSERT(locs()->out().reg() == EAX); | 2072 ASSERT(locs()->out().reg() == EAX); |
2071 __ CompareObject(locs()->out().reg(), compiler->bool_true()); | 2073 __ CompareObject(locs()->out().reg(), compiler->bool_true()); |
2072 EmitBranchOnCondition(compiler, branch_condition); | 2074 EmitBranchOnCondition(compiler, branch_condition); |
2073 } | 2075 } |
2074 | 2076 |
2075 } // namespace dart | 2077 } // namespace dart |
2076 | 2078 |
2077 #undef __ | 2079 #undef __ |
2078 | 2080 |
2079 #endif // defined TARGET_ARCH_X64 | 2081 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |