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

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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1269 } 1245 }
1270 case 16: { 1246 case 16: {
1271 __ add(index.reg(), array, ShifterOperand(index.reg(), LSL, 3)); 1247 __ add(index.reg(), array, ShifterOperand(index.reg(), LSL, 3));
1272 element_address = Address(index.reg(), offset); 1248 element_address = Address(index.reg(), offset);
1273 break; 1249 break;
1274 } 1250 }
1275 default: 1251 default:
1276 UNREACHABLE(); 1252 UNREACHABLE();
1277 } 1253 }
1278 1254
1255 if (representation() == kUnboxedMint) {
1256 ASSERT(locs()->out(0).IsPairLocation());
1257 PairLocation* result_pair = locs()->out(0).AsPairLocation();
1258 Register result1 = result_pair->At(0).reg();
1259 Register result2 = result_pair->At(1).reg();
1260 switch (class_id()) {
1261 case kTypedDataInt32ArrayCid:
1262 // Load low word.
1263 __ ldr(result1, element_address);
1264 // Sign extend into high word.
1265 __ SignFill(result2, result1);
1266 break;
1267 case kTypedDataUint32ArrayCid:
1268 // Load low word.
1269 __ ldr(result1, element_address);
1270 // Zero high word.
1271 __ eor(result2, result2, ShifterOperand(result2));
1272 break;
1273 default:
1274 UNREACHABLE();
1275 break;
1276 }
1277 return;
1278 }
1279
1280 ASSERT(representation() == kTagged);
1281
1279 Register result = locs()->out(0).reg(); 1282 Register result = locs()->out(0).reg();
1280 switch (class_id()) { 1283 switch (class_id()) {
1281 case kTypedDataInt8ArrayCid: 1284 case kTypedDataInt8ArrayCid:
1282 ASSERT(index_scale() == 1); 1285 ASSERT(index_scale() == 1);
1283 __ ldrsb(result, element_address); 1286 __ ldrsb(result, element_address);
1284 __ SmiTag(result); 1287 __ SmiTag(result);
1285 break; 1288 break;
1286 case kTypedDataUint8ArrayCid: 1289 case kTypedDataUint8ArrayCid:
1287 case kTypedDataUint8ClampedArrayCid: 1290 case kTypedDataUint8ClampedArrayCid:
1288 case kExternalTypedDataUint8ArrayCid: 1291 case kExternalTypedDataUint8ArrayCid:
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1386 case kTypedDataInt8ArrayCid: 1389 case kTypedDataInt8ArrayCid:
1387 case kTypedDataUint8ArrayCid: 1390 case kTypedDataUint8ArrayCid:
1388 case kTypedDataUint8ClampedArrayCid: 1391 case kTypedDataUint8ClampedArrayCid:
1389 case kOneByteStringCid: 1392 case kOneByteStringCid:
1390 case kTypedDataInt16ArrayCid: 1393 case kTypedDataInt16ArrayCid:
1391 case kTypedDataUint16ArrayCid: 1394 case kTypedDataUint16ArrayCid:
1392 locs->set_in(2, Location::WritableRegister()); 1395 locs->set_in(2, Location::WritableRegister());
1393 break; 1396 break;
1394 case kTypedDataInt32ArrayCid: 1397 case kTypedDataInt32ArrayCid:
1395 case kTypedDataUint32ArrayCid: 1398 case kTypedDataUint32ArrayCid:
1396 // Mints are stored in Q registers. For smis, use a writable register 1399 // For smis, use a writable register because the value must be untagged
1397 // because the value must be untagged before storing. 1400 // before storing. Mints are stored in register pairs.
1398 locs->set_in(2, value()->IsSmiValue() 1401 if (value()->IsSmiValue()) {
1399 ? Location::WritableRegister() 1402 locs->set_in(2, Location::WritableRegister());
1400 : Location::FpuRegisterLocation(Q7)); 1403 } else {
1404 // We only move the lower 32-bits so we don't care where the high bits
1405 // are located.
1406 locs->set_in(2, Location::Pair(Location::RequiresRegister(),
1407 Location::Any()));
1408 }
1401 break; 1409 break;
1402 case kTypedDataFloat32ArrayCid: 1410 case kTypedDataFloat32ArrayCid:
1403 // Need low register (<= Q7). 1411 // Need low register (<= Q7).
1404 locs->set_in(2, Location::FpuRegisterLocation(Q7)); 1412 locs->set_in(2, Location::FpuRegisterLocation(Q7));
1405 break; 1413 break;
1406 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. 1414 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants.
1407 case kTypedDataInt32x4ArrayCid: 1415 case kTypedDataInt32x4ArrayCid:
1408 case kTypedDataFloat32x4ArrayCid: 1416 case kTypedDataFloat32x4ArrayCid:
1409 case kTypedDataFloat64x2ArrayCid: 1417 case kTypedDataFloat64x2ArrayCid:
1410 locs->set_in(2, Location::RequiresFpuRegister()); 1418 locs->set_in(2, Location::RequiresFpuRegister());
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1521 } 1529 }
1522 case kTypedDataInt32ArrayCid: 1530 case kTypedDataInt32ArrayCid:
1523 case kTypedDataUint32ArrayCid: { 1531 case kTypedDataUint32ArrayCid: {
1524 if (value()->IsSmiValue()) { 1532 if (value()->IsSmiValue()) {
1525 ASSERT(RequiredInputRepresentation(2) == kTagged); 1533 ASSERT(RequiredInputRepresentation(2) == kTagged);
1526 Register value = locs()->in(2).reg(); 1534 Register value = locs()->in(2).reg();
1527 __ SmiUntag(value); 1535 __ SmiUntag(value);
1528 __ str(value, element_address); 1536 __ str(value, element_address);
1529 } else { 1537 } else {
1530 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); 1538 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint);
1531 QRegister value = locs()->in(2).fpu_reg(); 1539 PairLocation* value_pair = locs()->in(2).AsPairLocation();
1532 ASSERT(value == Q7); 1540 Register value1 = value_pair->At(0).reg();
1533 __ vmovrs(TMP, EvenSRegisterOf(EvenDRegisterOf(value))); 1541 __ str(value1, element_address);
1534 __ str(TMP, element_address);
1535 } 1542 }
1536 break; 1543 break;
1537 } 1544 }
1538 case kTypedDataFloat32ArrayCid: { 1545 case kTypedDataFloat32ArrayCid: {
1539 SRegister value = 1546 SRegister value =
1540 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg())); 1547 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg()));
1541 __ add(index.reg(), index.reg(), ShifterOperand(array)); 1548 __ add(index.reg(), index.reg(), ShifterOperand(array));
1542 __ StoreSToOffset(value, index.reg(), 0); 1549 __ StoreSToOffset(value, index.reg(), 0);
1543 break; 1550 break;
1544 } 1551 }
(...skipping 4149 matching lines...) Expand 10 before | Expand all | Expand 10 after
5694 Register length = length_loc.reg(); 5701 Register length = length_loc.reg();
5695 Register index = index_loc.reg(); 5702 Register index = index_loc.reg();
5696 __ cmp(index, ShifterOperand(length)); 5703 __ cmp(index, ShifterOperand(length));
5697 __ b(deopt, CS); 5704 __ b(deopt, CS);
5698 } 5705 }
5699 } 5706 }
5700 5707
5701 5708
5702 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, 5709 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
5703 Label* overflow, 5710 Label* overflow,
5704 QRegister result, 5711 Register result_lo,
5705 Register tmp_hi, Register tmp_lo) { 5712 Register result_hi) {
5706 __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(result));
5707 // Compare upper half. 5713 // Compare upper half.
5708 Label check_lower; 5714 Label check_lower;
5709 __ CompareImmediate(tmp_hi, 0x00200000); 5715 __ CompareImmediate(result_hi, 0x00200000);
5710 __ b(overflow, GT); 5716 __ b(overflow, GT);
5711 __ b(&check_lower, NE); 5717 __ b(&check_lower, NE);
5712 5718
5713 __ CompareImmediate(tmp_lo, 0); 5719 __ CompareImmediate(result_lo, 0);
5714 __ b(overflow, HI); 5720 __ b(overflow, HI);
5715 5721
5716 __ Bind(&check_lower); 5722 __ Bind(&check_lower);
5717 __ CompareImmediate(tmp_hi, -0x00200000); 5723 __ CompareImmediate(result_hi, -0x00200000);
5718 __ b(overflow, LT); 5724 __ b(overflow, LT);
5719 // Anything in the lower part would make the number bigger than the lower 5725 // Anything in the lower part would make the number bigger than the lower
5720 // bound, so we are done. 5726 // bound, so we are done.
5721 } 5727 }
5722 5728
5723 5729
5724 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { 5730 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
5725 const intptr_t kNumInputs = 1; 5731 const intptr_t kNumInputs = 1;
5726 const intptr_t value_cid = value()->Type()->ToCid(); 5732 const intptr_t kNumTemps = 1;
5727 const bool needs_writable_input = (value_cid != kMintCid);
5728 const bool needs_temp = (value_cid != kMintCid);
5729 const intptr_t kNumTemps = needs_temp ? 1 : 0;
5730 LocationSummary* summary = 5733 LocationSummary* summary =
5731 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5734 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5732 summary->set_in(0, needs_writable_input 5735 summary->set_in(0, Location::RequiresRegister());
5733 ? Location::WritableRegister() 5736 summary->set_temp(0, Location::RequiresRegister());
5734 : Location::RequiresRegister()); 5737 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5735 if (needs_temp) { 5738 Location::RequiresRegister()));
5736 summary->set_temp(0, Location::RequiresRegister());
5737 }
5738 summary->set_out(0, Location::RequiresFpuRegister());
5739 return summary; 5739 return summary;
5740 } 5740 }
5741 5741
5742 5742
5743 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5743 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5744 const intptr_t value_cid = value()->Type()->ToCid(); 5744 const intptr_t value_cid = value()->Type()->ToCid();
5745 const Register value = locs()->in(0).reg(); 5745 const Register value = locs()->in(0).reg();
5746 const QRegister result = locs()->out(0).fpu_reg(); 5746 PairLocation* result_pair = locs()->out(0).AsPairLocation();
5747 Register result_lo = result_pair->At(0).reg();
5748 Register result_hi = result_pair->At(1).reg();
5749 ASSERT(value != result_lo);
5750 ASSERT(value != result_hi);
5747 5751
5748 __ Comment("UnboxIntegerInstr"); 5752 __ Comment("UnboxIntegerInstr");
5749 __ veorq(result, result, result);
5750 if (value_cid == kMintCid) { 5753 if (value_cid == kMintCid) {
5751 __ LoadDFromOffset(EvenDRegisterOf(result), value, 5754 // Load low word.
5752 Mint::value_offset() - kHeapObjectTag); 5755 __ LoadFromOffset(kWord,
5756 result_lo,
5757 value,
5758 Mint::value_offset() - kHeapObjectTag);
5759 // Load high word.
5760 __ LoadFromOffset(kWord,
5761 result_hi,
5762 value,
5763 Mint::value_offset() - kHeapObjectTag + kWordSize);
5753 } else if (value_cid == kSmiCid) { 5764 } else if (value_cid == kSmiCid) {
5754 Register temp = locs()->temp(0).reg(); 5765 // Load Smi into result_lo.
5755 __ SmiUntag(value); 5766 __ mov(result_lo, ShifterOperand(value));
5756 // Sign extend value into temp. 5767 // Untag.
5757 __ Asr(temp, value, 31); 5768 __ SmiUntag(result_lo);
5758 __ vmovdrr(EvenDRegisterOf(result), value, temp); 5769 __ SignFill(result_hi, result_lo);
5759 } else { 5770 } else {
5760 Register temp = locs()->temp(0).reg(); 5771 Register temp = locs()->temp(0).reg();
5761 Label* deopt = compiler->AddDeoptStub(deopt_id_, 5772 Label* deopt = compiler->AddDeoptStub(deopt_id_,
5762 ICData::kDeoptUnboxInteger); 5773 ICData::kDeoptUnboxInteger);
5763 Label is_smi, done; 5774 Label is_smi, done;
5764 __ tst(value, ShifterOperand(kSmiTagMask)); 5775 __ tst(value, ShifterOperand(kSmiTagMask));
5765 __ b(&is_smi, EQ); 5776 __ b(&is_smi, EQ);
5766 __ CompareClassId(value, kMintCid, temp); 5777 __ CompareClassId(value, kMintCid, temp);
5767 __ b(deopt, NE); 5778 __ b(deopt, NE);
5768 5779
5769 // It's a Mint. 5780 // It's a Mint.
5770 __ LoadDFromOffset(EvenDRegisterOf(result), value, 5781 // Load low word.
5771 Mint::value_offset() - kHeapObjectTag); 5782 __ LoadFromOffset(kWord,
5783 result_lo,
5784 value,
5785 Mint::value_offset() - kHeapObjectTag);
5786 // Load high word.
5787 __ LoadFromOffset(kWord,
5788 result_hi,
5789 value,
5790 Mint::value_offset() - kHeapObjectTag + kWordSize);
5772 __ b(&done); 5791 __ b(&done);
5773 5792
5774 // It's a Smi. 5793 // It's a Smi.
5775 __ Bind(&is_smi); 5794 __ Bind(&is_smi);
5776 __ SmiUntag(value); 5795 // Load Smi into result_lo.
5777 // Sign extend into temp. 5796 __ mov(result_lo, ShifterOperand(value));
5778 __ Asr(temp, value, 31); 5797 // Untag.
5779 __ vmovdrr(EvenDRegisterOf(result), value, temp); 5798 __ SmiUntag(result_lo);
5799 // Sign extend result_lo into result_hi.
5800 __ SignFill(result_hi, result_lo);
5780 __ Bind(&done); 5801 __ Bind(&done);
5781 } 5802 }
5782 } 5803 }
5783 5804
5784 5805
5785 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { 5806 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
5786 const intptr_t kNumInputs = 1; 5807 const intptr_t kNumInputs = 1;
5787 const intptr_t kNumTemps = 2; 5808 const intptr_t kNumTemps = 1;
5788 LocationSummary* summary = 5809 LocationSummary* summary =
5789 new LocationSummary(kNumInputs, 5810 new LocationSummary(kNumInputs,
5790 kNumTemps, 5811 kNumTemps,
5791 LocationSummary::kCallOnSlowPath); 5812 LocationSummary::kCallOnSlowPath);
5792 summary->set_in(0, Location::RequiresFpuRegister()); 5813 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5814 Location::RequiresRegister()));
5793 summary->set_temp(0, Location::RequiresRegister()); 5815 summary->set_temp(0, Location::RequiresRegister());
5794 summary->set_temp(1, Location::RequiresRegister());
5795 summary->set_out(0, Location::RequiresRegister()); 5816 summary->set_out(0, Location::RequiresRegister());
5796 return summary; 5817 return summary;
5797 } 5818 }
5798 5819
5799 5820
5800 class BoxIntegerSlowPath : public SlowPathCode { 5821 class BoxIntegerSlowPath : public SlowPathCode {
5801 public: 5822 public:
5802 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) 5823 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction)
5803 : instruction_(instruction) { } 5824 : instruction_(instruction) { }
5804 5825
(...skipping 21 matching lines...) Expand all
5826 } 5847 }
5827 5848
5828 private: 5849 private:
5829 BoxIntegerInstr* instruction_; 5850 BoxIntegerInstr* instruction_;
5830 }; 5851 };
5831 5852
5832 5853
5833 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5854 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5834 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); 5855 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
5835 compiler->AddSlowPathCode(slow_path); 5856 compiler->AddSlowPathCode(slow_path);
5836 5857 PairLocation* value_pair = locs()->in(0).AsPairLocation();
5858 Register value_lo = value_pair->At(0).reg();
5859 Register value_hi = value_pair->At(1).reg();
5860 Register tmp = locs()->temp(0).reg();
5837 Register out_reg = locs()->out(0).reg(); 5861 Register out_reg = locs()->out(0).reg();
5838 QRegister value = locs()->in(0).fpu_reg();
5839 DRegister dvalue0 = EvenDRegisterOf(value);
5840 Register lo = locs()->temp(0).reg();
5841 Register hi = locs()->temp(1).reg();
5842 5862
5843 // Unboxed operations produce smis or mint-sized values. 5863 // Unboxed operations produce smis or mint-sized values.
5844 // Check if value fits into a smi. 5864 // Check if value fits into a smi.
5845 __ Comment("BoxIntegerInstr"); 5865 __ Comment("BoxIntegerInstr");
5846 Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi; 5866 Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi;
5847 __ vmovrrd(lo, hi, dvalue0); 5867 // Check high word.
5848 __ CompareImmediate(hi, 0); 5868 __ CompareImmediate(value_hi, 0);
5849 __ b(&maybe_pos_smi, EQ); 5869 __ b(&maybe_pos_smi, EQ);
5850 5870
5851 __ CompareImmediate(hi, -1); 5871 __ CompareImmediate(value_hi, -1);
5852 __ b(&maybe_neg_smi, EQ); 5872 __ b(&maybe_neg_smi, EQ);
5853 __ b(&not_smi); 5873 __ b(&not_smi);
5854 5874
5855 __ Bind(&maybe_pos_smi); 5875 __ Bind(&maybe_pos_smi);
5856 __ CompareImmediate(lo, kSmiMax); 5876 __ CompareImmediate(value_lo, kSmiMax);
5857 __ b(&is_smi, LS); // unsigned lower or same. 5877 __ b(&is_smi, LS); // unsigned lower or same.
5858 __ b(&not_smi); 5878 __ b(&not_smi);
5859 5879
5860 __ Bind(&maybe_neg_smi); 5880 __ Bind(&maybe_neg_smi);
5861 __ CompareImmediate(lo, 0); 5881 __ CompareImmediate(value_lo, 0);
5862 __ b(&not_smi, GE); 5882 __ b(&not_smi, GE);
5863 __ CompareImmediate(lo, kSmiMin); 5883 __ CompareImmediate(value_lo, kSmiMin);
5864 __ b(&not_smi, LT); 5884 __ b(&not_smi, LT);
5865 5885
5866 // lo is a Smi. Tag it and return. 5886 // lo is a Smi. Tag it and return.
5867 __ Bind(&is_smi); 5887 __ Bind(&is_smi);
5868 __ SmiTag(lo); 5888 __ mov(out_reg, ShifterOperand(value_lo));
5869 __ mov(out_reg, ShifterOperand(lo)); 5889 __ SmiTag(out_reg);
5870 __ b(&done); 5890 __ b(&done);
5871 5891
5872 // Not a smi. Box it. 5892 // Not a smi. Box it.
5873 __ Bind(&not_smi); 5893 __ Bind(&not_smi);
5874 __ TryAllocate( 5894 __ TryAllocate(
5875 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), 5895 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
5876 slow_path->entry_label(), 5896 slow_path->entry_label(),
5877 out_reg, 5897 out_reg,
5878 lo); 5898 tmp);
5879 __ Bind(slow_path->exit_label()); 5899 __ Bind(slow_path->exit_label());
5880 __ StoreDToOffset(dvalue0, out_reg, Mint::value_offset() - kHeapObjectTag); 5900 __ StoreToOffset(kWord,
5901 value_lo,
5902 out_reg,
5903 Mint::value_offset() - kHeapObjectTag);
5904 __ StoreToOffset(kWord,
5905 value_hi,
5906 out_reg,
5907 Mint::value_offset() - kHeapObjectTag + kWordSize);
5881 __ Bind(&done); 5908 __ Bind(&done);
5882 } 5909 }
5883 5910
5884 5911
5885 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { 5912 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
5886 const intptr_t kNumInputs = 2; 5913 const intptr_t kNumInputs = 2;
5887 const intptr_t kNumTemps = 5914 const intptr_t kNumTemps = 0;
5888 FLAG_throw_on_javascript_int_overflow ? 2 : 0;
5889 LocationSummary* summary = 5915 LocationSummary* summary =
5890 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5916 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5891 summary->set_in(0, Location::RequiresFpuRegister()); 5917 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5892 summary->set_in(1, Location::RequiresFpuRegister()); 5918 Location::RequiresRegister()));
5893 if (FLAG_throw_on_javascript_int_overflow) { 5919 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
5894 summary->set_temp(0, Location::RequiresRegister()); 5920 Location::RequiresRegister()));
5895 summary->set_temp(1, Location::RequiresRegister()); 5921 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5896 } 5922 Location::RequiresRegister()));
5897 if ((op_kind() == Token::kADD) || (op_kind() == Token::kSUB)) {
5898 // Need another temp for checking for overflow.
5899 summary->AddTemp(Location::RequiresFpuRegister());
5900 summary->AddTemp(Location::FpuRegisterLocation(Q7));
5901 }
5902 summary->set_out(0, Location::RequiresFpuRegister());
5903 return summary; 5923 return summary;
5904 } 5924 }
5905 5925
5906 5926
5907 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5927 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5908 QRegister left = locs()->in(0).fpu_reg(); 5928 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5909 QRegister right = locs()->in(1).fpu_reg(); 5929 Register left_lo = left_pair->At(0).reg();
5910 QRegister out = locs()->out(0).fpu_reg(); 5930 Register left_hi = left_pair->At(1).reg();
5931 PairLocation* right_pair = locs()->in(1).AsPairLocation();
5932 Register right_lo = right_pair->At(0).reg();
5933 Register right_hi = right_pair->At(1).reg();
5934 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5935 Register out_lo = out_pair->At(0).reg();
5936 Register out_hi = out_pair->At(1).reg();
5911 5937
5912 Label* deopt = NULL; 5938 Label* deopt = NULL;
5913 if (FLAG_throw_on_javascript_int_overflow) { 5939 if (FLAG_throw_on_javascript_int_overflow) {
5914 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5940 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5915 } 5941 }
5916 switch (op_kind()) { 5942 switch (op_kind()) {
5917 case Token::kBIT_AND: __ vandq(out, left, right); break; 5943 case Token::kBIT_AND: {
5918 case Token::kBIT_OR: __ vorrq(out, left, right); break; 5944 __ and_(out_lo, left_lo, ShifterOperand(right_lo));
5919 case Token::kBIT_XOR: __ veorq(out, left, right); break; 5945 __ and_(out_hi, left_hi, ShifterOperand(right_hi));
5946 }
5947 break;
5948 case Token::kBIT_OR: {
5949 __ orr(out_lo, left_lo, ShifterOperand(right_lo));
5950 __ orr(out_hi, left_hi, ShifterOperand(right_hi));
5951 }
5952 break;
5953 case Token::kBIT_XOR: {
5954 __ eor(out_lo, left_lo, ShifterOperand(right_lo));
5955 __ eor(out_hi, left_hi, ShifterOperand(right_hi));
5956 }
5957 break;
5920 case Token::kADD: 5958 case Token::kADD:
5921 case Token::kSUB: { 5959 case Token::kSUB: {
5922 const intptr_t tmpidx = FLAG_throw_on_javascript_int_overflow ? 2 : 0;
5923 QRegister tmp = locs()->temp(tmpidx).fpu_reg();
5924 QRegister ro = locs()->temp(tmpidx + 1).fpu_reg();
5925 ASSERT(ro == Q7);
5926 if (!FLAG_throw_on_javascript_int_overflow) { 5960 if (!FLAG_throw_on_javascript_int_overflow) {
5927 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5961 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5928 } 5962 }
5929 if (op_kind() == Token::kADD) { 5963 if (op_kind() == Token::kADD) {
5930 __ vaddqi(kWordPair, out, left, right); 5964 __ adds(out_lo, left_lo, ShifterOperand(right_lo));
5965 __ adcs(out_hi, left_hi, ShifterOperand(right_hi));
5931 } else { 5966 } else {
5932 ASSERT(op_kind() == Token::kSUB); 5967 ASSERT(op_kind() == Token::kSUB);
5933 __ vsubqi(kWordPair, out, left, right); 5968 __ subs(out_lo, left_lo, ShifterOperand(right_lo));
5969 __ sbcs(out_hi, left_hi, ShifterOperand(right_hi));
5934 } 5970 }
5935 __ veorq(ro, out, left); 5971 // Deopt on overflow.
5936 __ veorq(tmp, left, right); 5972 __ b(deopt, VS);
5937 __ vandq(ro, tmp, ro);
5938 __ vmovrs(TMP, OddSRegisterOf(EvenDRegisterOf(ro)));
5939 // If TMP < 0, there was overflow.
5940 __ cmp(TMP, ShifterOperand(0));
5941 __ b(deopt, LT);
5942 break; 5973 break;
5943 } 5974 }
5944 default: UNREACHABLE(); break; 5975 default:
5976 UNREACHABLE();
5977 break;
5945 } 5978 }
5946 if (FLAG_throw_on_javascript_int_overflow) { 5979 if (FLAG_throw_on_javascript_int_overflow) {
5947 Register tmp1 = locs()->temp(0).reg(); 5980 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
5948 Register tmp2 = locs()->temp(1).reg();
5949 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
5950 } 5981 }
5951 } 5982 }
5952 5983
5953 5984
5954 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { 5985 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
5955 const intptr_t kNumInputs = 2; 5986 const intptr_t kNumInputs = 2;
5956 const intptr_t kNumTemps = 5987 const intptr_t kNumTemps = 1;
5957 FLAG_throw_on_javascript_int_overflow ? 2 : 1;
5958 LocationSummary* summary = 5988 LocationSummary* summary =
5959 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5989 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5960 summary->set_in(0, Location::RequiresFpuRegister()); 5990 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5991 Location::RequiresRegister()));
5961 summary->set_in(1, Location::WritableRegister()); 5992 summary->set_in(1, Location::WritableRegister());
5962 summary->set_temp(0, Location::FpuRegisterLocation(Q7)); 5993 summary->set_temp(0, Location::RequiresRegister());
5963 if (FLAG_throw_on_javascript_int_overflow) { 5994 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5964 summary->set_temp(1, Location::RequiresRegister()); 5995 Location::RequiresRegister()));
5965 }
5966 summary->set_out(0, Location::RequiresFpuRegister());
5967 return summary; 5996 return summary;
5968 } 5997 }
5969 5998
5970 5999
5971 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6000 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5972 QRegister value = locs()->in(0).fpu_reg(); 6001 PairLocation* left_pair = locs()->in(0).AsPairLocation();
6002 Register left_lo = left_pair->At(0).reg();
6003 Register left_hi = left_pair->At(1).reg();
5973 Register shift = locs()->in(1).reg(); 6004 Register shift = locs()->in(1).reg();
5974 QRegister temp = locs()->temp(0).fpu_reg(); 6005 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5975 ASSERT(temp == Q7); 6006 Register out_lo = out_pair->At(0).reg();
5976 QRegister out = locs()->out(0).fpu_reg(); 6007 Register out_hi = out_pair->At(1).reg();
5977 DRegister dtemp0 = EvenDRegisterOf(temp); 6008 Register temp = locs()->temp(0).reg();
5978 SRegister stemp0 = EvenSRegisterOf(dtemp0);
5979 SRegister stemp1 = OddSRegisterOf(dtemp0);
5980 6009
5981 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); 6010 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
5982 Label done; 6011 Label done;
5983 6012
6013 // Early out if shift is 0.
5984 __ CompareImmediate(shift, 0); 6014 __ CompareImmediate(shift, 0);
5985 __ vmovq(out, value); 6015 __ mov(out_lo, ShifterOperand(left_lo));
6016 __ mov(out_hi, ShifterOperand(left_hi));
5986 __ b(&done, EQ); 6017 __ b(&done, EQ);
6018
6019 // Untag shift count.
5987 __ SmiUntag(shift); 6020 __ SmiUntag(shift);
5988 6021
5989 // vshlq takes the shift value from low byte. Deopt if shift is 6022 // Deopt if shift is negative.
5990 // outside of [0, 63]. 6023 __ CompareImmediate(shift, 1);
6024 __ b(deopt, LT);
6025
6026 // Deopt if shift is larger than 63.
5991 __ CompareImmediate(shift, 63); 6027 __ CompareImmediate(shift, 63);
5992 __ b(deopt, GT); 6028 __ b(deopt, GT);
5993 __ CompareImmediate(shift, 0);
5994 __ b(deopt, LT);
5995 6029
5996 __ veorq(temp, temp, temp); // Zero out temp.
5997 switch (op_kind()) { 6030 switch (op_kind()) {
5998 case Token::kSHR: { 6031 case Token::kSHR: {
5999 __ rsb(shift, shift, ShifterOperand(0)); // Negate shift. 6032 __ cmp(shift, ShifterOperand(32));
6000 __ vmovsr(stemp0, shift); // Move the shift into the low S register. 6033
6001 __ vshlqi(kWordPair, out, value, temp); 6034 __ mov(out_lo, ShifterOperand(out_hi), HI);
6035 __ Asr(out_hi, out_hi, 31, HI);
6036 __ sub(shift, shift, ShifterOperand(32), HI);
6037
6038 __ rsb(temp, shift, ShifterOperand(32));
6039 __ mov(temp, ShifterOperand(out_hi, LSL, temp));
6040 __ orr(out_lo, temp, ShifterOperand(out_lo, LSR, shift));
6041 __ Asr(out_hi, out_hi, shift);
6002 break; 6042 break;
6003 } 6043 }
6004 case Token::kSHL: { 6044 case Token::kSHL: {
6005 __ vmovsr(stemp0, shift); // Move the shift into the low S register. 6045 __ rsbs(temp, shift, ShifterOperand(32));
6006 __ vshlqu(kWordPair, out, value, temp); 6046 __ sub(temp, shift, ShifterOperand(32), MI);
6047 __ mov(out_hi, ShifterOperand(out_lo, LSL, temp), MI);
6048 __ mov(out_hi, ShifterOperand(out_hi, LSL, shift), PL);
6049 __ orr(out_hi, out_hi, ShifterOperand(out_lo, LSR, temp), PL);
6050 __ mov(out_lo, ShifterOperand(out_lo, LSL, shift));
6007 6051
6008 // check for overflow by shifting back and comparing. 6052 // Check for overflow.
6009 __ rsb(shift, shift, ShifterOperand(0)); 6053
6010 __ vmovsr(stemp0, shift); 6054 // Copy high word from output.
6011 __ vshlqi(kWordPair, temp, out, temp); 6055 __ mov(temp, ShifterOperand(out_hi));
6012 __ vceqqi(kWord, temp, temp, value); 6056 // Shift copy right.
6013 // Low 64 bits of temp should be all 1's, otherwise temp != value and 6057 __ Asr(temp, temp, shift);
6014 // we deopt. 6058 // Compare with high word from input.
6015 __ vmovrs(shift, stemp0); 6059 __ cmp(temp, ShifterOperand(left_hi));
6016 __ CompareImmediate(shift, -1); 6060 // Overflow if they aren't equal.
6017 __ b(deopt, NE);
6018 __ vmovrs(shift, stemp1);
6019 __ CompareImmediate(shift, -1);
6020 __ b(deopt, NE); 6061 __ b(deopt, NE);
6021 break; 6062 break;
6022 } 6063 }
6023 default: 6064 default:
6024 UNREACHABLE(); 6065 UNREACHABLE();
6025 break; 6066 break;
6026 } 6067 }
6027 6068
6028 __ Bind(&done); 6069 __ Bind(&done);
6029 if (FLAG_throw_on_javascript_int_overflow) { 6070 if (FLAG_throw_on_javascript_int_overflow) {
6030 Register tmp1 = locs()->in(1).reg(); 6071 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
6031 Register tmp2 = locs()->temp(1).reg();
6032 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
6033 } 6072 }
6034 } 6073 }
6035 6074
6036 6075
6037 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { 6076 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
6038 const intptr_t kNumInputs = 1; 6077 const intptr_t kNumInputs = 1;
6039 const intptr_t kNumTemps = 6078 const intptr_t kNumTemps = 0;
6040 FLAG_throw_on_javascript_int_overflow ? 2 : 0;
6041 LocationSummary* summary = 6079 LocationSummary* summary =
6042 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 6080 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
6043 summary->set_in(0, Location::RequiresFpuRegister()); 6081 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
6044 summary->set_out(0, Location::RequiresFpuRegister()); 6082 Location::RequiresRegister()));
6045 if (FLAG_throw_on_javascript_int_overflow) { 6083 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
6046 summary->set_temp(0, Location::RequiresRegister()); 6084 Location::RequiresRegister()));
6047 summary->set_temp(1, Location::RequiresRegister());
6048 }
6049 return summary; 6085 return summary;
6050 } 6086 }
6051 6087
6052 6088
6053 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6089 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6054 ASSERT(op_kind() == Token::kBIT_NOT); 6090 ASSERT(op_kind() == Token::kBIT_NOT);
6055 QRegister value = locs()->in(0).fpu_reg(); 6091
6056 QRegister out = locs()->out(0).fpu_reg(); 6092 PairLocation* left_pair = locs()->in(0).AsPairLocation();
6093 Register left_lo = left_pair->At(0).reg();
6094 Register left_hi = left_pair->At(1).reg();
6095
6096 PairLocation* out_pair = locs()->out(0).AsPairLocation();
6097 Register out_lo = out_pair->At(0).reg();
6098 Register out_hi = out_pair->At(1).reg();
6099
6057 Label* deopt = NULL; 6100 Label* deopt = NULL;
6101
6058 if (FLAG_throw_on_javascript_int_overflow) { 6102 if (FLAG_throw_on_javascript_int_overflow) {
6059 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); 6103 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
6060 } 6104 }
6061 __ vmvnq(out, value); 6105 __ mvn(out_lo, ShifterOperand(left_lo));
6106 __ mvn(out_hi, ShifterOperand(left_hi));
6062 if (FLAG_throw_on_javascript_int_overflow) { 6107 if (FLAG_throw_on_javascript_int_overflow) {
6063 Register tmp1 = locs()->temp(0).reg(); 6108 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
6064 Register tmp2 = locs()->temp(1).reg();
6065 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
6066 } 6109 }
6067 } 6110 }
6068 6111
6069 6112
6070 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { 6113 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const {
6071 return new LocationSummary(0, 0, LocationSummary::kCall); 6114 return new LocationSummary(0, 0, LocationSummary::kCall);
6072 } 6115 }
6073 6116
6074 6117
6075 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6118 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
6265 compiler->GenerateCall(token_pos(), 6308 compiler->GenerateCall(token_pos(),
6266 &label, 6309 &label,
6267 PcDescriptors::kOther, 6310 PcDescriptors::kOther,
6268 locs()); 6311 locs());
6269 __ Drop(ArgumentCount()); // Discard arguments. 6312 __ Drop(ArgumentCount()); // Discard arguments.
6270 } 6313 }
6271 6314
6272 } // namespace dart 6315 } // namespace dart
6273 6316
6274 #endif // defined TARGET_ARCH_ARM 6317 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698