Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: runtime/vm/intermediate_language_mips.cc

Issue 777943003: Implement mint unboxing on MIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | tests/standalone/standalone.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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, &not_smi);
3433 __ delay_slot()->sra(tmp, out_reg, 31);
3434 __ beq(tmp, value_hi, &done);
3435
3436 __ Bind(&not_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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | tests/standalone/standalone.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698