OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 ASSERT(value.IsStackSlot()); | 63 ASSERT(value.IsStackSlot()); |
64 const intptr_t value_offset = value.ToStackSlotOffset(); | 64 const intptr_t value_offset = value.ToStackSlotOffset(); |
65 __ LoadFromOffset(TMP, FP, value_offset); | 65 __ LoadFromOffset(TMP, FP, value_offset); |
66 __ Push(TMP); | 66 __ Push(TMP); |
67 } | 67 } |
68 } | 68 } |
69 } | 69 } |
70 | 70 |
71 | 71 |
72 LocationSummary* ReturnInstr::MakeLocationSummary(Isolate* isolate, | 72 LocationSummary* ReturnInstr::MakeLocationSummary(Isolate* isolate, |
73 bool opt) const { | 73 bool opt) const { |
74 const intptr_t kNumInputs = 1; | 74 const intptr_t kNumInputs = 1; |
75 const intptr_t kNumTemps = 0; | 75 const intptr_t kNumTemps = 0; |
76 LocationSummary* locs = new(isolate) LocationSummary( | 76 LocationSummary* locs = new(isolate) LocationSummary( |
77 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 77 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
78 locs->set_in(0, Location::RegisterLocation(V0)); | 78 locs->set_in(0, Location::RegisterLocation(V0)); |
79 return locs; | 79 return locs; |
80 } | 80 } |
81 | 81 |
82 | 82 |
83 // Attempt optimized compilation at return instruction instead of at the entry. | 83 // Attempt optimized compilation at return instruction instead of at the entry. |
(...skipping 30 matching lines...) Expand all Loading... |
114 | 114 |
115 static Condition NegateCondition(Condition condition) { | 115 static Condition NegateCondition(Condition condition) { |
116 switch (condition) { | 116 switch (condition) { |
117 case EQ: return NE; | 117 case EQ: return NE; |
118 case NE: return EQ; | 118 case NE: return EQ; |
119 case LT: return GE; | 119 case LT: return GE; |
120 case LE: return GT; | 120 case LE: return GT; |
121 case GT: return LE; | 121 case GT: return LE; |
122 case GE: return LT; | 122 case GE: return LT; |
123 default: | 123 default: |
124 OS::Print("Error: Condition not recognized: %d\n", condition); | 124 UNREACHABLE(); |
125 UNIMPLEMENTED(); | |
126 return EQ; | 125 return EQ; |
127 } | 126 } |
128 } | 127 } |
129 | 128 |
130 | 129 |
131 // Detect pattern when one value is zero and another is a power of 2. | 130 // Detect pattern when one value is zero and another is a power of 2. |
132 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 131 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
133 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 132 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
134 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 133 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
135 } | 134 } |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 return LocationSummary::Make(isolate, | 270 return LocationSummary::Make(isolate, |
272 0, | 271 0, |
273 Location::RequiresRegister(), | 272 Location::RequiresRegister(), |
274 LocationSummary::kNoCall); | 273 LocationSummary::kNoCall); |
275 } | 274 } |
276 | 275 |
277 | 276 |
278 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 277 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
279 __ TraceSimMsg("LoadLocalInstr"); | 278 __ TraceSimMsg("LoadLocalInstr"); |
280 Register result = locs()->out(0).reg(); | 279 Register result = locs()->out(0).reg(); |
281 __ lw(result, Address(FP, local().index() * kWordSize)); | 280 __ LoadFromOffset(result, FP, local().index() * kWordSize); |
282 } | 281 } |
283 | 282 |
284 | 283 |
285 LocationSummary* StoreLocalInstr::MakeLocationSummary(Isolate* isolate, | 284 LocationSummary* StoreLocalInstr::MakeLocationSummary(Isolate* isolate, |
286 bool opt) const { | 285 bool opt) const { |
287 return LocationSummary::Make(isolate, | 286 return LocationSummary::Make(isolate, |
288 1, | 287 1, |
289 Location::SameAsFirstInput(), | 288 Location::SameAsFirstInput(), |
290 LocationSummary::kNoCall); | 289 LocationSummary::kNoCall); |
291 } | 290 } |
292 | 291 |
293 | 292 |
294 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 293 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
295 __ TraceSimMsg("StoreLocalInstr"); | 294 __ TraceSimMsg("StoreLocalInstr"); |
296 Register value = locs()->in(0).reg(); | 295 Register value = locs()->in(0).reg(); |
297 Register result = locs()->out(0).reg(); | 296 Register result = locs()->out(0).reg(); |
298 ASSERT(result == value); // Assert that register assignment is correct. | 297 ASSERT(result == value); // Assert that register assignment is correct. |
299 __ sw(value, Address(FP, local().index() * kWordSize)); | 298 __ StoreToOffset(value, FP, local().index() * kWordSize); |
300 } | 299 } |
301 | 300 |
302 | 301 |
303 LocationSummary* ConstantInstr::MakeLocationSummary(Isolate* isolate, | 302 LocationSummary* ConstantInstr::MakeLocationSummary(Isolate* isolate, |
304 bool opt) const { | 303 bool opt) const { |
305 return LocationSummary::Make(isolate, | 304 return LocationSummary::Make(isolate, |
306 0, | 305 0, |
307 Location::RequiresRegister(), | 306 Location::RequiresRegister(), |
308 LocationSummary::kNoCall); | 307 LocationSummary::kNoCall); |
309 } | 308 } |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 __ TraceSimMsg("AssertBooleanInstr"); | 420 __ TraceSimMsg("AssertBooleanInstr"); |
422 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 421 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
423 ASSERT(obj == result); | 422 ASSERT(obj == result); |
424 } | 423 } |
425 | 424 |
426 | 425 |
427 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Isolate* isolate, | 426 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Isolate* isolate, |
428 bool opt) const { | 427 bool opt) const { |
429 const intptr_t kNumInputs = 2; | 428 const intptr_t kNumInputs = 2; |
430 if (operation_cid() == kMintCid) { | 429 if (operation_cid() == kMintCid) { |
431 const intptr_t kNumTemps = 1; | 430 const intptr_t kNumTemps = 0; |
432 LocationSummary* locs = new(isolate) LocationSummary( | 431 LocationSummary* locs = new(isolate) LocationSummary( |
433 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 432 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
434 locs->set_in(0, Location::RequiresFpuRegister()); | 433 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
435 locs->set_in(1, Location::RequiresFpuRegister()); | 434 Location::RequiresRegister())); |
436 locs->set_temp(0, Location::RequiresRegister()); | 435 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 436 Location::RequiresRegister())); |
437 locs->set_out(0, Location::RequiresRegister()); | 437 locs->set_out(0, Location::RequiresRegister()); |
438 return locs; | 438 return locs; |
439 } | 439 } |
440 if (operation_cid() == kDoubleCid) { | 440 if (operation_cid() == kDoubleCid) { |
441 const intptr_t kNumTemps = 0; | 441 const intptr_t kNumTemps = 0; |
442 LocationSummary* locs = new(isolate) LocationSummary( | 442 LocationSummary* locs = new(isolate) LocationSummary( |
443 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 443 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
444 locs->set_in(0, Location::RequiresFpuRegister()); | 444 locs->set_in(0, Location::RequiresFpuRegister()); |
445 locs->set_in(1, Location::RequiresFpuRegister()); | 445 locs->set_in(1, Location::RequiresFpuRegister()); |
446 locs->set_out(0, Location::RequiresRegister()); | 446 locs->set_out(0, Location::RequiresRegister()); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
546 // Fall through or jump to the true successor. | 546 // Fall through or jump to the true successor. |
547 if (labels.fall_through != labels.true_label) { | 547 if (labels.fall_through != labels.true_label) { |
548 __ b(labels.true_label); | 548 __ b(labels.true_label); |
549 } | 549 } |
550 } | 550 } |
551 } | 551 } |
552 | 552 |
553 | 553 |
554 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 554 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
555 const LocationSummary& locs, | 555 const LocationSummary& locs, |
556 Token::Kind kind, | 556 Token::Kind kind) { |
557 BranchLabels labels) { | |
558 __ TraceSimMsg("EmitSmiComparisonOp"); | 557 __ TraceSimMsg("EmitSmiComparisonOp"); |
559 __ Comment("EmitSmiComparisonOp"); | 558 __ Comment("EmitSmiComparisonOp"); |
560 Location left = locs.in(0); | 559 Location left = locs.in(0); |
561 Location right = locs.in(1); | 560 Location right = locs.in(1); |
562 ASSERT(!left.IsConstant() || !right.IsConstant()); | 561 ASSERT(!left.IsConstant() || !right.IsConstant()); |
563 | 562 |
564 Condition true_condition = TokenKindToSmiCondition(kind); | 563 Condition true_condition = TokenKindToSmiCondition(kind); |
565 | 564 |
566 if (left.IsConstant()) { | 565 if (left.IsConstant()) { |
567 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant()); | 566 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant()); |
568 true_condition = FlipCondition(true_condition); | 567 true_condition = FlipCondition(true_condition); |
569 } else if (right.IsConstant()) { | 568 } else if (right.IsConstant()) { |
570 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant()); | 569 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant()); |
571 } else { | 570 } else { |
572 __ slt(CMPRES1, left.reg(), right.reg()); | 571 __ slt(CMPRES1, left.reg(), right.reg()); |
573 __ slt(CMPRES2, right.reg(), left.reg()); | 572 __ slt(CMPRES2, right.reg(), left.reg()); |
574 } | 573 } |
575 return true_condition; | 574 return true_condition; |
576 } | 575 } |
577 | 576 |
578 | 577 |
| 578 static Condition TokenKindToMintCondition(Token::Kind kind) { |
| 579 switch (kind) { |
| 580 case Token::kEQ: return EQ; |
| 581 case Token::kNE: return NE; |
| 582 case Token::kLT: return LT; |
| 583 case Token::kGT: return GT; |
| 584 case Token::kLTE: return LE; |
| 585 case Token::kGTE: return GE; |
| 586 default: |
| 587 UNREACHABLE(); |
| 588 return VS; |
| 589 } |
| 590 } |
| 591 |
| 592 |
| 593 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
| 594 const LocationSummary& locs, |
| 595 Token::Kind kind) { |
| 596 __ TraceSimMsg("EmitUnboxedMintEqualityOp"); |
| 597 __ Comment("EmitUnboxedMintEqualityOp"); |
| 598 ASSERT(Token::IsEqualityOperator(kind)); |
| 599 PairLocation* left_pair = locs.in(0).AsPairLocation(); |
| 600 Register left_lo = left_pair->At(0).reg(); |
| 601 Register left_hi = left_pair->At(1).reg(); |
| 602 PairLocation* right_pair = locs.in(1).AsPairLocation(); |
| 603 Register right_lo = right_pair->At(0).reg(); |
| 604 Register right_hi = right_pair->At(1).reg(); |
| 605 |
| 606 __ xor_(CMPRES1, left_lo, right_lo); |
| 607 __ xor_(CMPRES2, left_hi, right_hi); |
| 608 __ or_(CMPRES1, CMPRES1, CMPRES2); |
| 609 __ mov(CMPRES2, ZR); |
| 610 return TokenKindToMintCondition(kind); |
| 611 } |
| 612 |
| 613 |
| 614 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
| 615 const LocationSummary& locs, |
| 616 Token::Kind kind) { |
| 617 __ TraceSimMsg("EmitUnboxedMintComparisonOp"); |
| 618 __ Comment("EmitUnboxedMintComparisonOp"); |
| 619 PairLocation* left_pair = locs.in(0).AsPairLocation(); |
| 620 Register left_lo = left_pair->At(0).reg(); |
| 621 Register left_hi = left_pair->At(1).reg(); |
| 622 PairLocation* right_pair = locs.in(1).AsPairLocation(); |
| 623 Register right_lo = right_pair->At(0).reg(); |
| 624 Register right_hi = right_pair->At(1).reg(); |
| 625 |
| 626 Label done; |
| 627 // Compare upper halves first. |
| 628 __ slt(CMPRES1, left_hi, right_hi); |
| 629 __ slt(CMPRES2, right_hi, left_hi); |
| 630 // If higher words aren't equal, skip comparing lower words. |
| 631 __ bne(CMPRES1, CMPRES2, &done); |
| 632 |
| 633 __ sltu(CMPRES1, left_lo, right_lo); |
| 634 __ sltu(CMPRES2, right_lo, left_lo); |
| 635 __ Bind(&done); |
| 636 |
| 637 return TokenKindToMintCondition(kind); |
| 638 } |
| 639 |
| 640 |
579 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 641 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
580 switch (kind) { | 642 switch (kind) { |
581 case Token::kEQ: return EQ; | 643 case Token::kEQ: return EQ; |
582 case Token::kNE: return NE; | 644 case Token::kNE: return NE; |
583 case Token::kLT: return LT; | 645 case Token::kLT: return LT; |
584 case Token::kGT: return GT; | 646 case Token::kGT: return GT; |
585 case Token::kLTE: return LE; | 647 case Token::kLTE: return LE; |
586 case Token::kGTE: return GE; | 648 case Token::kGTE: return GE; |
587 default: | 649 default: |
588 UNREACHABLE(); | 650 UNREACHABLE(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 __ movt(CMPRES1, ZR); | 692 __ movt(CMPRES1, ZR); |
631 } | 693 } |
632 __ mov(CMPRES2, ZR); | 694 __ mov(CMPRES2, ZR); |
633 return EQ; | 695 return EQ; |
634 } | 696 } |
635 | 697 |
636 | 698 |
637 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 699 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
638 BranchLabels labels) { | 700 BranchLabels labels) { |
639 if (operation_cid() == kSmiCid) { | 701 if (operation_cid() == kSmiCid) { |
640 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 702 return EmitSmiComparisonOp(compiler, *locs(), kind()); |
| 703 } else if (operation_cid() == kMintCid) { |
| 704 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind()); |
641 } else { | 705 } else { |
642 ASSERT(operation_cid() == kDoubleCid); | 706 ASSERT(operation_cid() == kDoubleCid); |
643 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 707 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
644 } | 708 } |
645 } | 709 } |
646 | 710 |
647 | 711 |
648 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 712 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
649 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 713 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
650 __ Comment("EqualityCompareInstr"); | 714 __ Comment("EqualityCompareInstr"); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 __ LoadObject(result_reg, Bool::True()); | 858 __ LoadObject(result_reg, Bool::True()); |
795 __ Bind(&done); | 859 __ Bind(&done); |
796 } | 860 } |
797 | 861 |
798 | 862 |
799 LocationSummary* RelationalOpInstr::MakeLocationSummary(Isolate* isolate, | 863 LocationSummary* RelationalOpInstr::MakeLocationSummary(Isolate* isolate, |
800 bool opt) const { | 864 bool opt) const { |
801 const intptr_t kNumInputs = 2; | 865 const intptr_t kNumInputs = 2; |
802 const intptr_t kNumTemps = 0; | 866 const intptr_t kNumTemps = 0; |
803 if (operation_cid() == kMintCid) { | 867 if (operation_cid() == kMintCid) { |
804 const intptr_t kNumTemps = 2; | 868 const intptr_t kNumTemps = 0; |
805 LocationSummary* locs = new(isolate) LocationSummary( | 869 LocationSummary* locs = new(isolate) LocationSummary( |
806 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 870 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
807 locs->set_in(0, Location::RequiresFpuRegister()); | 871 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
808 locs->set_in(1, Location::RequiresFpuRegister()); | 872 Location::RequiresRegister())); |
809 locs->set_temp(0, Location::RequiresRegister()); | 873 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
810 locs->set_temp(1, Location::RequiresRegister()); | 874 Location::RequiresRegister())); |
811 locs->set_out(0, Location::RequiresRegister()); | 875 locs->set_out(0, Location::RequiresRegister()); |
812 return locs; | 876 return locs; |
813 } | 877 } |
814 if (operation_cid() == kDoubleCid) { | 878 if (operation_cid() == kDoubleCid) { |
815 LocationSummary* summary = new(isolate) LocationSummary( | 879 LocationSummary* summary = new(isolate) LocationSummary( |
816 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 880 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
817 summary->set_in(0, Location::RequiresFpuRegister()); | 881 summary->set_in(0, Location::RequiresFpuRegister()); |
818 summary->set_in(1, Location::RequiresFpuRegister()); | 882 summary->set_in(1, Location::RequiresFpuRegister()); |
819 summary->set_out(0, Location::RequiresRegister()); | 883 summary->set_out(0, Location::RequiresRegister()); |
820 return summary; | 884 return summary; |
821 } | 885 } |
822 ASSERT(operation_cid() == kSmiCid); | 886 ASSERT(operation_cid() == kSmiCid); |
823 LocationSummary* summary = new(isolate) LocationSummary( | 887 LocationSummary* summary = new(isolate) LocationSummary( |
824 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 888 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
825 summary->set_in(0, Location::RegisterOrConstant(left())); | 889 summary->set_in(0, Location::RegisterOrConstant(left())); |
826 // Only one input can be a constant operand. The case of two constant | 890 // Only one input can be a constant operand. The case of two constant |
827 // operands should be handled by constant propagation. | 891 // operands should be handled by constant propagation. |
828 summary->set_in(1, summary->in(0).IsConstant() | 892 summary->set_in(1, summary->in(0).IsConstant() |
829 ? Location::RequiresRegister() | 893 ? Location::RequiresRegister() |
830 : Location::RegisterOrConstant(right())); | 894 : Location::RegisterOrConstant(right())); |
831 summary->set_out(0, Location::RequiresRegister()); | 895 summary->set_out(0, Location::RequiresRegister()); |
832 return summary; | 896 return summary; |
833 } | 897 } |
834 | 898 |
835 | 899 |
836 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 900 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
837 BranchLabels labels) { | 901 BranchLabels labels) { |
838 if (operation_cid() == kSmiCid) { | 902 if (operation_cid() == kSmiCid) { |
839 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 903 return EmitSmiComparisonOp(compiler, *locs(), kind()); |
| 904 } else if (operation_cid() == kMintCid) { |
| 905 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind()); |
840 } else { | 906 } else { |
841 ASSERT(operation_cid() == kDoubleCid); | 907 ASSERT(operation_cid() == kDoubleCid); |
842 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 908 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
843 } | 909 } |
844 } | 910 } |
845 | 911 |
846 | 912 |
847 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 913 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
848 __ TraceSimMsg("RelationalOpInstr"); | 914 __ TraceSimMsg("RelationalOpInstr"); |
849 | 915 |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1189 case kTypedDataFloat32x4ArrayCid: | 1255 case kTypedDataFloat32x4ArrayCid: |
1190 UNIMPLEMENTED(); | 1256 UNIMPLEMENTED(); |
1191 break; | 1257 break; |
1192 } | 1258 } |
1193 return; | 1259 return; |
1194 } | 1260 } |
1195 | 1261 |
1196 if ((representation() == kUnboxedUint32) || | 1262 if ((representation() == kUnboxedUint32) || |
1197 (representation() == kUnboxedInt32)) { | 1263 (representation() == kUnboxedInt32)) { |
1198 const Register result = locs()->out(0).reg(); | 1264 const Register result = locs()->out(0).reg(); |
| 1265 if ((index_scale() == 1) && index.IsRegister()) { |
| 1266 __ SmiUntag(index.reg()); |
| 1267 } |
1199 switch (class_id()) { | 1268 switch (class_id()) { |
1200 case kTypedDataInt32ArrayCid: | 1269 case kTypedDataInt32ArrayCid: |
| 1270 ASSERT(representation() == kUnboxedInt32); |
| 1271 __ lw(result, element_address); |
| 1272 break; |
| 1273 case kTypedDataUint32ArrayCid: |
1201 ASSERT(representation() == kUnboxedUint32); | 1274 ASSERT(representation() == kUnboxedUint32); |
1202 __ lw(result, element_address); | 1275 __ lw(result, element_address); |
1203 break; | 1276 break; |
1204 case kTypedDataUint32ArrayCid: | |
1205 ASSERT(representation() == kUnboxedInt32); | |
1206 __ lw(result, element_address); | |
1207 break; | |
1208 default: | 1277 default: |
1209 UNREACHABLE(); | 1278 UNREACHABLE(); |
1210 } | 1279 } |
1211 return; | 1280 return; |
1212 } | 1281 } |
1213 | 1282 |
1214 ASSERT(representation() == kTagged); | 1283 ASSERT(representation() == kTagged); |
1215 | 1284 |
1216 const Register result = locs()->out(0).reg(); | 1285 const Register result = locs()->out(0).reg(); |
1217 switch (class_id()) { | 1286 switch (class_id()) { |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1386 const Register array = locs()->in(0).reg(); | 1455 const Register array = locs()->in(0).reg(); |
1387 const Location index = locs()->in(1); | 1456 const Location index = locs()->in(1); |
1388 | 1457 |
1389 Address element_address = index.IsRegister() | 1458 Address element_address = index.IsRegister() |
1390 ? __ ElementAddressForRegIndex(false, // Store. | 1459 ? __ ElementAddressForRegIndex(false, // Store. |
1391 IsExternal(), class_id(), index_scale(), | 1460 IsExternal(), class_id(), index_scale(), |
1392 array, index.reg()) | 1461 array, index.reg()) |
1393 : __ ElementAddressForIntIndex( | 1462 : __ ElementAddressForIntIndex( |
1394 IsExternal(), class_id(), index_scale(), | 1463 IsExternal(), class_id(), index_scale(), |
1395 array, Smi::Cast(index.constant()).Value()); | 1464 array, Smi::Cast(index.constant()).Value()); |
| 1465 ASSERT(element_address.base() != TMP); // Allowed for load only. |
1396 | 1466 |
1397 switch (class_id()) { | 1467 switch (class_id()) { |
1398 case kArrayCid: | 1468 case kArrayCid: |
1399 if (ShouldEmitStoreBarrier()) { | 1469 if (ShouldEmitStoreBarrier()) { |
1400 Register value = locs()->in(2).reg(); | 1470 Register value = locs()->in(2).reg(); |
1401 __ StoreIntoObject(array, element_address, value); | 1471 __ StoreIntoObject(array, element_address, value); |
1402 } else if (locs()->in(2).IsConstant()) { | 1472 } else if (locs()->in(2).IsConstant()) { |
1403 const Object& constant = locs()->in(2).constant(); | 1473 const Object& constant = locs()->in(2).constant(); |
1404 __ StoreIntoObjectNoBarrier(array, element_address, constant); | 1474 __ StoreIntoObjectNoBarrier(array, element_address, constant); |
1405 } else { | 1475 } else { |
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1981 | 2051 |
1982 // When the parser is building an implicit static getter for optimization, | 2052 // When the parser is building an implicit static getter for optimization, |
1983 // it can generate a function body where deoptimization ids do not line up | 2053 // it can generate a function body where deoptimization ids do not line up |
1984 // with the unoptimized code. | 2054 // with the unoptimized code. |
1985 // | 2055 // |
1986 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 2056 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
1987 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2057 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1988 __ TraceSimMsg("LoadStaticFieldInstr"); | 2058 __ TraceSimMsg("LoadStaticFieldInstr"); |
1989 Register field = locs()->in(0).reg(); | 2059 Register field = locs()->in(0).reg(); |
1990 Register result = locs()->out(0).reg(); | 2060 Register result = locs()->out(0).reg(); |
1991 __ lw(result, FieldAddress(field, Field::value_offset())); | 2061 __ LoadFromOffset(result, field, Field::value_offset() - kHeapObjectTag); |
1992 } | 2062 } |
1993 | 2063 |
1994 | 2064 |
1995 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Isolate* isolate, | 2065 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Isolate* isolate, |
1996 bool opt) const { | 2066 bool opt) const { |
1997 LocationSummary* locs = new(isolate) LocationSummary( | 2067 LocationSummary* locs = new(isolate) LocationSummary( |
1998 isolate, 1, 1, LocationSummary::kNoCall); | 2068 isolate, 1, 1, LocationSummary::kNoCall); |
1999 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 2069 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
2000 : Location::RequiresRegister()); | 2070 : Location::RequiresRegister()); |
2001 locs->set_temp(0, Location::RequiresRegister()); | 2071 locs->set_temp(0, Location::RequiresRegister()); |
(...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2570 | 2640 |
2571 // Restore SP from FP as we are coming from a throw and the code for | 2641 // Restore SP from FP as we are coming from a throw and the code for |
2572 // popping arguments has not been run. | 2642 // popping arguments has not been run. |
2573 const intptr_t fp_sp_dist = | 2643 const intptr_t fp_sp_dist = |
2574 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 2644 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
2575 ASSERT(fp_sp_dist <= 0); | 2645 ASSERT(fp_sp_dist <= 0); |
2576 __ AddImmediate(SP, FP, fp_sp_dist); | 2646 __ AddImmediate(SP, FP, fp_sp_dist); |
2577 | 2647 |
2578 // Restore stack and initialize the two exception variables: | 2648 // Restore stack and initialize the two exception variables: |
2579 // exception and stack trace variables. | 2649 // exception and stack trace variables. |
2580 __ sw(kExceptionObjectReg, | 2650 __ StoreToOffset(kExceptionObjectReg, |
2581 Address(FP, exception_var().index() * kWordSize)); | 2651 FP, exception_var().index() * kWordSize); |
2582 __ sw(kStackTraceObjectReg, | 2652 __ StoreToOffset(kStackTraceObjectReg, |
2583 Address(FP, stacktrace_var().index() * kWordSize)); | 2653 FP, stacktrace_var().index() * kWordSize); |
2584 } | 2654 } |
2585 | 2655 |
2586 | 2656 |
2587 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Isolate* isolate, | 2657 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Isolate* isolate, |
2588 bool opt) const { | 2658 bool opt) const { |
2589 const intptr_t kNumInputs = 0; | 2659 const intptr_t kNumInputs = 0; |
2590 const intptr_t kNumTemps = 1; | 2660 const intptr_t kNumTemps = 1; |
2591 LocationSummary* summary = new(isolate) LocationSummary( | 2661 LocationSummary* summary = new(isolate) LocationSummary( |
2592 isolate, kNumInputs, | 2662 isolate, kNumInputs, |
2593 kNumTemps, | 2663 kNumTemps, |
(...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3149 } | 3219 } |
3150 | 3220 |
3151 | 3221 |
3152 LocationSummary* UnboxInstr::MakeLocationSummary(Isolate* isolate, | 3222 LocationSummary* UnboxInstr::MakeLocationSummary(Isolate* isolate, |
3153 bool opt) const { | 3223 bool opt) const { |
3154 const intptr_t kNumInputs = 1; | 3224 const intptr_t kNumInputs = 1; |
3155 const intptr_t kNumTemps = 0; | 3225 const intptr_t kNumTemps = 0; |
3156 LocationSummary* summary = new(isolate) LocationSummary( | 3226 LocationSummary* summary = new(isolate) LocationSummary( |
3157 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3227 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3158 summary->set_in(0, Location::RequiresRegister()); | 3228 summary->set_in(0, Location::RequiresRegister()); |
3159 summary->set_out(0, Location::RequiresFpuRegister()); | 3229 if (representation() == kUnboxedMint) { |
| 3230 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 3231 Location::RequiresRegister())); |
| 3232 } else { |
| 3233 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3234 } |
3160 return summary; | 3235 return summary; |
3161 } | 3236 } |
3162 | 3237 |
3163 | 3238 |
3164 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { | 3239 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { |
3165 const Register box = locs()->in(0).reg(); | 3240 const Register box = locs()->in(0).reg(); |
3166 | 3241 |
3167 switch (representation()) { | 3242 switch (representation()) { |
3168 case kUnboxedMint: { | 3243 case kUnboxedMint: { |
3169 UNIMPLEMENTED(); | 3244 PairLocation* result = locs()->out(0).AsPairLocation(); |
| 3245 __ LoadFromOffset(result->At(0).reg(), |
| 3246 box, |
| 3247 ValueOffset() - kHeapObjectTag); |
| 3248 __ LoadFromOffset(result->At(1).reg(), |
| 3249 box, |
| 3250 ValueOffset() - kHeapObjectTag + kWordSize); |
3170 break; | 3251 break; |
3171 } | 3252 } |
3172 | 3253 |
3173 case kUnboxedDouble: { | 3254 case kUnboxedDouble: { |
3174 const DRegister result = locs()->out(0).fpu_reg(); | 3255 const DRegister result = locs()->out(0).fpu_reg(); |
3175 __ LoadDFromOffset(result, box, Double::value_offset() - kHeapObjectTag); | 3256 __ LoadDFromOffset(result, box, Double::value_offset() - kHeapObjectTag); |
3176 break; | 3257 break; |
3177 } | 3258 } |
3178 | 3259 |
3179 case kUnboxedFloat32x4: | 3260 case kUnboxedFloat32x4: |
3180 case kUnboxedFloat64x2: | 3261 case kUnboxedFloat64x2: |
3181 case kUnboxedInt32x4: { | 3262 case kUnboxedInt32x4: { |
3182 UNIMPLEMENTED(); | 3263 UNIMPLEMENTED(); |
3183 break; | 3264 break; |
3184 } | 3265 } |
3185 | 3266 |
3186 default: | 3267 default: |
3187 UNREACHABLE(); | 3268 UNREACHABLE(); |
3188 break; | 3269 break; |
3189 } | 3270 } |
3190 } | 3271 } |
3191 | 3272 |
3192 | 3273 |
3193 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { | 3274 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { |
3194 const Register box = locs()->in(0).reg(); | 3275 const Register box = locs()->in(0).reg(); |
3195 | 3276 |
3196 switch (representation()) { | 3277 switch (representation()) { |
3197 case kUnboxedMint: { | 3278 case kUnboxedMint: { |
3198 UNIMPLEMENTED(); | 3279 PairLocation* result = locs()->out(0).AsPairLocation(); |
| 3280 __ SmiUntag(result->At(0).reg(), box); |
| 3281 __ sra(result->At(1).reg(), result->At(0).reg(), 31); |
3199 break; | 3282 break; |
3200 } | 3283 } |
3201 | 3284 |
3202 case kUnboxedDouble: { | 3285 case kUnboxedDouble: { |
3203 const DRegister result = locs()->out(0).fpu_reg(); | 3286 const DRegister result = locs()->out(0).fpu_reg(); |
3204 __ SmiUntag(TMP, box); | 3287 __ SmiUntag(TMP, box); |
3205 __ mtc1(TMP, STMP1); | 3288 __ mtc1(TMP, STMP1); |
3206 __ cvtdw(result, STMP1); | 3289 __ cvtdw(result, STMP1); |
3207 break; | 3290 break; |
3208 } | 3291 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3264 summary->set_out(0, Location::RequiresRegister()); | 3347 summary->set_out(0, Location::RequiresRegister()); |
3265 return summary; | 3348 return summary; |
3266 } | 3349 } |
3267 | 3350 |
3268 | 3351 |
3269 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3352 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3270 Register value = locs()->in(0).reg(); | 3353 Register value = locs()->in(0).reg(); |
3271 Register out = locs()->out(0).reg(); | 3354 Register out = locs()->out(0).reg(); |
3272 ASSERT(value != out); | 3355 ASSERT(value != out); |
3273 | 3356 |
3274 Label done; | |
3275 __ SmiTag(out, value); | 3357 __ SmiTag(out, value); |
3276 if (!ValueFitsSmi()) { | 3358 if (!ValueFitsSmi()) { |
3277 Register temp = locs()->temp(0).reg(); | 3359 Register temp = locs()->temp(0).reg(); |
| 3360 Label done; |
3278 if (from_representation() == kUnboxedInt32) { | 3361 if (from_representation() == kUnboxedInt32) { |
3279 __ SmiUntag(CMPRES1, out); | 3362 __ SmiUntag(CMPRES1, out); |
3280 __ BranchEqual(CMPRES1, value, &done); | 3363 __ BranchEqual(CMPRES1, value, &done); |
3281 } else { | 3364 } else { |
3282 ASSERT(from_representation() == kUnboxedUint32); | 3365 ASSERT(from_representation() == kUnboxedUint32); |
3283 __ AndImmediate(CMPRES1, value, 0xC0000000); | 3366 __ AndImmediate(CMPRES1, value, 0xC0000000); |
3284 __ BranchEqual(CMPRES1, ZR, &done); | 3367 __ BranchEqual(CMPRES1, ZR, &done); |
3285 } | 3368 } |
3286 BoxAllocationSlowPath::Allocate( | 3369 BoxAllocationSlowPath::Allocate( |
3287 compiler, | 3370 compiler, |
(...skipping 13 matching lines...) Expand all Loading... |
3301 out, | 3384 out, |
3302 Mint::value_offset() - kHeapObjectTag); | 3385 Mint::value_offset() - kHeapObjectTag); |
3303 __ StoreToOffset(hi, | 3386 __ StoreToOffset(hi, |
3304 out, | 3387 out, |
3305 Mint::value_offset() - kHeapObjectTag + kWordSize); | 3388 Mint::value_offset() - kHeapObjectTag + kWordSize); |
3306 __ Bind(&done); | 3389 __ Bind(&done); |
3307 } | 3390 } |
3308 } | 3391 } |
3309 | 3392 |
3310 | 3393 |
3311 DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt64Instr); | 3394 LocationSummary* BoxInt64Instr::MakeLocationSummary(Isolate* isolate, |
| 3395 bool opt) const { |
| 3396 const intptr_t kNumInputs = 1; |
| 3397 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
| 3398 LocationSummary* summary = new(isolate) LocationSummary( |
| 3399 isolate, |
| 3400 kNumInputs, |
| 3401 kNumTemps, |
| 3402 ValueFitsSmi() ? LocationSummary::kNoCall |
| 3403 : LocationSummary::kCallOnSlowPath); |
| 3404 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 3405 Location::RequiresRegister())); |
| 3406 if (!ValueFitsSmi()) { |
| 3407 summary->set_temp(0, Location::RequiresRegister()); |
| 3408 } |
| 3409 summary->set_out(0, Location::RequiresRegister()); |
| 3410 return summary; |
| 3411 } |
| 3412 |
| 3413 |
| 3414 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3415 if (ValueFitsSmi()) { |
| 3416 PairLocation* value_pair = locs()->in(0).AsPairLocation(); |
| 3417 Register value_lo = value_pair->At(0).reg(); |
| 3418 Register out_reg = locs()->out(0).reg(); |
| 3419 __ SmiTag(out_reg, value_lo); |
| 3420 return; |
| 3421 } |
| 3422 |
| 3423 PairLocation* value_pair = locs()->in(0).AsPairLocation(); |
| 3424 Register value_lo = value_pair->At(0).reg(); |
| 3425 Register value_hi = value_pair->At(1).reg(); |
| 3426 Register tmp = locs()->temp(0).reg(); |
| 3427 Register out_reg = locs()->out(0).reg(); |
| 3428 |
| 3429 Label not_smi, done; |
| 3430 __ SmiTag(out_reg, value_lo); |
| 3431 __ SmiUntag(tmp, out_reg); |
| 3432 __ bne(tmp, value_lo, ¬_smi); |
| 3433 __ delay_slot()->sra(tmp, out_reg, 31); |
| 3434 __ beq(tmp, value_hi, &done); |
| 3435 |
| 3436 __ Bind(¬_smi); |
| 3437 BoxAllocationSlowPath::Allocate( |
| 3438 compiler, |
| 3439 this, |
| 3440 compiler->mint_class(), |
| 3441 out_reg, |
| 3442 tmp); |
| 3443 __ StoreToOffset(value_lo, out_reg, Mint::value_offset() - kHeapObjectTag); |
| 3444 __ StoreToOffset(value_hi, |
| 3445 out_reg, |
| 3446 Mint::value_offset() - kHeapObjectTag + kWordSize); |
| 3447 __ Bind(&done); |
| 3448 } |
| 3449 |
3312 | 3450 |
3313 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Isolate* isolate, | 3451 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Isolate* isolate, |
3314 bool opt) const { | 3452 bool opt) const { |
3315 ASSERT((representation() == kUnboxedInt32) || | 3453 ASSERT((representation() == kUnboxedInt32) || |
3316 (representation() == kUnboxedUint32)); | 3454 (representation() == kUnboxedUint32)); |
3317 const intptr_t kNumInputs = 1; | 3455 const intptr_t kNumInputs = 1; |
3318 const intptr_t kNumTemps = 0; | 3456 const intptr_t kNumTemps = 0; |
3319 LocationSummary* summary = new(isolate) LocationSummary( | 3457 LocationSummary* summary = new(isolate) LocationSummary( |
3320 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3458 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3321 summary->set_in(0, Location::RequiresRegister()); | 3459 summary->set_in(0, Location::RequiresRegister()); |
(...skipping 1124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4446 instance_call()->token_pos(), | 4584 instance_call()->token_pos(), |
4447 target, | 4585 target, |
4448 instance_call()->ArgumentCount(), | 4586 instance_call()->ArgumentCount(), |
4449 instance_call()->argument_names(), | 4587 instance_call()->argument_names(), |
4450 locs(), | 4588 locs(), |
4451 ICData::Handle()); | 4589 ICData::Handle()); |
4452 return; | 4590 return; |
4453 } | 4591 } |
4454 | 4592 |
4455 // Load receiver into T0. | 4593 // Load receiver into T0. |
4456 __ lw(T0, Address(SP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 4594 __ LoadFromOffset(T0, SP, (instance_call()->ArgumentCount() - 1) * kWordSize); |
4457 | 4595 |
4458 Label* deopt = compiler->AddDeoptStub( | 4596 Label* deopt = compiler->AddDeoptStub( |
4459 deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail); | 4597 deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail); |
4460 LoadValueCid(compiler, T2, T0, | 4598 LoadValueCid(compiler, T2, T0, |
4461 (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt); | 4599 (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt); |
4462 | 4600 |
4463 compiler->EmitTestAndCall(ic_data(), | 4601 compiler->EmitTestAndCall(ic_data(), |
4464 T2, // Class id register. | 4602 T2, // Class id register. |
4465 instance_call()->ArgumentCount(), | 4603 instance_call()->ArgumentCount(), |
4466 instance_call()->argument_names(), | 4604 instance_call()->argument_names(), |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4650 __ BranchUnsignedGreaterEqual( | 4788 __ BranchUnsignedGreaterEqual( |
4651 index, Immediate(reinterpret_cast<int32_t>(length.raw())), deopt); | 4789 index, Immediate(reinterpret_cast<int32_t>(length.raw())), deopt); |
4652 } | 4790 } |
4653 } else { | 4791 } else { |
4654 Register length = length_loc.reg(); | 4792 Register length = length_loc.reg(); |
4655 Register index = index_loc.reg(); | 4793 Register index = index_loc.reg(); |
4656 __ BranchUnsignedGreaterEqual(index, length, deopt); | 4794 __ BranchUnsignedGreaterEqual(index, length, deopt); |
4657 } | 4795 } |
4658 } | 4796 } |
4659 | 4797 |
4660 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryMintOpInstr); | 4798 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 4799 bool opt) const { |
| 4800 const intptr_t kNumInputs = 2; |
| 4801 const intptr_t kNumTemps = 0; |
| 4802 LocationSummary* summary = new(isolate) LocationSummary( |
| 4803 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4804 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 4805 Location::RequiresRegister())); |
| 4806 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 4807 Location::RequiresRegister())); |
| 4808 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 4809 Location::RequiresRegister())); |
| 4810 return summary; |
| 4811 } |
| 4812 |
| 4813 |
| 4814 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4815 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| 4816 Register left_lo = left_pair->At(0).reg(); |
| 4817 Register left_hi = left_pair->At(1).reg(); |
| 4818 PairLocation* right_pair = locs()->in(1).AsPairLocation(); |
| 4819 Register right_lo = right_pair->At(0).reg(); |
| 4820 Register right_hi = right_pair->At(1).reg(); |
| 4821 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 4822 Register out_lo = out_pair->At(0).reg(); |
| 4823 Register out_hi = out_pair->At(1).reg(); |
| 4824 |
| 4825 Label* deopt = NULL; |
| 4826 if (CanDeoptimize()) { |
| 4827 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 4828 } |
| 4829 switch (op_kind()) { |
| 4830 case Token::kBIT_AND: { |
| 4831 __ and_(out_lo, left_lo, right_lo); |
| 4832 __ and_(out_hi, left_hi, right_hi); |
| 4833 break; |
| 4834 } |
| 4835 case Token::kBIT_OR: { |
| 4836 __ or_(out_lo, left_lo, right_lo); |
| 4837 __ or_(out_hi, left_hi, right_hi); |
| 4838 break; |
| 4839 } |
| 4840 case Token::kBIT_XOR: { |
| 4841 __ xor_(out_lo, left_lo, right_lo); |
| 4842 __ xor_(out_hi, left_hi, right_hi); |
| 4843 break; |
| 4844 } |
| 4845 case Token::kADD: |
| 4846 case Token::kSUB: { |
| 4847 if (op_kind() == Token::kADD) { |
| 4848 __ addu(out_lo, left_lo, right_lo); |
| 4849 __ sltu(TMP, out_lo, left_lo); // TMP = carry of left_lo + right_lo. |
| 4850 __ addu(out_hi, left_hi, right_hi); |
| 4851 __ addu(out_hi, out_hi, TMP); |
| 4852 if (can_overflow()) { |
| 4853 __ xor_(CMPRES1, out_hi, left_hi); |
| 4854 __ xor_(TMP, out_hi, right_hi); |
| 4855 __ and_(CMPRES1, TMP, CMPRES1); |
| 4856 __ bltz(CMPRES1, deopt); |
| 4857 } |
| 4858 } else { |
| 4859 __ subu(out_lo, left_lo, right_lo); |
| 4860 __ sltu(TMP, left_lo, out_lo); // TMP = borrow of left_lo - right_lo. |
| 4861 __ subu(out_hi, left_hi, right_hi); |
| 4862 __ subu(out_hi, out_hi, TMP); |
| 4863 if (can_overflow()) { |
| 4864 __ xor_(CMPRES1, out_hi, left_hi); |
| 4865 __ xor_(TMP, left_hi, right_hi); |
| 4866 __ and_(CMPRES1, TMP, CMPRES1); |
| 4867 __ bltz(CMPRES1, deopt); |
| 4868 } |
| 4869 } |
| 4870 break; |
| 4871 } |
| 4872 case Token::kMUL: { |
| 4873 // The product of two signed 32-bit integers fits in a signed 64-bit |
| 4874 // result without causing overflow. |
| 4875 // We deopt on larger inputs. |
| 4876 // TODO(regis): Range analysis may eliminate the deopt check. |
| 4877 __ sra(CMPRES1, left_lo, 31); |
| 4878 __ bne(CMPRES1, left_hi, deopt); |
| 4879 __ delay_slot()->sra(CMPRES2, right_lo, 31); |
| 4880 __ bne(CMPRES2, right_hi, deopt); |
| 4881 __ delay_slot()->mult(left_lo, right_lo); |
| 4882 __ mflo(out_lo); |
| 4883 __ mfhi(out_hi); |
| 4884 break; |
| 4885 } |
| 4886 default: |
| 4887 UNREACHABLE(); |
| 4888 } |
| 4889 } |
| 4890 |
| 4891 |
| 4892 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 4893 bool opt) const { |
| 4894 const intptr_t kNumInputs = 2; |
| 4895 const intptr_t kNumTemps = 0; |
| 4896 LocationSummary* summary = new(isolate) LocationSummary( |
| 4897 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4898 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 4899 Location::RequiresRegister())); |
| 4900 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); |
| 4901 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 4902 Location::RequiresRegister())); |
| 4903 return summary; |
| 4904 } |
| 4905 |
| 4906 |
| 4907 static const intptr_t kMintShiftCountLimit = 63; |
4661 | 4908 |
4662 bool ShiftMintOpInstr::has_shift_count_check() const { | 4909 bool ShiftMintOpInstr::has_shift_count_check() const { |
4663 UNREACHABLE(); | 4910 return !RangeUtils::IsWithin( |
4664 return false; | 4911 right()->definition()->range(), 0, kMintShiftCountLimit); |
4665 } | 4912 } |
4666 | 4913 |
4667 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftMintOpInstr); | 4914 |
4668 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryMintOpInstr); | 4915 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4916 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| 4917 Register left_lo = left_pair->At(0).reg(); |
| 4918 Register left_hi = left_pair->At(1).reg(); |
| 4919 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 4920 Register out_lo = out_pair->At(0).reg(); |
| 4921 Register out_hi = out_pair->At(1).reg(); |
| 4922 |
| 4923 Label* deopt = NULL; |
| 4924 if (CanDeoptimize()) { |
| 4925 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
| 4926 } |
| 4927 if (locs()->in(1).IsConstant()) { |
| 4928 // Code for a constant shift amount. |
| 4929 ASSERT(locs()->in(1).constant().IsSmi()); |
| 4930 const int32_t shift = |
| 4931 reinterpret_cast<int32_t>(locs()->in(1).constant().raw()) >> 1; |
| 4932 switch (op_kind()) { |
| 4933 case Token::kSHR: { |
| 4934 if (shift < 32) { |
| 4935 __ sll(out_lo, left_hi, 32 - shift); |
| 4936 __ srl(TMP, left_lo, shift); |
| 4937 __ or_(out_lo, out_lo, TMP); |
| 4938 __ sra(out_hi, left_hi, shift); |
| 4939 } else { |
| 4940 __ sra(out_lo, left_hi, shift - 32); |
| 4941 __ sra(out_hi, left_hi, 31); |
| 4942 } |
| 4943 break; |
| 4944 } |
| 4945 case Token::kSHL: { |
| 4946 if (shift < 32) { |
| 4947 __ srl(out_hi, left_lo, 32 - shift); |
| 4948 __ sll(TMP, left_hi, shift); |
| 4949 __ or_(out_hi, out_hi, TMP); |
| 4950 __ sll(out_lo, left_lo, shift); |
| 4951 } else { |
| 4952 __ sll(out_hi, left_lo, shift - 32); |
| 4953 __ mov(out_lo, ZR); |
| 4954 } |
| 4955 // Check for overflow. |
| 4956 if (can_overflow()) { |
| 4957 // Compare high word from input with shifted high word from output. |
| 4958 // Overflow if they aren't equal. |
| 4959 // If shift > 32, also compare low word from input with high word from |
| 4960 // output shifted back shift - 32. |
| 4961 if (shift > 32) { |
| 4962 __ sra(TMP, out_hi, shift - 32); |
| 4963 __ bne(left_lo, TMP, deopt); |
| 4964 __ delay_slot()->sra(TMP, out_hi, 31); |
| 4965 } else if (shift == 32) { |
| 4966 __ sra(TMP, out_hi, 31); |
| 4967 } else { |
| 4968 __ sra(TMP, out_hi, shift); |
| 4969 } |
| 4970 __ bne(left_hi, TMP, deopt); |
| 4971 } |
| 4972 break; |
| 4973 } |
| 4974 default: |
| 4975 UNREACHABLE(); |
| 4976 } |
| 4977 } else { |
| 4978 // Code for a variable shift amount. |
| 4979 Register shift = locs()->in(1).reg(); |
| 4980 |
| 4981 // Deopt if shift is larger than 63 or less than 0. |
| 4982 if (has_shift_count_check()) { |
| 4983 __ sltiu(CMPRES1, shift, Immediate(2*(kMintShiftCountLimit + 1))); |
| 4984 __ beq(CMPRES1, ZR, deopt); |
| 4985 // Untag shift count. |
| 4986 __ delay_slot()->SmiUntag(shift); |
| 4987 } else { |
| 4988 // Untag shift count. |
| 4989 __ SmiUntag(shift); |
| 4990 } |
| 4991 |
| 4992 switch (op_kind()) { |
| 4993 case Token::kSHR: { |
| 4994 Label large_shift, done; |
| 4995 __ sltiu(CMPRES1, shift, Immediate(32)); |
| 4996 __ beq(CMPRES1, ZR, &large_shift); |
| 4997 |
| 4998 // shift < 32. |
| 4999 __ delay_slot()->ori(TMP, ZR, Immediate(32)); |
| 5000 __ subu(TMP, TMP, shift); // TMP = 32 - shift; 0 < TMP <= 31. |
| 5001 __ sllv(out_lo, left_hi, TMP); |
| 5002 __ srlv(TMP, left_lo, shift); |
| 5003 __ or_(out_lo, out_lo, TMP); |
| 5004 __ b(&done); |
| 5005 __ delay_slot()->srav(out_hi, left_hi, shift); |
| 5006 |
| 5007 // shift >= 32. |
| 5008 __ Bind(&large_shift); |
| 5009 __ sra(out_hi, left_hi, 31); |
| 5010 __ srav(out_lo, left_hi, shift); // Only 5 low bits of shift used. |
| 5011 |
| 5012 __ Bind(&done); |
| 5013 break; |
| 5014 } |
| 5015 case Token::kSHL: { |
| 5016 Label large_shift, done; |
| 5017 __ sltiu(CMPRES1, shift, Immediate(32)); |
| 5018 __ beq(CMPRES1, ZR, &large_shift); |
| 5019 |
| 5020 // shift < 32. |
| 5021 __ delay_slot()->ori(TMP, ZR, Immediate(32)); |
| 5022 __ subu(TMP, TMP, shift); // TMP = 32 - shift; 0 < TMP <= 31. |
| 5023 __ srlv(out_hi, left_lo, TMP); |
| 5024 __ sllv(TMP, left_hi, shift); |
| 5025 __ or_(out_hi, out_hi, TMP); |
| 5026 // Check for overflow. |
| 5027 if (can_overflow()) { |
| 5028 // Compare high word from input with shifted high word from output. |
| 5029 __ srav(TMP, out_hi, shift); |
| 5030 __ beq(TMP, left_hi, &done); |
| 5031 __ delay_slot()->sllv(out_lo, left_lo, shift); |
| 5032 __ b(deopt); |
| 5033 } else { |
| 5034 __ b(&done); |
| 5035 __ delay_slot()->sllv(out_lo, left_lo, shift); |
| 5036 } |
| 5037 |
| 5038 // shift >= 32. |
| 5039 __ Bind(&large_shift); |
| 5040 __ sllv(out_hi, left_lo, shift); // Only 5 low bits of shift used. |
| 5041 // Check for overflow. |
| 5042 if (can_overflow()) { |
| 5043 // Compare low word from input with shifted high word from output and |
| 5044 // high word from input to sign of output. |
| 5045 // Overflow if they aren't equal. |
| 5046 __ srav(TMP, out_hi, shift); |
| 5047 __ bne(TMP, left_lo, deopt); |
| 5048 __ delay_slot()->sra(TMP, out_hi, 31); |
| 5049 __ bne(TMP, left_hi, deopt); |
| 5050 __ delay_slot()->mov(out_lo, ZR); |
| 5051 } else { |
| 5052 __ mov(out_lo, ZR); |
| 5053 } |
| 5054 __ Bind(&done); |
| 5055 break; |
| 5056 } |
| 5057 default: |
| 5058 UNREACHABLE(); |
| 5059 } |
| 5060 } |
| 5061 } |
| 5062 |
| 5063 |
| 5064 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5065 bool opt) const { |
| 5066 const intptr_t kNumInputs = 1; |
| 5067 const intptr_t kNumTemps = 0; |
| 5068 LocationSummary* summary = new(isolate) LocationSummary( |
| 5069 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5070 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5071 Location::RequiresRegister())); |
| 5072 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 5073 Location::RequiresRegister())); |
| 5074 return summary; |
| 5075 } |
| 5076 |
| 5077 |
| 5078 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5079 ASSERT(op_kind() == Token::kBIT_NOT); |
| 5080 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| 5081 Register left_lo = left_pair->At(0).reg(); |
| 5082 Register left_hi = left_pair->At(1).reg(); |
| 5083 |
| 5084 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 5085 Register out_lo = out_pair->At(0).reg(); |
| 5086 Register out_hi = out_pair->At(1).reg(); |
| 5087 |
| 5088 __ nor(out_lo, ZR, left_lo); |
| 5089 __ nor(out_hi, ZR, left_hi); |
| 5090 } |
| 5091 |
4669 | 5092 |
4670 CompileType BinaryUint32OpInstr::ComputeType() const { | 5093 CompileType BinaryUint32OpInstr::ComputeType() const { |
4671 return CompileType::Int(); | 5094 return CompileType::Int(); |
4672 } | 5095 } |
4673 | 5096 |
4674 | 5097 |
4675 CompileType ShiftUint32OpInstr::ComputeType() const { | 5098 CompileType ShiftUint32OpInstr::ComputeType() const { |
4676 return CompileType::Int(); | 5099 return CompileType::Int(); |
4677 } | 5100 } |
4678 | 5101 |
4679 | 5102 |
4680 CompileType UnaryUint32OpInstr::ComputeType() const { | 5103 CompileType UnaryUint32OpInstr::ComputeType() const { |
4681 return CompileType::Int(); | 5104 return CompileType::Int(); |
4682 } | 5105 } |
4683 | 5106 |
4684 | 5107 |
4685 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) | 5108 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
4686 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) | 5109 bool opt) const { |
4687 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) | 5110 const intptr_t kNumInputs = 2; |
| 5111 const intptr_t kNumTemps = 0; |
| 5112 LocationSummary* summary = new(isolate) LocationSummary( |
| 5113 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5114 summary->set_in(0, Location::RequiresRegister()); |
| 5115 summary->set_in(1, Location::RequiresRegister()); |
| 5116 summary->set_out(0, Location::RequiresRegister()); |
| 5117 return summary; |
| 5118 } |
| 5119 |
| 5120 |
| 5121 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5122 Register left = locs()->in(0).reg(); |
| 5123 Register right = locs()->in(1).reg(); |
| 5124 Register out = locs()->out(0).reg(); |
| 5125 ASSERT(out != left); |
| 5126 switch (op_kind()) { |
| 5127 case Token::kBIT_AND: |
| 5128 __ and_(out, left, right); |
| 5129 break; |
| 5130 case Token::kBIT_OR: |
| 5131 __ or_(out, left, right); |
| 5132 break; |
| 5133 case Token::kBIT_XOR: |
| 5134 __ xor_(out, left, right); |
| 5135 break; |
| 5136 case Token::kADD: |
| 5137 __ addu(out, left, right); |
| 5138 break; |
| 5139 case Token::kSUB: |
| 5140 __ subu(out, left, right); |
| 5141 break; |
| 5142 case Token::kMUL: |
| 5143 __ multu(left, right); |
| 5144 __ mflo(out); |
| 5145 break; |
| 5146 default: |
| 5147 UNREACHABLE(); |
| 5148 } |
| 5149 } |
| 5150 |
| 5151 |
| 5152 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 5153 bool opt) const { |
| 5154 const intptr_t kNumInputs = 2; |
| 5155 const intptr_t kNumTemps = 1; |
| 5156 LocationSummary* summary = new(isolate) LocationSummary( |
| 5157 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5158 summary->set_in(0, Location::RequiresRegister()); |
| 5159 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 5160 summary->set_temp(0, Location::RequiresRegister()); |
| 5161 summary->set_out(0, Location::RequiresRegister()); |
| 5162 return summary; |
| 5163 } |
| 5164 |
| 5165 |
| 5166 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5167 const intptr_t kShifterLimit = 31; |
| 5168 |
| 5169 Register left = locs()->in(0).reg(); |
| 5170 Register out = locs()->out(0).reg(); |
| 5171 Register temp = locs()->temp(0).reg(); |
| 5172 |
| 5173 ASSERT(left != out); |
| 5174 |
| 5175 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
| 5176 |
| 5177 if (locs()->in(1).IsConstant()) { |
| 5178 // Shifter is constant. |
| 5179 |
| 5180 const Object& constant = locs()->in(1).constant(); |
| 5181 ASSERT(constant.IsSmi()); |
| 5182 const intptr_t shift_value = Smi::Cast(constant).Value(); |
| 5183 |
| 5184 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). |
| 5185 switch (op_kind()) { |
| 5186 case Token::kSHR: |
| 5187 __ srl(out, left, shift_value); |
| 5188 break; |
| 5189 case Token::kSHL: |
| 5190 __ sll(out, left, shift_value); |
| 5191 break; |
| 5192 default: |
| 5193 UNREACHABLE(); |
| 5194 } |
| 5195 return; |
| 5196 } |
| 5197 |
| 5198 // Non constant shift value. |
| 5199 Register shifter = locs()->in(1).reg(); |
| 5200 |
| 5201 __ SmiUntag(temp, shifter); |
| 5202 // If shift value is < 0, deoptimize. |
| 5203 __ bltz(temp, deopt); |
| 5204 __ delay_slot()->mov(out, left); |
| 5205 __ sltiu(CMPRES1, temp, Immediate(kShifterLimit + 1)); |
| 5206 __ movz(out, ZR, CMPRES1); // out = shift > kShifterLimit ? 0 : left. |
| 5207 // Do the shift % 32. |
| 5208 switch (op_kind()) { |
| 5209 case Token::kSHR: |
| 5210 __ srlv(out, out, temp); |
| 5211 break; |
| 5212 case Token::kSHL: |
| 5213 __ sllv(out, out, temp); |
| 5214 break; |
| 5215 default: |
| 5216 UNREACHABLE(); |
| 5217 } |
| 5218 } |
| 5219 |
| 5220 |
| 5221 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 5222 bool opt) const { |
| 5223 const intptr_t kNumInputs = 1; |
| 5224 const intptr_t kNumTemps = 0; |
| 5225 LocationSummary* summary = new(isolate) LocationSummary( |
| 5226 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5227 summary->set_in(0, Location::RequiresRegister()); |
| 5228 summary->set_out(0, Location::RequiresRegister()); |
| 5229 return summary; |
| 5230 } |
| 5231 |
| 5232 |
| 5233 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5234 Register left = locs()->in(0).reg(); |
| 5235 Register out = locs()->out(0).reg(); |
| 5236 ASSERT(left != out); |
| 5237 |
| 5238 ASSERT(op_kind() == Token::kBIT_NOT); |
| 5239 |
| 5240 __ nor(out, ZR, left); |
| 5241 } |
| 5242 |
| 5243 |
4688 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 5244 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
4689 | 5245 |
4690 | 5246 |
4691 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, | 5247 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, |
4692 bool opt) const { | 5248 bool opt) const { |
4693 const intptr_t kNumInputs = 1; | 5249 const intptr_t kNumInputs = 1; |
4694 const intptr_t kNumTemps = 0; | 5250 const intptr_t kNumTemps = 0; |
4695 LocationSummary* summary = new(isolate) LocationSummary( | 5251 LocationSummary* summary = new(isolate) LocationSummary( |
4696 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5252 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4697 if (from() == kUnboxedMint) { | 5253 if (from() == kUnboxedMint) { |
4698 UNREACHABLE(); | 5254 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 5255 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5256 Location::RequiresRegister())); |
| 5257 summary->set_out(0, Location::RequiresRegister()); |
4699 } else if (to() == kUnboxedMint) { | 5258 } else if (to() == kUnboxedMint) { |
4700 UNREACHABLE(); | 5259 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 5260 summary->set_in(0, Location::RequiresRegister()); |
| 5261 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 5262 Location::RequiresRegister())); |
4701 } else { | 5263 } else { |
4702 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 5264 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
4703 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 5265 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
4704 summary->set_in(0, Location::RequiresRegister()); | 5266 summary->set_in(0, Location::RequiresRegister()); |
4705 summary->set_out(0, Location::SameAsFirstInput()); | 5267 summary->set_out(0, Location::SameAsFirstInput()); |
4706 } | 5268 } |
4707 return summary; | 5269 return summary; |
4708 } | 5270 } |
4709 | 5271 |
4710 | 5272 |
4711 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5273 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4712 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { | 5274 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { |
4713 const Register out = locs()->out(0).reg(); | 5275 const Register out = locs()->out(0).reg(); |
4714 // Representations are bitwise equivalent. | 5276 // Representations are bitwise equivalent. |
4715 ASSERT(out == locs()->in(0).reg()); | 5277 ASSERT(out == locs()->in(0).reg()); |
4716 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { | 5278 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { |
4717 const Register out = locs()->out(0).reg(); | 5279 const Register out = locs()->out(0).reg(); |
4718 // Representations are bitwise equivalent. | 5280 // Representations are bitwise equivalent. |
4719 ASSERT(out == locs()->in(0).reg()); | 5281 ASSERT(out == locs()->in(0).reg()); |
4720 if (CanDeoptimize()) { | 5282 if (CanDeoptimize()) { |
4721 Label* deopt = | 5283 Label* deopt = |
4722 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); | 5284 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); |
4723 __ BranchSignedLess(out, Immediate(0), deopt); | 5285 __ BranchSignedLess(out, Immediate(0), deopt); |
4724 } | 5286 } |
4725 } else if (from() == kUnboxedMint) { | 5287 } else if (from() == kUnboxedMint) { |
4726 UNREACHABLE(); | 5288 ASSERT(to() == kUnboxedUint32 || to() == kUnboxedInt32); |
4727 } else if (to() == kUnboxedMint) { | 5289 PairLocation* in_pair = locs()->in(0).AsPairLocation(); |
4728 ASSERT(from() == kUnboxedUint32 || from() == kUnboxedInt32); | 5290 Register in_lo = in_pair->At(0).reg(); |
4729 UNREACHABLE(); | 5291 Register in_hi = in_pair->At(1).reg(); |
| 5292 Register out = locs()->out(0).reg(); |
| 5293 // Copy low word. |
| 5294 __ mov(out, in_lo); |
| 5295 if (CanDeoptimize()) { |
| 5296 Label* deopt = |
| 5297 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); |
| 5298 ASSERT(to() == kUnboxedInt32); |
| 5299 __ sra(TMP, in_lo, 31); |
| 5300 __ bne(in_hi, TMP, deopt); |
| 5301 } |
| 5302 } else if (from() == kUnboxedUint32 || from() == kUnboxedInt32) { |
| 5303 ASSERT(to() == kUnboxedMint); |
| 5304 Register in = locs()->in(0).reg(); |
| 5305 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 5306 Register out_lo = out_pair->At(0).reg(); |
| 5307 Register out_hi = out_pair->At(1).reg(); |
| 5308 // Copy low word. |
| 5309 __ mov(out_lo, in); |
| 5310 if (from() == kUnboxedUint32) { |
| 5311 __ xor_(out_hi, out_hi, out_hi); |
| 5312 } else { |
| 5313 ASSERT(from() == kUnboxedInt32); |
| 5314 __ sra(out_hi, in, 31); |
| 5315 } |
4730 } else { | 5316 } else { |
4731 UNREACHABLE(); | 5317 UNREACHABLE(); |
4732 } | 5318 } |
4733 } | 5319 } |
4734 | 5320 |
4735 | 5321 |
4736 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 5322 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
4737 bool opt) const { | 5323 bool opt) const { |
4738 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 5324 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
4739 } | 5325 } |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4971 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 5557 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
4972 #if defined(DEBUG) | 5558 #if defined(DEBUG) |
4973 __ LoadImmediate(S4, kInvalidObjectPointer); | 5559 __ LoadImmediate(S4, kInvalidObjectPointer); |
4974 __ LoadImmediate(S5, kInvalidObjectPointer); | 5560 __ LoadImmediate(S5, kInvalidObjectPointer); |
4975 #endif | 5561 #endif |
4976 } | 5562 } |
4977 | 5563 |
4978 } // namespace dart | 5564 } // namespace dart |
4979 | 5565 |
4980 #endif // defined TARGET_ARCH_MIPS | 5566 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |