| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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(¬_smi); | 5873 __ b(¬_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(¬_smi); | 5878 __ b(¬_smi); |
| 5859 | 5879 |
| 5860 __ Bind(&maybe_neg_smi); | 5880 __ Bind(&maybe_neg_smi); |
| 5861 __ CompareImmediate(lo, 0); | 5881 __ CompareImmediate(value_lo, 0); |
| 5862 __ b(¬_smi, GE); | 5882 __ b(¬_smi, GE); |
| 5863 __ CompareImmediate(lo, kSmiMin); | 5883 __ CompareImmediate(value_lo, kSmiMin); |
| 5864 __ b(¬_smi, LT); | 5884 __ b(¬_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(¬_smi); | 5893 __ Bind(¬_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 Loading... |
| 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 |
| OLD | NEW |