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

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

Issue 252333002: Use GPRs for mints (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 months 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
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_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 default: 373 default:
374 UNREACHABLE(); 374 UNREACHABLE();
375 return VS; 375 return VS;
376 } 376 }
377 } 377 }
378 378
379 379
380 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { 380 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const {
381 const intptr_t kNumInputs = 2; 381 const intptr_t kNumInputs = 2;
382 if (operation_cid() == kMintCid) { 382 if (operation_cid() == kMintCid) {
383 const intptr_t kNumTemps = 3; 383 const intptr_t kNumTemps = 0;
384 LocationSummary* locs = 384 LocationSummary* locs =
385 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 385 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
386 locs->set_in(0, Location::RequiresFpuRegister()); 386 locs->set_in(0, Location::Pair(Location::RequiresRegister(),
387 locs->set_in(1, Location::RequiresFpuRegister()); 387 Location::RequiresRegister()));
388 locs->set_temp(0, Location::RequiresFpuRegister()); 388 locs->set_in(1, Location::Pair(Location::RequiresRegister(),
389 locs->set_temp(1, Location::RequiresRegister()); 389 Location::RequiresRegister()));
390 locs->set_temp(2, Location::RequiresRegister());
391 locs->set_out(0, Location::RequiresRegister()); 390 locs->set_out(0, Location::RequiresRegister());
392 return locs; 391 return locs;
393 } 392 }
394 if (operation_cid() == kDoubleCid) { 393 if (operation_cid() == kDoubleCid) {
395 const intptr_t kNumTemps = 0; 394 const intptr_t kNumTemps = 0;
396 LocationSummary* locs = 395 LocationSummary* locs =
397 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 396 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
398 locs->set_in(0, Location::RequiresFpuRegister()); 397 locs->set_in(0, Location::RequiresFpuRegister());
399 locs->set_in(1, Location::RequiresFpuRegister()); 398 locs->set_in(1, Location::RequiresFpuRegister());
400 locs->set_out(0, Location::RequiresRegister()); 399 locs->set_out(0, Location::RequiresRegister());
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 UNREACHABLE(); 507 UNREACHABLE();
509 return VS; 508 return VS;
510 } 509 }
511 } 510 }
512 511
513 512
514 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, 513 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
515 LocationSummary* locs, 514 LocationSummary* locs,
516 Token::Kind kind) { 515 Token::Kind kind) {
517 ASSERT(Token::IsEqualityOperator(kind)); 516 ASSERT(Token::IsEqualityOperator(kind));
518 QRegister left = locs->in(0).fpu_reg(); 517 PairLocation* left_pair = locs->in(0).AsPairLocation();
519 QRegister right = locs->in(1).fpu_reg(); 518 Register left1 = left_pair->At(0).reg();
520 QRegister tmpq = locs->temp(0).fpu_reg(); 519 Register left2 = left_pair->At(1).reg();
521 Register tmp_lo = locs->temp(1).reg(); 520 PairLocation* right_pair = locs->in(1).AsPairLocation();
522 Register tmp_hi = locs->temp(2).reg(); 521 Register right1 = right_pair->At(0).reg();
522 Register right2 = right_pair->At(1).reg();
523 523
524 __ vceqqi(kWord, tmpq, left, right); 524 // Compare lower.
525 __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(tmpq)); 525 __ cmp(left1, ShifterOperand(right1));
526 // tmp_lo and tmp_hi must both be 0xffffffff. 526 // Compare upper if lower is equal.
527 __ and_(tmp_lo, tmp_lo, ShifterOperand(tmp_hi)); 527 __ cmp(left2, ShifterOperand(right2), EQ);
528 528 return TokenKindToMintCondition(kind);
529 Condition true_condition = TokenKindToMintCondition(kind);
530 __ CompareImmediate(tmp_lo, 0xffffffff);
531 return true_condition;
532 } 529 }
533 530
534 531
535 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, 532 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
536 LocationSummary* locs, 533 LocationSummary* locs,
537 Token::Kind kind) { 534 Token::Kind kind) {
538 QRegister left = locs->in(0).fpu_reg(); 535 PairLocation* left_pair = locs->in(0).AsPairLocation();
539 QRegister right = locs->in(1).fpu_reg(); 536 Register left1 = left_pair->At(0).reg();
540 DRegister dleft0 = EvenDRegisterOf(left); 537 Register left2 = left_pair->At(1).reg();
541 DRegister dright0 = EvenDRegisterOf(right); 538 PairLocation* right_pair = locs->in(1).AsPairLocation();
542 SRegister sleft0 = EvenSRegisterOf(dleft0); 539 Register right1 = right_pair->At(0).reg();
543 SRegister sleft1 = OddSRegisterOf(dleft0); 540 Register right2 = right_pair->At(1).reg();
544 SRegister sright0 = EvenSRegisterOf(dright0);
545 SRegister sright1 = OddSRegisterOf(dright0);
546 541
547 Register tmp_left = locs->temp(0).reg(); 542 Register out = locs->temp(0).reg();
548 Register tmp_right = locs->temp(1).reg();
549 543
550 // 64-bit comparison 544 // 64-bit comparison
551 Condition hi_true_cond, hi_false_cond, lo_false_cond; 545 Condition hi_true_cond, hi_false_cond, lo_false_cond;
552 switch (kind) { 546 switch (kind) {
553 case Token::kLT: 547 case Token::kLT:
554 case Token::kLTE: 548 case Token::kLTE:
555 hi_true_cond = LT; 549 hi_true_cond = LT;
556 hi_false_cond = GT; 550 hi_false_cond = GT;
557 lo_false_cond = (kind == Token::kLT) ? CS : HI; 551 lo_false_cond = (kind == Token::kLT) ? CS : HI;
558 break; 552 break;
559 case Token::kGT: 553 case Token::kGT:
560 case Token::kGTE: 554 case Token::kGTE:
561 hi_true_cond = GT; 555 hi_true_cond = GT;
562 hi_false_cond = LT; 556 hi_false_cond = LT;
563 lo_false_cond = (kind == Token::kGT) ? LS : CC; 557 lo_false_cond = (kind == Token::kGT) ? LS : CC;
564 break; 558 break;
565 default: 559 default:
566 UNREACHABLE(); 560 UNREACHABLE();
567 hi_true_cond = hi_false_cond = lo_false_cond = VS; 561 hi_true_cond = hi_false_cond = lo_false_cond = VS;
568 } 562 }
569 563
570 Label is_true, is_false, done; 564 Label is_true, is_false, done;
571 __ vmovrs(tmp_left, sleft1); 565 // Compare upper halves first.
572 __ vmovrs(tmp_right, sright1); 566 __ cmp(left2, ShifterOperand(right2));
573 __ cmp(tmp_left, ShifterOperand(tmp_right)); 567 __ LoadImmediate(out, 0, hi_false_cond);
574 __ b(&is_false, hi_false_cond); 568 __ LoadImmediate(out, 1, hi_true_cond);
575 __ b(&is_true, hi_true_cond); 569 // If higher words aren't equal, skip comparing lower words.
570 __ b(&done, NE);
576 571
577 __ vmovrs(tmp_left, sleft0); 572 __ cmp(left1, ShifterOperand(right1));
578 __ vmovrs(tmp_right, sright0); 573 __ LoadImmediate(out, 1);
579 __ cmp(tmp_left, ShifterOperand(tmp_right)); 574 __ LoadImmediate(out, 0, lo_false_cond);
580 __ b(&is_false, lo_false_cond); 575 __ Bind(&done);
581 // Else is true.
582 __ b(&is_true);
583 576
584 __ Bind(&is_false);
585 __ LoadImmediate(tmp_left, 0);
586 __ b(&done);
587 __ Bind(&is_true);
588 __ LoadImmediate(tmp_left, 1);
589 __ Bind(&done);
590 return NegateCondition(lo_false_cond); 577 return NegateCondition(lo_false_cond);
591 } 578 }
592 579
593 580
594 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 581 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
595 switch (kind) { 582 switch (kind) {
596 case Token::kEQ: return EQ; 583 case Token::kEQ: return EQ;
597 case Token::kNE: return NE; 584 case Token::kNE: return NE;
598 case Token::kLT: return LT; 585 case Token::kLT: return LT;
599 case Token::kGT: return GT; 586 case Token::kGT: return GT;
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
786 __ Bind(&is_true); 773 __ Bind(&is_true);
787 __ LoadObject(result_reg, Bool::True()); 774 __ LoadObject(result_reg, Bool::True());
788 __ Bind(&done); 775 __ Bind(&done);
789 } 776 }
790 777
791 778
792 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const { 779 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const {
793 const intptr_t kNumInputs = 2; 780 const intptr_t kNumInputs = 2;
794 const intptr_t kNumTemps = 0; 781 const intptr_t kNumTemps = 0;
795 if (operation_cid() == kMintCid) { 782 if (operation_cid() == kMintCid) {
796 const intptr_t kNumTemps = 2; 783 const intptr_t kNumTemps = 1;
797 LocationSummary* locs = 784 LocationSummary* locs =
798 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 785 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
799 locs->set_in(0, Location::RequiresFpuRegister()); 786 locs->set_in(0, Location::Pair(Location::RequiresRegister(),
800 locs->set_in(1, Location::RequiresFpuRegister()); 787 Location::RequiresRegister()));
788 locs->set_in(1, Location::Pair(Location::RequiresRegister(),
789 Location::RequiresRegister()));
801 locs->set_temp(0, Location::RequiresRegister()); 790 locs->set_temp(0, Location::RequiresRegister());
802 locs->set_temp(1, Location::RequiresRegister());
803 locs->set_out(0, Location::RequiresRegister()); 791 locs->set_out(0, Location::RequiresRegister());
804 return locs; 792 return locs;
805 } 793 }
806 if (operation_cid() == kDoubleCid) { 794 if (operation_cid() == kDoubleCid) {
807 LocationSummary* summary = 795 LocationSummary* summary =
808 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 796 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
809 summary->set_in(0, Location::RequiresFpuRegister()); 797 summary->set_in(0, Location::RequiresFpuRegister());
810 summary->set_in(1, Location::RequiresFpuRegister()); 798 summary->set_in(1, Location::RequiresFpuRegister());
811 summary->set_out(0, Location::RequiresRegister()); 799 summary->set_out(0, Location::RequiresRegister());
812 return summary; 800 return summary;
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
1146 (representation() == kUnboxedInt32x4) || 1134 (representation() == kUnboxedInt32x4) ||
1147 (representation() == kUnboxedFloat64x2)) { 1135 (representation() == kUnboxedFloat64x2)) {
1148 if (class_id() == kTypedDataFloat32ArrayCid) { 1136 if (class_id() == kTypedDataFloat32ArrayCid) {
1149 // Need register <= Q7 for float operations. 1137 // Need register <= Q7 for float operations.
1150 // TODO(fschneider): Add a register policy to specify a subset of 1138 // TODO(fschneider): Add a register policy to specify a subset of
1151 // registers. 1139 // registers.
1152 locs->set_out(0, Location::FpuRegisterLocation(Q7)); 1140 locs->set_out(0, Location::FpuRegisterLocation(Q7));
1153 } else { 1141 } else {
1154 locs->set_out(0, Location::RequiresFpuRegister()); 1142 locs->set_out(0, Location::RequiresFpuRegister());
1155 } 1143 }
1144 } else if (representation() == kUnboxedMint) {
1145 locs->set_out(0, Location::Pair(Location::RequiresRegister(),
1146 Location::RequiresRegister()));
1156 } else { 1147 } else {
1148 ASSERT(representation() == kTagged);
1157 locs->set_out(0, Location::RequiresRegister()); 1149 locs->set_out(0, Location::RequiresRegister());
1158 } 1150 }
1159 return locs; 1151 return locs;
1160 } 1152 }
1161 1153
1162 1154
1163 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1155 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1164 if ((representation() == kUnboxedDouble) || 1156 if ((representation() == kUnboxedDouble) ||
1165 (representation() == kUnboxedMint) ||
1166 (representation() == kUnboxedFloat32x4) || 1157 (representation() == kUnboxedFloat32x4) ||
1167 (representation() == kUnboxedInt32x4) || 1158 (representation() == kUnboxedInt32x4) ||
1168 (representation() == kUnboxedFloat64x2)) { 1159 (representation() == kUnboxedFloat64x2)) {
1169 Register array = locs()->in(0).reg(); 1160 Register array = locs()->in(0).reg();
1170 Register idx = locs()->in(1).reg(); 1161 Register idx = locs()->in(1).reg();
1171 switch (index_scale()) { 1162 switch (index_scale()) {
1172 case 1: 1163 case 1:
1173 __ add(idx, array, ShifterOperand(idx, ASR, kSmiTagSize)); 1164 __ add(idx, array, ShifterOperand(idx, ASR, kSmiTagSize));
1174 break; 1165 break;
1175 case 4: 1166 case 4:
(...skipping 11 matching lines...) Expand all
1187 } 1178 }
1188 if (!IsExternal()) { 1179 if (!IsExternal()) {
1189 ASSERT(this->array()->definition()->representation() == kTagged); 1180 ASSERT(this->array()->definition()->representation() == kTagged);
1190 __ AddImmediate(idx, 1181 __ AddImmediate(idx,
1191 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); 1182 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
1192 } 1183 }
1193 Address element_address(idx); 1184 Address element_address(idx);
1194 const QRegister result = locs()->out(0).fpu_reg(); 1185 const QRegister result = locs()->out(0).fpu_reg();
1195 const DRegister dresult0 = EvenDRegisterOf(result); 1186 const DRegister dresult0 = EvenDRegisterOf(result);
1196 switch (class_id()) { 1187 switch (class_id()) {
1197 case kTypedDataInt32ArrayCid:
1198 __ veorq(result, result, result);
1199 __ ldr(TMP, element_address);
1200 // Re-use the index register so we don't have to require a low-numbered
1201 // Q register.
1202 // Sign-extend into idx.
1203 __ Asr(idx, TMP, 31);
1204 __ vmovdrr(dresult0, TMP, idx);
1205 break;
1206 case kTypedDataUint32ArrayCid:
1207 __ veorq(result, result, result);
1208 __ ldr(TMP, element_address);
1209 // Re-use the index register so we don't have to require a low-numbered
1210 // Q register.
1211 __ LoadImmediate(idx, 0);
1212 __ vmovdrr(dresult0, TMP, idx);
1213 break;
1214 case kTypedDataFloat32ArrayCid: 1188 case kTypedDataFloat32ArrayCid:
1215 // Load single precision float. 1189 // Load single precision float.
1216 // vldrs does not support indexed addressing. 1190 // vldrs does not support indexed addressing.
1217 __ vldrs(EvenSRegisterOf(dresult0), element_address); 1191 __ vldrs(EvenSRegisterOf(dresult0), element_address);
1218 break; 1192 break;
1219 case kTypedDataFloat64ArrayCid: 1193 case kTypedDataFloat64ArrayCid:
1220 // vldrd does not support indexed addressing. 1194 // vldrd does not support indexed addressing.
1221 __ vldrd(dresult0, element_address); 1195 __ vldrd(dresult0, element_address);
1222 break; 1196 break;
1223 case kTypedDataFloat64x2ArrayCid: 1197 case kTypedDataFloat64x2ArrayCid:
1224 case kTypedDataInt32x4ArrayCid: 1198 case kTypedDataInt32x4ArrayCid:
1225 case kTypedDataFloat32x4ArrayCid: 1199 case kTypedDataFloat32x4ArrayCid:
1226 __ vldmd(IA, idx, dresult0, 2); 1200 __ vldmd(IA, idx, dresult0, 2);
1227 break; 1201 break;
1202 default:
1203 UNREACHABLE();
1228 } 1204 }
1229 return; 1205 return;
1230 } 1206 }
1231 1207
1232 Register array = locs()->in(0).reg(); 1208 Register array = locs()->in(0).reg();
1233 Location index = locs()->in(1); 1209 Location index = locs()->in(1);
1234 ASSERT(index.IsRegister()); // TODO(regis): Revisit. 1210 ASSERT(index.IsRegister()); // TODO(regis): Revisit.
1235 Address element_address(kNoRegister, 0); 1211 Address element_address(kNoRegister, 0);
1236 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays 1212 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
1237 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the 1213 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the
(...skipping 22 matching lines...) Expand all
1260 case 4: { 1236 case 4: {
1261 __ add(index.reg(), array, ShifterOperand(index.reg(), LSL, 1)); 1237 __ add(index.reg(), array, ShifterOperand(index.reg(), LSL, 1));
1262 element_address = Address(index.reg(), offset); 1238 element_address = Address(index.reg(), offset);
1263 break; 1239 break;
1264 } 1240 }
1265 // Cases 8 and 16 are only for unboxed values and are handled above. 1241 // Cases 8 and 16 are only for unboxed values and are handled above.
1266 default: 1242 default:
1267 UNREACHABLE(); 1243 UNREACHABLE();
1268 } 1244 }
1269 1245
1246 if (representation() == kUnboxedMint) {
1247 ASSERT(locs()->out(0).IsPairLocation());
1248 PairLocation* result_pair = locs()->out(0).AsPairLocation();
1249 Register result1 = result_pair->At(0).reg();
1250 Register result2 = result_pair->At(1).reg();
1251 switch (class_id()) {
1252 case kTypedDataInt32ArrayCid:
1253 // Load low word.
1254 __ ldr(result1, element_address);
1255 // Sign extend into high word.
1256 __ SignFill(result2, result1);
1257 break;
1258 case kTypedDataUint32ArrayCid:
1259 // Load low word.
1260 __ ldr(result1, element_address);
1261 // Zero high word.
1262 __ eor(result2, result2, ShifterOperand(result2));
1263 break;
1264 default:
1265 UNREACHABLE();
1266 break;
1267 }
1268 return;
1269 }
1270
1271 ASSERT(representation() == kTagged);
1272
1270 Register result = locs()->out(0).reg(); 1273 Register result = locs()->out(0).reg();
1271 switch (class_id()) { 1274 switch (class_id()) {
1272 case kTypedDataInt8ArrayCid: 1275 case kTypedDataInt8ArrayCid:
1273 ASSERT(index_scale() == 1); 1276 ASSERT(index_scale() == 1);
1274 __ ldrsb(result, element_address); 1277 __ ldrsb(result, element_address);
1275 __ SmiTag(result); 1278 __ SmiTag(result);
1276 break; 1279 break;
1277 case kTypedDataUint8ArrayCid: 1280 case kTypedDataUint8ArrayCid:
1278 case kTypedDataUint8ClampedArrayCid: 1281 case kTypedDataUint8ClampedArrayCid:
1279 case kExternalTypedDataUint8ArrayCid: 1282 case kExternalTypedDataUint8ArrayCid:
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1377 case kTypedDataInt8ArrayCid: 1380 case kTypedDataInt8ArrayCid:
1378 case kTypedDataUint8ArrayCid: 1381 case kTypedDataUint8ArrayCid:
1379 case kTypedDataUint8ClampedArrayCid: 1382 case kTypedDataUint8ClampedArrayCid:
1380 case kOneByteStringCid: 1383 case kOneByteStringCid:
1381 case kTypedDataInt16ArrayCid: 1384 case kTypedDataInt16ArrayCid:
1382 case kTypedDataUint16ArrayCid: 1385 case kTypedDataUint16ArrayCid:
1383 locs->set_in(2, Location::WritableRegister()); 1386 locs->set_in(2, Location::WritableRegister());
1384 break; 1387 break;
1385 case kTypedDataInt32ArrayCid: 1388 case kTypedDataInt32ArrayCid:
1386 case kTypedDataUint32ArrayCid: 1389 case kTypedDataUint32ArrayCid:
1387 // Mints are stored in Q registers. For smis, use a writable register 1390 // For smis, use a writable register because the value must be untagged
1388 // because the value must be untagged before storing. 1391 // before storing. Mints are stored in register pairs.
1389 locs->set_in(2, value()->IsSmiValue() 1392 if (value()->IsSmiValue()) {
1390 ? Location::WritableRegister() 1393 locs->set_in(2, Location::WritableRegister());
1391 : Location::FpuRegisterLocation(Q7)); 1394 } else {
1395 // We only move the lower 32-bits so we don't care where the high bits
1396 // are located.
1397 locs->set_in(2, Location::Pair(Location::RequiresRegister(),
1398 Location::Any()));
1399 }
1392 break; 1400 break;
1393 case kTypedDataFloat32ArrayCid: 1401 case kTypedDataFloat32ArrayCid:
1394 // Need low register (<= Q7). 1402 // Need low register (<= Q7).
1395 locs->set_in(2, Location::FpuRegisterLocation(Q7)); 1403 locs->set_in(2, Location::FpuRegisterLocation(Q7));
1396 break; 1404 break;
1397 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. 1405 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants.
1398 case kTypedDataInt32x4ArrayCid: 1406 case kTypedDataInt32x4ArrayCid:
1399 case kTypedDataFloat32x4ArrayCid: 1407 case kTypedDataFloat32x4ArrayCid:
1400 case kTypedDataFloat64x2ArrayCid: 1408 case kTypedDataFloat64x2ArrayCid:
1401 locs->set_in(2, Location::RequiresFpuRegister()); 1409 locs->set_in(2, Location::RequiresFpuRegister());
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1566 } 1574 }
1567 case kTypedDataInt32ArrayCid: 1575 case kTypedDataInt32ArrayCid:
1568 case kTypedDataUint32ArrayCid: { 1576 case kTypedDataUint32ArrayCid: {
1569 if (value()->IsSmiValue()) { 1577 if (value()->IsSmiValue()) {
1570 ASSERT(RequiredInputRepresentation(2) == kTagged); 1578 ASSERT(RequiredInputRepresentation(2) == kTagged);
1571 Register value = locs()->in(2).reg(); 1579 Register value = locs()->in(2).reg();
1572 __ SmiUntag(value); 1580 __ SmiUntag(value);
1573 __ str(value, element_address); 1581 __ str(value, element_address);
1574 } else { 1582 } else {
1575 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); 1583 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint);
1576 QRegister value = locs()->in(2).fpu_reg(); 1584 PairLocation* value_pair = locs()->in(2).AsPairLocation();
1577 ASSERT(value == Q7); 1585 Register value1 = value_pair->At(0).reg();
1578 __ vmovrs(TMP, EvenSRegisterOf(EvenDRegisterOf(value))); 1586 __ str(value1, element_address);
1579 __ str(TMP, element_address);
1580 } 1587 }
1581 break; 1588 break;
1582 } 1589 }
1583 default: 1590 default:
1584 UNREACHABLE(); 1591 UNREACHABLE();
1585 } 1592 }
1586 } 1593 }
1587 1594
1588 1595
1589 LocationSummary* GuardFieldInstr::MakeLocationSummary(bool opt) const { 1596 LocationSummary* GuardFieldInstr::MakeLocationSummary(bool opt) const {
(...skipping 4127 matching lines...) Expand 10 before | Expand all | Expand 10 after
5717 Register length = length_loc.reg(); 5724 Register length = length_loc.reg();
5718 Register index = index_loc.reg(); 5725 Register index = index_loc.reg();
5719 __ cmp(index, ShifterOperand(length)); 5726 __ cmp(index, ShifterOperand(length));
5720 __ b(deopt, CS); 5727 __ b(deopt, CS);
5721 } 5728 }
5722 } 5729 }
5723 5730
5724 5731
5725 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, 5732 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
5726 Label* overflow, 5733 Label* overflow,
5727 QRegister result, 5734 Register result_lo,
5728 Register tmp_hi, Register tmp_lo) { 5735 Register result_hi) {
5729 __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(result));
5730 // Compare upper half. 5736 // Compare upper half.
5731 Label check_lower; 5737 Label check_lower;
5732 __ CompareImmediate(tmp_hi, 0x00200000); 5738 __ CompareImmediate(result_hi, 0x00200000);
5733 __ b(overflow, GT); 5739 __ b(overflow, GT);
5734 __ b(&check_lower, NE); 5740 __ b(&check_lower, NE);
5735 5741
5736 __ CompareImmediate(tmp_lo, 0); 5742 __ CompareImmediate(result_lo, 0);
5737 __ b(overflow, HI); 5743 __ b(overflow, HI);
5738 5744
5739 __ Bind(&check_lower); 5745 __ Bind(&check_lower);
5740 __ CompareImmediate(tmp_hi, -0x00200000); 5746 __ CompareImmediate(result_hi, -0x00200000);
5741 __ b(overflow, LT); 5747 __ b(overflow, LT);
5742 // Anything in the lower part would make the number bigger than the lower 5748 // Anything in the lower part would make the number bigger than the lower
5743 // bound, so we are done. 5749 // bound, so we are done.
5744 } 5750 }
5745 5751
5746 5752
5747 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { 5753 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
5748 const intptr_t kNumInputs = 1; 5754 const intptr_t kNumInputs = 1;
5749 const intptr_t value_cid = value()->Type()->ToCid(); 5755 const intptr_t kNumTemps = 1;
5750 const bool needs_writable_input = (value_cid != kMintCid);
5751 const bool needs_temp = (value_cid != kMintCid);
5752 const intptr_t kNumTemps = needs_temp ? 1 : 0;
5753 LocationSummary* summary = 5756 LocationSummary* summary =
5754 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5757 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5755 summary->set_in(0, needs_writable_input 5758 summary->set_in(0, Location::RequiresRegister());
5756 ? Location::WritableRegister() 5759 summary->set_temp(0, Location::RequiresRegister());
5757 : Location::RequiresRegister()); 5760 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5758 if (needs_temp) { 5761 Location::RequiresRegister()));
5759 summary->set_temp(0, Location::RequiresRegister());
5760 }
5761 summary->set_out(0, Location::RequiresFpuRegister());
5762 return summary; 5762 return summary;
5763 } 5763 }
5764 5764
5765 5765
5766 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5766 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5767 const intptr_t value_cid = value()->Type()->ToCid(); 5767 const intptr_t value_cid = value()->Type()->ToCid();
5768 const Register value = locs()->in(0).reg(); 5768 const Register value = locs()->in(0).reg();
5769 const QRegister result = locs()->out(0).fpu_reg(); 5769 PairLocation* result_pair = locs()->out(0).AsPairLocation();
5770 Register result_lo = result_pair->At(0).reg();
5771 Register result_hi = result_pair->At(1).reg();
5772 ASSERT(value != result_lo);
5773 ASSERT(value != result_hi);
5770 5774
5771 __ Comment("UnboxIntegerInstr"); 5775 __ Comment("UnboxIntegerInstr");
5772 __ veorq(result, result, result);
5773 if (value_cid == kMintCid) { 5776 if (value_cid == kMintCid) {
5774 __ LoadDFromOffset(EvenDRegisterOf(result), value, 5777 // Load low word.
5775 Mint::value_offset() - kHeapObjectTag); 5778 __ LoadFromOffset(kWord,
5779 result_lo,
5780 value,
5781 Mint::value_offset() - kHeapObjectTag);
5782 // Load high word.
5783 __ LoadFromOffset(kWord,
5784 result_hi,
5785 value,
5786 Mint::value_offset() - kHeapObjectTag + kWordSize);
5776 } else if (value_cid == kSmiCid) { 5787 } else if (value_cid == kSmiCid) {
5777 Register temp = locs()->temp(0).reg(); 5788 // Load Smi into result_lo.
5778 __ SmiUntag(value); 5789 __ mov(result_lo, ShifterOperand(value));
5779 // Sign extend value into temp. 5790 // Untag.
5780 __ Asr(temp, value, 31); 5791 __ SmiUntag(result_lo);
5781 __ vmovdrr(EvenDRegisterOf(result), value, temp); 5792 __ SignFill(result_hi, result_lo);
5782 } else { 5793 } else {
5783 Register temp = locs()->temp(0).reg(); 5794 Register temp = locs()->temp(0).reg();
5784 Label* deopt = compiler->AddDeoptStub(deopt_id_, 5795 Label* deopt = compiler->AddDeoptStub(deopt_id_,
5785 ICData::kDeoptUnboxInteger); 5796 ICData::kDeoptUnboxInteger);
5786 Label is_smi, done; 5797 Label is_smi, done;
5787 __ tst(value, ShifterOperand(kSmiTagMask)); 5798 __ tst(value, ShifterOperand(kSmiTagMask));
5788 __ b(&is_smi, EQ); 5799 __ b(&is_smi, EQ);
5789 __ CompareClassId(value, kMintCid, temp); 5800 __ CompareClassId(value, kMintCid, temp);
5790 __ b(deopt, NE); 5801 __ b(deopt, NE);
5791 5802
5792 // It's a Mint. 5803 // It's a Mint.
5793 __ LoadDFromOffset(EvenDRegisterOf(result), value, 5804 // Load low word.
5794 Mint::value_offset() - kHeapObjectTag); 5805 __ LoadFromOffset(kWord,
5806 result_lo,
5807 value,
5808 Mint::value_offset() - kHeapObjectTag);
5809 // Load high word.
5810 __ LoadFromOffset(kWord,
5811 result_hi,
5812 value,
5813 Mint::value_offset() - kHeapObjectTag + kWordSize);
5795 __ b(&done); 5814 __ b(&done);
5796 5815
5797 // It's a Smi. 5816 // It's a Smi.
5798 __ Bind(&is_smi); 5817 __ Bind(&is_smi);
5799 __ SmiUntag(value); 5818 // Load Smi into result_lo.
5800 // Sign extend into temp. 5819 __ mov(result_lo, ShifterOperand(value));
5801 __ Asr(temp, value, 31); 5820 // Untag.
5802 __ vmovdrr(EvenDRegisterOf(result), value, temp); 5821 __ SmiUntag(result_lo);
5822 // Sign extend result_lo into result_hi.
5823 __ SignFill(result_hi, result_lo);
5803 __ Bind(&done); 5824 __ Bind(&done);
5804 } 5825 }
5805 } 5826 }
5806 5827
5807 5828
5808 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { 5829 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
5809 const intptr_t kNumInputs = 1; 5830 const intptr_t kNumInputs = 1;
5810 const intptr_t kNumTemps = 2; 5831 const intptr_t kNumTemps = 1;
5811 LocationSummary* summary = 5832 LocationSummary* summary =
5812 new LocationSummary(kNumInputs, 5833 new LocationSummary(kNumInputs,
5813 kNumTemps, 5834 kNumTemps,
5814 LocationSummary::kCallOnSlowPath); 5835 LocationSummary::kCallOnSlowPath);
5815 summary->set_in(0, Location::RequiresFpuRegister()); 5836 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5837 Location::RequiresRegister()));
5816 summary->set_temp(0, Location::RequiresRegister()); 5838 summary->set_temp(0, Location::RequiresRegister());
5817 summary->set_temp(1, Location::RequiresRegister());
5818 summary->set_out(0, Location::RequiresRegister()); 5839 summary->set_out(0, Location::RequiresRegister());
5819 return summary; 5840 return summary;
5820 } 5841 }
5821 5842
5822 5843
5823 class BoxIntegerSlowPath : public SlowPathCode { 5844 class BoxIntegerSlowPath : public SlowPathCode {
5824 public: 5845 public:
5825 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) 5846 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction)
5826 : instruction_(instruction) { } 5847 : instruction_(instruction) { }
5827 5848
(...skipping 21 matching lines...) Expand all
5849 } 5870 }
5850 5871
5851 private: 5872 private:
5852 BoxIntegerInstr* instruction_; 5873 BoxIntegerInstr* instruction_;
5853 }; 5874 };
5854 5875
5855 5876
5856 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5877 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5857 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); 5878 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
5858 compiler->AddSlowPathCode(slow_path); 5879 compiler->AddSlowPathCode(slow_path);
5859 5880 PairLocation* value_pair = locs()->in(0).AsPairLocation();
5881 Register value_lo = value_pair->At(0).reg();
5882 Register value_hi = value_pair->At(1).reg();
5883 Register tmp = locs()->temp(0).reg();
5860 Register out_reg = locs()->out(0).reg(); 5884 Register out_reg = locs()->out(0).reg();
5861 QRegister value = locs()->in(0).fpu_reg();
5862 DRegister dvalue0 = EvenDRegisterOf(value);
5863 Register lo = locs()->temp(0).reg();
5864 Register hi = locs()->temp(1).reg();
5865 5885
5866 // Unboxed operations produce smis or mint-sized values. 5886 // Unboxed operations produce smis or mint-sized values.
5867 // Check if value fits into a smi. 5887 // Check if value fits into a smi.
5868 __ Comment("BoxIntegerInstr"); 5888 __ Comment("BoxIntegerInstr");
5869 Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi; 5889 Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi;
5870 __ vmovrrd(lo, hi, dvalue0); 5890 // Check high word.
5871 __ CompareImmediate(hi, 0); 5891 __ CompareImmediate(value_hi, 0);
5872 __ b(&maybe_pos_smi, EQ); 5892 __ b(&maybe_pos_smi, EQ);
5873 5893
5874 __ CompareImmediate(hi, -1); 5894 __ CompareImmediate(value_hi, -1);
5875 __ b(&maybe_neg_smi, EQ); 5895 __ b(&maybe_neg_smi, EQ);
5876 __ b(&not_smi); 5896 __ b(&not_smi);
5877 5897
5878 __ Bind(&maybe_pos_smi); 5898 __ Bind(&maybe_pos_smi);
5879 __ CompareImmediate(lo, kSmiMax); 5899 __ CompareImmediate(value_lo, kSmiMax);
5880 __ b(&is_smi, LS); // unsigned lower or same. 5900 __ b(&is_smi, LS); // unsigned lower or same.
5881 __ b(&not_smi); 5901 __ b(&not_smi);
5882 5902
5883 __ Bind(&maybe_neg_smi); 5903 __ Bind(&maybe_neg_smi);
5884 __ CompareImmediate(lo, 0); 5904 __ CompareImmediate(value_lo, 0);
5885 __ b(&not_smi, GE); 5905 __ b(&not_smi, GE);
5886 __ CompareImmediate(lo, kSmiMin); 5906 __ CompareImmediate(value_lo, kSmiMin);
5887 __ b(&not_smi, LT); 5907 __ b(&not_smi, LT);
5888 5908
5889 // lo is a Smi. Tag it and return. 5909 // lo is a Smi. Tag it and return.
5890 __ Bind(&is_smi); 5910 __ Bind(&is_smi);
5891 __ SmiTag(lo); 5911 __ mov(out_reg, ShifterOperand(value_lo));
5892 __ mov(out_reg, ShifterOperand(lo)); 5912 __ SmiTag(out_reg);
5893 __ b(&done); 5913 __ b(&done);
5894 5914
5895 // Not a smi. Box it. 5915 // Not a smi. Box it.
5896 __ Bind(&not_smi); 5916 __ Bind(&not_smi);
5897 __ TryAllocate( 5917 __ TryAllocate(
5898 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), 5918 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
5899 slow_path->entry_label(), 5919 slow_path->entry_label(),
5900 out_reg, 5920 out_reg,
5901 lo); 5921 tmp);
5902 __ Bind(slow_path->exit_label()); 5922 __ Bind(slow_path->exit_label());
5903 __ StoreDToOffset(dvalue0, out_reg, Mint::value_offset() - kHeapObjectTag); 5923 __ StoreToOffset(kWord,
5924 value_lo,
5925 out_reg,
5926 Mint::value_offset() - kHeapObjectTag);
5927 __ StoreToOffset(kWord,
5928 value_hi,
5929 out_reg,
5930 Mint::value_offset() - kHeapObjectTag + kWordSize);
5904 __ Bind(&done); 5931 __ Bind(&done);
5905 } 5932 }
5906 5933
5907 5934
5908 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { 5935 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
5909 const intptr_t kNumInputs = 2; 5936 const intptr_t kNumInputs = 2;
5910 const intptr_t kNumTemps = 5937 const intptr_t kNumTemps = 0;
5911 FLAG_throw_on_javascript_int_overflow ? 2 : 0;
5912 LocationSummary* summary = 5938 LocationSummary* summary =
5913 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5939 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5914 summary->set_in(0, Location::RequiresFpuRegister()); 5940 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5915 summary->set_in(1, Location::RequiresFpuRegister()); 5941 Location::RequiresRegister()));
5916 if (FLAG_throw_on_javascript_int_overflow) { 5942 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
5917 summary->set_temp(0, Location::RequiresRegister()); 5943 Location::RequiresRegister()));
5918 summary->set_temp(1, Location::RequiresRegister()); 5944 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5919 } 5945 Location::RequiresRegister()));
5920 if ((op_kind() == Token::kADD) || (op_kind() == Token::kSUB)) {
5921 // Need another temp for checking for overflow.
5922 summary->AddTemp(Location::RequiresFpuRegister());
5923 summary->AddTemp(Location::FpuRegisterLocation(Q7));
5924 }
5925 summary->set_out(0, Location::RequiresFpuRegister());
5926 return summary; 5946 return summary;
5927 } 5947 }
5928 5948
5929 5949
5930 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5950 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5931 QRegister left = locs()->in(0).fpu_reg(); 5951 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5932 QRegister right = locs()->in(1).fpu_reg(); 5952 Register left_lo = left_pair->At(0).reg();
5933 QRegister out = locs()->out(0).fpu_reg(); 5953 Register left_hi = left_pair->At(1).reg();
5954 PairLocation* right_pair = locs()->in(1).AsPairLocation();
5955 Register right_lo = right_pair->At(0).reg();
5956 Register right_hi = right_pair->At(1).reg();
5957 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5958 Register out_lo = out_pair->At(0).reg();
5959 Register out_hi = out_pair->At(1).reg();
5934 5960
5935 Label* deopt = NULL; 5961 Label* deopt = NULL;
5936 if (FLAG_throw_on_javascript_int_overflow) { 5962 if (FLAG_throw_on_javascript_int_overflow) {
5937 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5963 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5938 } 5964 }
5939 switch (op_kind()) { 5965 switch (op_kind()) {
5940 case Token::kBIT_AND: __ vandq(out, left, right); break; 5966 case Token::kBIT_AND: {
5941 case Token::kBIT_OR: __ vorrq(out, left, right); break; 5967 __ and_(out_lo, left_lo, ShifterOperand(right_lo));
5942 case Token::kBIT_XOR: __ veorq(out, left, right); break; 5968 __ and_(out_hi, left_hi, ShifterOperand(right_hi));
5969 }
5970 break;
5971 case Token::kBIT_OR: {
5972 __ orr(out_lo, left_lo, ShifterOperand(right_lo));
5973 __ orr(out_hi, left_hi, ShifterOperand(right_hi));
5974 }
5975 break;
5976 case Token::kBIT_XOR: {
5977 __ eor(out_lo, left_lo, ShifterOperand(right_lo));
5978 __ eor(out_hi, left_hi, ShifterOperand(right_hi));
5979 }
5980 break;
5943 case Token::kADD: 5981 case Token::kADD:
5944 case Token::kSUB: { 5982 case Token::kSUB: {
5945 const intptr_t tmpidx = FLAG_throw_on_javascript_int_overflow ? 2 : 0;
5946 QRegister tmp = locs()->temp(tmpidx).fpu_reg();
5947 QRegister ro = locs()->temp(tmpidx + 1).fpu_reg();
5948 ASSERT(ro == Q7);
5949 if (!FLAG_throw_on_javascript_int_overflow) { 5983 if (!FLAG_throw_on_javascript_int_overflow) {
5950 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5984 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5951 } 5985 }
5952 if (op_kind() == Token::kADD) { 5986 if (op_kind() == Token::kADD) {
5953 __ vaddqi(kWordPair, out, left, right); 5987 __ adds(out_lo, left_lo, ShifterOperand(right_lo));
5988 __ adcs(out_hi, left_hi, ShifterOperand(right_hi));
5954 } else { 5989 } else {
5955 ASSERT(op_kind() == Token::kSUB); 5990 ASSERT(op_kind() == Token::kSUB);
5956 __ vsubqi(kWordPair, out, left, right); 5991 __ subs(out_lo, left_lo, ShifterOperand(right_lo));
5992 __ sbcs(out_hi, left_hi, ShifterOperand(right_hi));
5957 } 5993 }
5958 __ veorq(ro, out, left); 5994 // Deopt on overflow.
5959 __ veorq(tmp, left, right); 5995 __ b(deopt, VS);
5960 __ vandq(ro, tmp, ro);
5961 __ vmovrs(TMP, OddSRegisterOf(EvenDRegisterOf(ro)));
5962 // If TMP < 0, there was overflow.
5963 __ cmp(TMP, ShifterOperand(0));
5964 __ b(deopt, LT);
5965 break; 5996 break;
5966 } 5997 }
5967 default: UNREACHABLE(); break; 5998 default:
5999 UNREACHABLE();
6000 break;
5968 } 6001 }
5969 if (FLAG_throw_on_javascript_int_overflow) { 6002 if (FLAG_throw_on_javascript_int_overflow) {
5970 Register tmp1 = locs()->temp(0).reg(); 6003 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
5971 Register tmp2 = locs()->temp(1).reg();
5972 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
5973 } 6004 }
5974 } 6005 }
5975 6006
5976 6007
5977 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { 6008 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
5978 const intptr_t kNumInputs = 2; 6009 const intptr_t kNumInputs = 2;
5979 const intptr_t kNumTemps = 6010 const intptr_t kNumTemps = 1;
5980 FLAG_throw_on_javascript_int_overflow ? 2 : 1;
5981 LocationSummary* summary = 6011 LocationSummary* summary =
5982 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 6012 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5983 summary->set_in(0, Location::RequiresFpuRegister()); 6013 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
6014 Location::RequiresRegister()));
5984 summary->set_in(1, Location::WritableRegister()); 6015 summary->set_in(1, Location::WritableRegister());
5985 summary->set_temp(0, Location::FpuRegisterLocation(Q7)); 6016 summary->set_temp(0, Location::RequiresRegister());
5986 if (FLAG_throw_on_javascript_int_overflow) { 6017 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5987 summary->set_temp(1, Location::RequiresRegister()); 6018 Location::RequiresRegister()));
5988 }
5989 summary->set_out(0, Location::RequiresFpuRegister());
5990 return summary; 6019 return summary;
5991 } 6020 }
5992 6021
5993 6022
5994 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6023 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5995 QRegister value = locs()->in(0).fpu_reg(); 6024 PairLocation* left_pair = locs()->in(0).AsPairLocation();
6025 Register left_lo = left_pair->At(0).reg();
6026 Register left_hi = left_pair->At(1).reg();
5996 Register shift = locs()->in(1).reg(); 6027 Register shift = locs()->in(1).reg();
5997 QRegister temp = locs()->temp(0).fpu_reg(); 6028 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5998 ASSERT(temp == Q7); 6029 Register out_lo = out_pair->At(0).reg();
5999 QRegister out = locs()->out(0).fpu_reg(); 6030 Register out_hi = out_pair->At(1).reg();
6000 DRegister dtemp0 = EvenDRegisterOf(temp); 6031 Register temp = locs()->temp(0).reg();
6001 SRegister stemp0 = EvenSRegisterOf(dtemp0);
6002 SRegister stemp1 = OddSRegisterOf(dtemp0);
6003 6032
6004 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); 6033 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
6005 Label done; 6034 Label done;
6006 6035
6036 // Early out if shift is 0.
6007 __ CompareImmediate(shift, 0); 6037 __ CompareImmediate(shift, 0);
6008 __ vmovq(out, value); 6038 __ mov(out_lo, ShifterOperand(left_lo));
6039 __ mov(out_hi, ShifterOperand(left_hi));
6009 __ b(&done, EQ); 6040 __ b(&done, EQ);
6041
6042 // Untag shift count.
6010 __ SmiUntag(shift); 6043 __ SmiUntag(shift);
6011 6044
6012 // vshlq takes the shift value from low byte. Deopt if shift is 6045 // Deopt if shift is negative.
6013 // outside of [0, 63]. 6046 __ CompareImmediate(shift, 1);
6047 __ b(deopt, LT);
6048
6049 // Deopt if shift is larger than 63.
6014 __ CompareImmediate(shift, 63); 6050 __ CompareImmediate(shift, 63);
6015 __ b(deopt, GT); 6051 __ b(deopt, GT);
6016 __ CompareImmediate(shift, 0);
6017 __ b(deopt, LT);
6018 6052
6019 __ veorq(temp, temp, temp); // Zero out temp.
6020 switch (op_kind()) { 6053 switch (op_kind()) {
6021 case Token::kSHR: { 6054 case Token::kSHR: {
6022 __ rsb(shift, shift, ShifterOperand(0)); // Negate shift. 6055 __ cmp(shift, ShifterOperand(32));
6023 __ vmovsr(stemp0, shift); // Move the shift into the low S register. 6056
6024 __ vshlqi(kWordPair, out, value, temp); 6057 __ mov(out_lo, ShifterOperand(out_hi), HI);
6058 __ Asr(out_hi, out_hi, 31, HI);
6059 __ sub(shift, shift, ShifterOperand(32), HI);
6060
6061 __ rsb(temp, shift, ShifterOperand(32));
6062 __ mov(temp, ShifterOperand(out_hi, LSL, temp));
6063 __ orr(out_lo, temp, ShifterOperand(out_lo, LSR, shift));
6064 __ Asr(out_hi, out_hi, shift);
6025 break; 6065 break;
6026 } 6066 }
6027 case Token::kSHL: { 6067 case Token::kSHL: {
6028 __ vmovsr(stemp0, shift); // Move the shift into the low S register. 6068 __ rsbs(temp, shift, ShifterOperand(32));
6029 __ vshlqu(kWordPair, out, value, temp); 6069 __ sub(temp, shift, ShifterOperand(32), MI);
6070 __ mov(out_hi, ShifterOperand(out_lo, LSL, temp), MI);
6071 __ mov(out_hi, ShifterOperand(out_hi, LSL, shift), PL);
6072 __ orr(out_hi, out_hi, ShifterOperand(out_lo, LSR, temp), PL);
6073 __ mov(out_lo, ShifterOperand(out_lo, LSL, shift));
6030 6074
6031 // check for overflow by shifting back and comparing. 6075 // Check for overflow.
6032 __ rsb(shift, shift, ShifterOperand(0)); 6076
6033 __ vmovsr(stemp0, shift); 6077 // Copy high word from output.
6034 __ vshlqi(kWordPair, temp, out, temp); 6078 __ mov(temp, ShifterOperand(out_hi));
6035 __ vceqqi(kWord, temp, temp, value); 6079 // Shift copy right.
6036 // Low 64 bits of temp should be all 1's, otherwise temp != value and 6080 __ Asr(temp, temp, shift);
6037 // we deopt. 6081 // Compare with high word from input.
6038 __ vmovrs(shift, stemp0); 6082 __ cmp(temp, ShifterOperand(left_hi));
6039 __ CompareImmediate(shift, -1); 6083 // Overflow if they aren't equal.
6040 __ b(deopt, NE);
6041 __ vmovrs(shift, stemp1);
6042 __ CompareImmediate(shift, -1);
6043 __ b(deopt, NE); 6084 __ b(deopt, NE);
6044 break; 6085 break;
6045 } 6086 }
6046 default: 6087 default:
6047 UNREACHABLE(); 6088 UNREACHABLE();
6048 break; 6089 break;
6049 } 6090 }
6050 6091
6051 __ Bind(&done); 6092 __ Bind(&done);
6052 if (FLAG_throw_on_javascript_int_overflow) { 6093 if (FLAG_throw_on_javascript_int_overflow) {
6053 Register tmp1 = locs()->in(1).reg(); 6094 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
6054 Register tmp2 = locs()->temp(1).reg();
6055 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
6056 } 6095 }
6057 } 6096 }
6058 6097
6059 6098
6060 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { 6099 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
6061 const intptr_t kNumInputs = 1; 6100 const intptr_t kNumInputs = 1;
6062 const intptr_t kNumTemps = 6101 const intptr_t kNumTemps = 0;
6063 FLAG_throw_on_javascript_int_overflow ? 2 : 0;
6064 LocationSummary* summary = 6102 LocationSummary* summary =
6065 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 6103 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
6066 summary->set_in(0, Location::RequiresFpuRegister()); 6104 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
6067 summary->set_out(0, Location::RequiresFpuRegister()); 6105 Location::RequiresRegister()));
6068 if (FLAG_throw_on_javascript_int_overflow) { 6106 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
6069 summary->set_temp(0, Location::RequiresRegister()); 6107 Location::RequiresRegister()));
6070 summary->set_temp(1, Location::RequiresRegister());
6071 }
6072 return summary; 6108 return summary;
6073 } 6109 }
6074 6110
6075 6111
6076 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6112 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6077 ASSERT(op_kind() == Token::kBIT_NOT); 6113 ASSERT(op_kind() == Token::kBIT_NOT);
6078 QRegister value = locs()->in(0).fpu_reg(); 6114
6079 QRegister out = locs()->out(0).fpu_reg(); 6115 PairLocation* left_pair = locs()->in(0).AsPairLocation();
6116 Register left_lo = left_pair->At(0).reg();
6117 Register left_hi = left_pair->At(1).reg();
6118
6119 PairLocation* out_pair = locs()->out(0).AsPairLocation();
6120 Register out_lo = out_pair->At(0).reg();
6121 Register out_hi = out_pair->At(1).reg();
6122
6080 Label* deopt = NULL; 6123 Label* deopt = NULL;
6124
6081 if (FLAG_throw_on_javascript_int_overflow) { 6125 if (FLAG_throw_on_javascript_int_overflow) {
6082 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); 6126 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
6083 } 6127 }
6084 __ vmvnq(out, value); 6128 __ mvn(out_lo, ShifterOperand(left_lo));
6129 __ mvn(out_hi, ShifterOperand(left_hi));
6085 if (FLAG_throw_on_javascript_int_overflow) { 6130 if (FLAG_throw_on_javascript_int_overflow) {
6086 Register tmp1 = locs()->temp(0).reg(); 6131 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
6087 Register tmp2 = locs()->temp(1).reg();
6088 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
6089 } 6132 }
6090 } 6133 }
6091 6134
6092 6135
6093 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { 6136 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const {
6094 return new LocationSummary(0, 0, LocationSummary::kCall); 6137 return new LocationSummary(0, 0, LocationSummary::kCall);
6095 } 6138 }
6096 6139
6097 6140
6098 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6141 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
6288 compiler->GenerateCall(token_pos(), 6331 compiler->GenerateCall(token_pos(),
6289 &label, 6332 &label,
6290 PcDescriptors::kOther, 6333 PcDescriptors::kOther,
6291 locs()); 6334 locs());
6292 __ Drop(ArgumentCount()); // Discard arguments. 6335 __ Drop(ArgumentCount()); // Discard arguments.
6293 } 6336 }
6294 6337
6295 } // namespace dart 6338 } // namespace dart
6296 6339
6297 #endif // defined TARGET_ARCH_ARM 6340 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698