Chromium Code Reviews| 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 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 372 default: | 372 default: |
| 373 UNREACHABLE(); | 373 UNREACHABLE(); |
| 374 return VS; | 374 return VS; |
| 375 } | 375 } |
| 376 } | 376 } |
| 377 | 377 |
| 378 | 378 |
| 379 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { | 379 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { |
| 380 const intptr_t kNumInputs = 2; | 380 const intptr_t kNumInputs = 2; |
| 381 if (operation_cid() == kMintCid) { | 381 if (operation_cid() == kMintCid) { |
| 382 const intptr_t kNumTemps = 3; | 382 const intptr_t kNumTemps = 0; |
| 383 LocationSummary* locs = | 383 LocationSummary* locs = |
| 384 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 384 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 385 locs->set_in(0, Location::RequiresFpuRegister()); | 385 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 386 locs->set_in(1, Location::RequiresFpuRegister()); | 386 Location::RequiresRegister())); |
| 387 locs->set_temp(0, Location::RequiresFpuRegister()); | 387 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 388 locs->set_temp(1, Location::RequiresRegister()); | 388 Location::RequiresRegister())); |
| 389 locs->set_temp(2, Location::RequiresRegister()); | |
| 390 locs->set_out(0, Location::RequiresRegister()); | 389 locs->set_out(0, Location::RequiresRegister()); |
| 391 return locs; | 390 return locs; |
| 392 } | 391 } |
| 393 if (operation_cid() == kDoubleCid) { | 392 if (operation_cid() == kDoubleCid) { |
| 394 const intptr_t kNumTemps = 0; | 393 const intptr_t kNumTemps = 0; |
| 395 LocationSummary* locs = | 394 LocationSummary* locs = |
| 396 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 395 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 397 locs->set_in(0, Location::RequiresFpuRegister()); | 396 locs->set_in(0, Location::RequiresFpuRegister()); |
| 398 locs->set_in(1, Location::RequiresFpuRegister()); | 397 locs->set_in(1, Location::RequiresFpuRegister()); |
| 399 locs->set_out(0, Location::RequiresRegister()); | 398 locs->set_out(0, Location::RequiresRegister()); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 507 UNREACHABLE(); | 506 UNREACHABLE(); |
| 508 return VS; | 507 return VS; |
| 509 } | 508 } |
| 510 } | 509 } |
| 511 | 510 |
| 512 | 511 |
| 513 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 512 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
| 514 LocationSummary* locs, | 513 LocationSummary* locs, |
| 515 Token::Kind kind) { | 514 Token::Kind kind) { |
| 516 ASSERT(Token::IsEqualityOperator(kind)); | 515 ASSERT(Token::IsEqualityOperator(kind)); |
| 517 QRegister left = locs->in(0).fpu_reg(); | 516 PairLocation* left_pair = locs->in(0).AsPairLocation(); |
| 518 QRegister right = locs->in(1).fpu_reg(); | 517 Register left1 = left_pair->At(0).reg(); |
|
zra
2014/05/14 18:27:41
optional: rename to {left, right}_{lo, hi}.
Cutch
2014/05/15 18:26:08
Done.
| |
| 519 QRegister tmpq = locs->temp(0).fpu_reg(); | 518 Register left2 = left_pair->At(1).reg(); |
| 520 Register tmp_lo = locs->temp(1).reg(); | 519 PairLocation* right_pair = locs->in(1).AsPairLocation(); |
| 521 Register tmp_hi = locs->temp(2).reg(); | 520 Register right1 = right_pair->At(0).reg(); |
| 521 Register right2 = right_pair->At(1).reg(); | |
| 522 | 522 |
| 523 __ vceqqi(kWord, tmpq, left, right); | 523 Label done; |
| 524 __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(tmpq)); | |
| 525 // tmp_lo and tmp_hi must both be 0xffffffff. | |
| 526 __ and_(tmp_lo, tmp_lo, ShifterOperand(tmp_hi)); | |
| 527 | 524 |
| 528 Condition true_condition = TokenKindToMintCondition(kind); | 525 // Compare lower. |
| 529 __ CompareImmediate(tmp_lo, 0xffffffff); | 526 __ cmp(left1, ShifterOperand(right1)); |
| 530 return true_condition; | 527 __ b(&done, NE); |
| 528 // Lower is equal, compare upper. | |
| 529 __ cmp(left2, ShifterOperand(right2)); | |
|
zra
2014/05/14 18:27:41
Remove branch, instead:
__ cmp(left2, ShifterOpera
Cutch
2014/05/15 18:26:08
Done but I think you meant EQ instead of NE.
zra
2014/05/15 18:30:45
Yes, you're right.
| |
| 530 __ Bind(&done); | |
| 531 return TokenKindToMintCondition(kind); | |
| 531 } | 532 } |
| 532 | 533 |
| 533 | 534 |
| 534 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | 535 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
| 535 LocationSummary* locs, | 536 LocationSummary* locs, |
| 536 Token::Kind kind) { | 537 Token::Kind kind) { |
| 537 QRegister left = locs->in(0).fpu_reg(); | 538 PairLocation* left_pair = locs->in(0).AsPairLocation(); |
| 538 QRegister right = locs->in(1).fpu_reg(); | 539 Register left1 = left_pair->At(0).reg(); |
|
zra
2014/05/14 18:27:41
optional: rename to {left, right}_{lo, hi}.
Cutch
2014/05/15 18:26:08
Done.
| |
| 539 DRegister dleft0 = EvenDRegisterOf(left); | 540 Register left2 = left_pair->At(1).reg(); |
| 540 DRegister dright0 = EvenDRegisterOf(right); | 541 PairLocation* right_pair = locs->in(1).AsPairLocation(); |
| 541 SRegister sleft0 = EvenSRegisterOf(dleft0); | 542 Register right1 = right_pair->At(0).reg(); |
| 542 SRegister sleft1 = OddSRegisterOf(dleft0); | 543 Register right2 = right_pair->At(1).reg(); |
| 543 SRegister sright0 = EvenSRegisterOf(dright0); | |
| 544 SRegister sright1 = OddSRegisterOf(dright0); | |
| 545 | 544 |
| 546 Register tmp_left = locs->temp(0).reg(); | 545 Register out = locs->temp(0).reg(); |
| 547 Register tmp_right = locs->temp(1).reg(); | |
| 548 | 546 |
| 549 // 64-bit comparison | 547 // 64-bit comparison |
| 550 Condition hi_true_cond, hi_false_cond, lo_false_cond; | 548 Condition hi_true_cond, hi_false_cond, lo_false_cond; |
| 551 switch (kind) { | 549 switch (kind) { |
| 552 case Token::kLT: | 550 case Token::kLT: |
| 553 case Token::kLTE: | 551 case Token::kLTE: |
| 554 hi_true_cond = LT; | 552 hi_true_cond = LT; |
| 555 hi_false_cond = GT; | 553 hi_false_cond = GT; |
| 556 lo_false_cond = (kind == Token::kLT) ? CS : HI; | 554 lo_false_cond = (kind == Token::kLT) ? CS : HI; |
| 557 break; | 555 break; |
| 558 case Token::kGT: | 556 case Token::kGT: |
| 559 case Token::kGTE: | 557 case Token::kGTE: |
| 560 hi_true_cond = GT; | 558 hi_true_cond = GT; |
| 561 hi_false_cond = LT; | 559 hi_false_cond = LT; |
| 562 lo_false_cond = (kind == Token::kGT) ? LS : CC; | 560 lo_false_cond = (kind == Token::kGT) ? LS : CC; |
| 563 break; | 561 break; |
| 564 default: | 562 default: |
| 565 UNREACHABLE(); | 563 UNREACHABLE(); |
| 566 hi_true_cond = hi_false_cond = lo_false_cond = VS; | 564 hi_true_cond = hi_false_cond = lo_false_cond = VS; |
| 567 } | 565 } |
| 568 | 566 |
| 569 Label is_true, is_false, done; | 567 Label is_true, is_false, done; |
| 570 __ vmovrs(tmp_left, sleft1); | 568 // Compare upper halves first. |
| 571 __ vmovrs(tmp_right, sright1); | 569 __ cmp(left2, ShifterOperand(right2)); |
| 572 __ cmp(tmp_left, ShifterOperand(tmp_right)); | |
| 573 __ b(&is_false, hi_false_cond); | 570 __ b(&is_false, hi_false_cond); |
| 574 __ b(&is_true, hi_true_cond); | 571 __ b(&is_true, hi_true_cond); |
|
zra
2014/05/14 18:27:41
Instead, to avoid so many branches:
__ cmp(left2,
Cutch
2014/05/15 18:26:08
Done.
| |
| 575 | 572 |
| 576 __ vmovrs(tmp_left, sleft0); | 573 // If upper is equal, compare lower half. |
| 577 __ vmovrs(tmp_right, sright0); | 574 __ cmp(left1, ShifterOperand(right1)); |
| 578 __ cmp(tmp_left, ShifterOperand(tmp_right)); | |
| 579 __ b(&is_false, lo_false_cond); | 575 __ b(&is_false, lo_false_cond); |
| 576 | |
| 580 // Else is true. | 577 // Else is true. |
| 581 __ b(&is_true); | 578 __ b(&is_true); |
| 582 | 579 |
| 583 __ Bind(&is_false); | 580 __ Bind(&is_false); |
| 584 __ LoadImmediate(tmp_left, 0); | 581 __ LoadImmediate(out, 0); |
| 585 __ b(&done); | 582 __ b(&done); |
| 586 __ Bind(&is_true); | 583 __ Bind(&is_true); |
| 587 __ LoadImmediate(tmp_left, 1); | 584 __ LoadImmediate(out, 1); |
| 588 __ Bind(&done); | 585 __ Bind(&done); |
| 589 return NegateCondition(lo_false_cond); | 586 return NegateCondition(lo_false_cond); |
| 590 } | 587 } |
| 591 | 588 |
| 592 | 589 |
| 593 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 590 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 594 switch (kind) { | 591 switch (kind) { |
| 595 case Token::kEQ: return EQ; | 592 case Token::kEQ: return EQ; |
| 596 case Token::kNE: return NE; | 593 case Token::kNE: return NE; |
| 597 case Token::kLT: return LT; | 594 case Token::kLT: return LT; |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 785 __ Bind(&is_true); | 782 __ Bind(&is_true); |
| 786 __ LoadObject(result_reg, Bool::True()); | 783 __ LoadObject(result_reg, Bool::True()); |
| 787 __ Bind(&done); | 784 __ Bind(&done); |
| 788 } | 785 } |
| 789 | 786 |
| 790 | 787 |
| 791 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const { | 788 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const { |
| 792 const intptr_t kNumInputs = 2; | 789 const intptr_t kNumInputs = 2; |
| 793 const intptr_t kNumTemps = 0; | 790 const intptr_t kNumTemps = 0; |
| 794 if (operation_cid() == kMintCid) { | 791 if (operation_cid() == kMintCid) { |
| 795 const intptr_t kNumTemps = 2; | 792 const intptr_t kNumTemps = 1; |
| 796 LocationSummary* locs = | 793 LocationSummary* locs = |
| 797 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 794 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 798 locs->set_in(0, Location::RequiresFpuRegister()); | 795 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 799 locs->set_in(1, Location::RequiresFpuRegister()); | 796 Location::RequiresRegister())); |
| 797 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | |
| 798 Location::RequiresRegister())); | |
| 800 locs->set_temp(0, Location::RequiresRegister()); | 799 locs->set_temp(0, Location::RequiresRegister()); |
| 801 locs->set_temp(1, Location::RequiresRegister()); | |
| 802 locs->set_out(0, Location::RequiresRegister()); | 800 locs->set_out(0, Location::RequiresRegister()); |
| 803 return locs; | 801 return locs; |
| 804 } | 802 } |
| 805 if (operation_cid() == kDoubleCid) { | 803 if (operation_cid() == kDoubleCid) { |
| 806 LocationSummary* summary = | 804 LocationSummary* summary = |
| 807 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 805 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 808 summary->set_in(0, Location::RequiresFpuRegister()); | 806 summary->set_in(0, Location::RequiresFpuRegister()); |
| 809 summary->set_in(1, Location::RequiresFpuRegister()); | 807 summary->set_in(1, Location::RequiresFpuRegister()); |
| 810 summary->set_out(0, Location::RequiresRegister()); | 808 summary->set_out(0, Location::RequiresRegister()); |
| 811 return summary; | 809 return summary; |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1141 (representation() == kUnboxedInt32x4) || | 1139 (representation() == kUnboxedInt32x4) || |
| 1142 (representation() == kUnboxedFloat64x2)) { | 1140 (representation() == kUnboxedFloat64x2)) { |
| 1143 if (class_id() == kTypedDataFloat32ArrayCid) { | 1141 if (class_id() == kTypedDataFloat32ArrayCid) { |
| 1144 // Need register <= Q7 for float operations. | 1142 // Need register <= Q7 for float operations. |
| 1145 // TODO(fschneider): Add a register policy to specify a subset of | 1143 // TODO(fschneider): Add a register policy to specify a subset of |
| 1146 // registers. | 1144 // registers. |
| 1147 locs->set_out(0, Location::FpuRegisterLocation(Q7)); | 1145 locs->set_out(0, Location::FpuRegisterLocation(Q7)); |
| 1148 } else { | 1146 } else { |
| 1149 locs->set_out(0, Location::RequiresFpuRegister()); | 1147 locs->set_out(0, Location::RequiresFpuRegister()); |
| 1150 } | 1148 } |
| 1149 } else if (representation() == kUnboxedMint) { | |
| 1150 locs->set_out(0, Location::Pair(Location::RequiresRegister(), | |
| 1151 Location::RequiresRegister())); | |
| 1151 } else { | 1152 } else { |
| 1153 ASSERT(representation() == kTagged); | |
| 1152 locs->set_out(0, Location::RequiresRegister()); | 1154 locs->set_out(0, Location::RequiresRegister()); |
| 1153 } | 1155 } |
| 1154 return locs; | 1156 return locs; |
| 1155 } | 1157 } |
| 1156 | 1158 |
| 1157 | 1159 |
| 1158 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1160 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1159 if ((representation() == kUnboxedDouble) || | 1161 if ((representation() == kUnboxedDouble) || |
| 1160 (representation() == kUnboxedMint) || | |
| 1161 (representation() == kUnboxedFloat32x4) || | 1162 (representation() == kUnboxedFloat32x4) || |
| 1162 (representation() == kUnboxedInt32x4) || | 1163 (representation() == kUnboxedInt32x4) || |
| 1163 (representation() == kUnboxedFloat64x2)) { | 1164 (representation() == kUnboxedFloat64x2)) { |
| 1164 Register array = locs()->in(0).reg(); | 1165 Register array = locs()->in(0).reg(); |
| 1165 Register idx = locs()->in(1).reg(); | 1166 Register idx = locs()->in(1).reg(); |
| 1166 switch (index_scale()) { | 1167 switch (index_scale()) { |
| 1167 case 1: | 1168 case 1: |
| 1168 __ add(idx, array, ShifterOperand(idx, ASR, kSmiTagSize)); | 1169 __ add(idx, array, ShifterOperand(idx, ASR, kSmiTagSize)); |
| 1169 break; | 1170 break; |
| 1170 case 4: | 1171 case 4: |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1182 } | 1183 } |
| 1183 if (!IsExternal()) { | 1184 if (!IsExternal()) { |
| 1184 ASSERT(this->array()->definition()->representation() == kTagged); | 1185 ASSERT(this->array()->definition()->representation() == kTagged); |
| 1185 __ AddImmediate(idx, | 1186 __ AddImmediate(idx, |
| 1186 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); | 1187 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); |
| 1187 } | 1188 } |
| 1188 Address element_address(idx); | 1189 Address element_address(idx); |
| 1189 const QRegister result = locs()->out(0).fpu_reg(); | 1190 const QRegister result = locs()->out(0).fpu_reg(); |
| 1190 const DRegister dresult0 = EvenDRegisterOf(result); | 1191 const DRegister dresult0 = EvenDRegisterOf(result); |
| 1191 switch (class_id()) { | 1192 switch (class_id()) { |
| 1192 case kTypedDataInt32ArrayCid: | |
| 1193 __ veorq(result, result, result); | |
| 1194 __ ldr(TMP, element_address); | |
| 1195 // Re-use the index register so we don't have to require a low-numbered | |
| 1196 // Q register. | |
| 1197 // Sign-extend into idx. | |
| 1198 __ Asr(idx, TMP, 31); | |
| 1199 __ vmovdrr(dresult0, TMP, idx); | |
| 1200 break; | |
| 1201 case kTypedDataUint32ArrayCid: | |
| 1202 __ veorq(result, result, result); | |
| 1203 __ ldr(TMP, element_address); | |
| 1204 // Re-use the index register so we don't have to require a low-numbered | |
| 1205 // Q register. | |
| 1206 __ LoadImmediate(idx, 0); | |
| 1207 __ vmovdrr(dresult0, TMP, idx); | |
| 1208 break; | |
| 1209 case kTypedDataFloat32ArrayCid: | 1193 case kTypedDataFloat32ArrayCid: |
| 1210 // Load single precision float. | 1194 // Load single precision float. |
| 1211 // vldrs does not support indexed addressing. | 1195 // vldrs does not support indexed addressing. |
| 1212 __ vldrs(EvenSRegisterOf(dresult0), element_address); | 1196 __ vldrs(EvenSRegisterOf(dresult0), element_address); |
| 1213 break; | 1197 break; |
| 1214 case kTypedDataFloat64ArrayCid: | 1198 case kTypedDataFloat64ArrayCid: |
| 1215 // vldrd does not support indexed addressing. | 1199 // vldrd does not support indexed addressing. |
| 1216 __ vldrd(dresult0, element_address); | 1200 __ vldrd(dresult0, element_address); |
| 1217 break; | 1201 break; |
| 1218 case kTypedDataFloat64x2ArrayCid: | 1202 case kTypedDataFloat64x2ArrayCid: |
| 1219 case kTypedDataInt32x4ArrayCid: | 1203 case kTypedDataInt32x4ArrayCid: |
| 1220 case kTypedDataFloat32x4ArrayCid: | 1204 case kTypedDataFloat32x4ArrayCid: |
| 1221 __ vldmd(IA, idx, dresult0, 2); | 1205 __ vldmd(IA, idx, dresult0, 2); |
| 1222 break; | 1206 break; |
| 1207 default: | |
| 1208 UNREACHABLE(); | |
| 1223 } | 1209 } |
| 1224 return; | 1210 return; |
| 1225 } | 1211 } |
| 1226 | 1212 |
| 1227 Register array = locs()->in(0).reg(); | 1213 Register array = locs()->in(0).reg(); |
| 1228 Location index = locs()->in(1); | 1214 Location index = locs()->in(1); |
| 1229 | 1215 |
| 1230 Address element_address(kNoRegister, 0); | 1216 Address element_address(kNoRegister, 0); |
| 1231 ASSERT(index.IsRegister()); // TODO(regis): Revisit. | 1217 ASSERT(index.IsRegister()); // TODO(regis): Revisit. |
| 1232 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays | 1218 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1256 default: | 1242 default: |
| 1257 UNREACHABLE(); | 1243 UNREACHABLE(); |
| 1258 } | 1244 } |
| 1259 | 1245 |
| 1260 if (!IsExternal()) { | 1246 if (!IsExternal()) { |
| 1261 ASSERT(this->array()->definition()->representation() == kTagged); | 1247 ASSERT(this->array()->definition()->representation() == kTagged); |
| 1262 __ AddImmediate(index.reg(), | 1248 __ AddImmediate(index.reg(), |
| 1263 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); | 1249 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); |
| 1264 } | 1250 } |
| 1265 element_address = Address(array, index.reg(), LSL, 0); | 1251 element_address = Address(array, index.reg(), LSL, 0); |
| 1252 | |
| 1253 if (representation() == kUnboxedMint) { | |
| 1254 ASSERT(locs()->out(0).IsPairLocation()); | |
| 1255 PairLocation* result_pair = locs()->out(0).AsPairLocation(); | |
| 1256 Register result1 = result_pair->At(0).reg(); | |
| 1257 Register result2 = result_pair->At(1).reg(); | |
| 1258 switch (class_id()) { | |
| 1259 case kTypedDataInt32ArrayCid: | |
| 1260 // Load low word. | |
| 1261 __ ldr(result1, element_address); | |
| 1262 // Sign extend into high word. | |
| 1263 __ SignFill(result2, result1); | |
| 1264 break; | |
| 1265 case kTypedDataUint32ArrayCid: | |
| 1266 // Load low word. | |
| 1267 __ ldr(result1, element_address); | |
| 1268 // Zero high word. | |
| 1269 __ eor(result2, result2, ShifterOperand(result2)); | |
| 1270 break; | |
| 1271 default: | |
| 1272 UNREACHABLE(); | |
| 1273 break; | |
| 1274 } | |
| 1275 return; | |
| 1276 } | |
| 1277 | |
| 1278 ASSERT(representation() == kTagged); | |
| 1279 | |
| 1266 Register result = locs()->out(0).reg(); | 1280 Register result = locs()->out(0).reg(); |
| 1267 switch (class_id()) { | 1281 switch (class_id()) { |
| 1268 case kTypedDataInt8ArrayCid: | 1282 case kTypedDataInt8ArrayCid: |
| 1269 ASSERT(index_scale() == 1); | 1283 ASSERT(index_scale() == 1); |
| 1270 __ ldrsb(result, element_address); | 1284 __ ldrsb(result, element_address); |
| 1271 __ SmiTag(result); | 1285 __ SmiTag(result); |
| 1272 break; | 1286 break; |
| 1273 case kTypedDataUint8ArrayCid: | 1287 case kTypedDataUint8ArrayCid: |
| 1274 case kTypedDataUint8ClampedArrayCid: | 1288 case kTypedDataUint8ClampedArrayCid: |
| 1275 case kExternalTypedDataUint8ArrayCid: | 1289 case kExternalTypedDataUint8ArrayCid: |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1373 case kTypedDataInt8ArrayCid: | 1387 case kTypedDataInt8ArrayCid: |
| 1374 case kTypedDataUint8ArrayCid: | 1388 case kTypedDataUint8ArrayCid: |
| 1375 case kTypedDataUint8ClampedArrayCid: | 1389 case kTypedDataUint8ClampedArrayCid: |
| 1376 case kOneByteStringCid: | 1390 case kOneByteStringCid: |
| 1377 case kTypedDataInt16ArrayCid: | 1391 case kTypedDataInt16ArrayCid: |
| 1378 case kTypedDataUint16ArrayCid: | 1392 case kTypedDataUint16ArrayCid: |
| 1379 locs->set_in(2, Location::WritableRegister()); | 1393 locs->set_in(2, Location::WritableRegister()); |
| 1380 break; | 1394 break; |
| 1381 case kTypedDataInt32ArrayCid: | 1395 case kTypedDataInt32ArrayCid: |
| 1382 case kTypedDataUint32ArrayCid: | 1396 case kTypedDataUint32ArrayCid: |
| 1383 // Mints are stored in Q registers. For smis, use a writable register | 1397 // For smis, use a writable register because the value must be untagged |
| 1384 // because the value must be untagged before storing. | 1398 // before storing. Mints are stored in register pairs. |
| 1385 locs->set_in(2, value()->IsSmiValue() | 1399 if (value()->IsSmiValue()) { |
| 1386 ? Location::WritableRegister() | 1400 locs->set_in(2, Location::WritableRegister()); |
| 1387 : Location::FpuRegisterLocation(Q7)); | 1401 } else { |
| 1402 // We only move the lower 32-bits so we don't care where the high bits | |
| 1403 // are located. | |
| 1404 locs->set_in(2, Location::Pair(Location::RequiresRegister(), | |
| 1405 Location::Any())); | |
| 1406 } | |
| 1388 break; | 1407 break; |
| 1389 case kTypedDataFloat32ArrayCid: | 1408 case kTypedDataFloat32ArrayCid: |
| 1390 // Need low register (<= Q7). | 1409 // Need low register (<= Q7). |
| 1391 locs->set_in(2, Location::FpuRegisterLocation(Q7)); | 1410 locs->set_in(2, Location::FpuRegisterLocation(Q7)); |
| 1392 break; | 1411 break; |
| 1393 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. | 1412 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. |
| 1394 case kTypedDataInt32x4ArrayCid: | 1413 case kTypedDataInt32x4ArrayCid: |
| 1395 case kTypedDataFloat32x4ArrayCid: | 1414 case kTypedDataFloat32x4ArrayCid: |
| 1396 case kTypedDataFloat64x2ArrayCid: | 1415 case kTypedDataFloat64x2ArrayCid: |
| 1397 locs->set_in(2, Location::RequiresFpuRegister()); | 1416 locs->set_in(2, Location::RequiresFpuRegister()); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1508 } | 1527 } |
| 1509 case kTypedDataInt32ArrayCid: | 1528 case kTypedDataInt32ArrayCid: |
| 1510 case kTypedDataUint32ArrayCid: { | 1529 case kTypedDataUint32ArrayCid: { |
| 1511 if (value()->IsSmiValue()) { | 1530 if (value()->IsSmiValue()) { |
| 1512 ASSERT(RequiredInputRepresentation(2) == kTagged); | 1531 ASSERT(RequiredInputRepresentation(2) == kTagged); |
| 1513 Register value = locs()->in(2).reg(); | 1532 Register value = locs()->in(2).reg(); |
| 1514 __ SmiUntag(value); | 1533 __ SmiUntag(value); |
| 1515 __ str(value, element_address); | 1534 __ str(value, element_address); |
| 1516 } else { | 1535 } else { |
| 1517 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); | 1536 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); |
| 1518 QRegister value = locs()->in(2).fpu_reg(); | 1537 PairLocation* value_pair = locs()->in(2).AsPairLocation(); |
| 1519 ASSERT(value == Q7); | 1538 Register value1 = value_pair->At(0).reg(); |
| 1520 __ vmovrs(TMP, EvenSRegisterOf(EvenDRegisterOf(value))); | 1539 __ str(value1, element_address); |
| 1521 __ str(TMP, element_address); | |
| 1522 } | 1540 } |
| 1523 break; | 1541 break; |
| 1524 } | 1542 } |
| 1525 case kTypedDataFloat32ArrayCid: { | 1543 case kTypedDataFloat32ArrayCid: { |
| 1526 SRegister value = | 1544 SRegister value = |
| 1527 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg())); | 1545 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg())); |
| 1528 __ add(index.reg(), index.reg(), ShifterOperand(array)); | 1546 __ add(index.reg(), index.reg(), ShifterOperand(array)); |
| 1529 __ StoreSToOffset(value, index.reg(), 0); | 1547 __ StoreSToOffset(value, index.reg(), 0); |
| 1530 break; | 1548 break; |
| 1531 } | 1549 } |
| (...skipping 4060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5592 Register length = length_loc.reg(); | 5610 Register length = length_loc.reg(); |
| 5593 Register index = index_loc.reg(); | 5611 Register index = index_loc.reg(); |
| 5594 __ cmp(index, ShifterOperand(length)); | 5612 __ cmp(index, ShifterOperand(length)); |
| 5595 __ b(deopt, CS); | 5613 __ b(deopt, CS); |
| 5596 } | 5614 } |
| 5597 } | 5615 } |
| 5598 | 5616 |
| 5599 | 5617 |
| 5600 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, | 5618 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, |
| 5601 Label* overflow, | 5619 Label* overflow, |
| 5602 QRegister result, | 5620 Register result_lo, |
| 5603 Register tmp_hi, Register tmp_lo) { | 5621 Register result_hi) { |
| 5604 __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(result)); | |
| 5605 // Compare upper half. | 5622 // Compare upper half. |
| 5606 Label check_lower; | 5623 Label check_lower; |
| 5607 __ CompareImmediate(tmp_hi, 0x00200000); | 5624 __ CompareImmediate(result_hi, 0x00200000); |
| 5608 __ b(overflow, GT); | 5625 __ b(overflow, GT); |
| 5609 __ b(&check_lower, NE); | 5626 __ b(&check_lower, NE); |
| 5610 | 5627 |
| 5611 __ CompareImmediate(tmp_lo, 0); | 5628 __ CompareImmediate(result_lo, 0); |
| 5612 __ b(overflow, HI); | 5629 __ b(overflow, HI); |
| 5613 | 5630 |
| 5614 __ Bind(&check_lower); | 5631 __ Bind(&check_lower); |
| 5615 __ CompareImmediate(tmp_hi, -0x00200000); | 5632 __ CompareImmediate(result_hi, -0x00200000); |
| 5616 __ b(overflow, LT); | 5633 __ b(overflow, LT); |
| 5617 // Anything in the lower part would make the number bigger than the lower | 5634 // Anything in the lower part would make the number bigger than the lower |
| 5618 // bound, so we are done. | 5635 // bound, so we are done. |
| 5619 } | 5636 } |
| 5620 | 5637 |
| 5621 | 5638 |
| 5622 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { | 5639 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { |
| 5623 const intptr_t kNumInputs = 1; | 5640 const intptr_t kNumInputs = 1; |
| 5624 const intptr_t value_cid = value()->Type()->ToCid(); | 5641 const intptr_t kNumTemps = 1; |
| 5625 const bool needs_writable_input = (value_cid != kMintCid); | |
| 5626 const bool needs_temp = (value_cid != kMintCid); | |
| 5627 const intptr_t kNumTemps = needs_temp ? 1 : 0; | |
| 5628 LocationSummary* summary = | 5642 LocationSummary* summary = |
| 5629 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5643 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5630 summary->set_in(0, needs_writable_input | 5644 summary->set_in(0, Location::RequiresRegister()); |
| 5631 ? Location::WritableRegister() | 5645 summary->set_temp(0, Location::RequiresRegister()); |
| 5632 : Location::RequiresRegister()); | 5646 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 5633 if (needs_temp) { | 5647 Location::RequiresRegister())); |
| 5634 summary->set_temp(0, Location::RequiresRegister()); | |
| 5635 } | |
| 5636 summary->set_out(0, Location::RequiresFpuRegister()); | |
| 5637 return summary; | 5648 return summary; |
| 5638 } | 5649 } |
| 5639 | 5650 |
| 5640 | 5651 |
| 5641 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5652 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5642 const intptr_t value_cid = value()->Type()->ToCid(); | 5653 const intptr_t value_cid = value()->Type()->ToCid(); |
| 5643 const Register value = locs()->in(0).reg(); | 5654 const Register value = locs()->in(0).reg(); |
| 5644 const QRegister result = locs()->out(0).fpu_reg(); | 5655 PairLocation* result_pair = locs()->out(0).AsPairLocation(); |
| 5656 Register result1 = result_pair->At(0).reg(); | |
| 5657 Register result2 = result_pair->At(1).reg(); | |
| 5658 ASSERT(value != result1); | |
| 5659 ASSERT(value != result2); | |
| 5645 | 5660 |
| 5646 __ Comment("UnboxIntegerInstr"); | 5661 __ Comment("UnboxIntegerInstr"); |
| 5647 __ veorq(result, result, result); | |
| 5648 if (value_cid == kMintCid) { | 5662 if (value_cid == kMintCid) { |
| 5649 __ LoadDFromOffset(EvenDRegisterOf(result), value, | 5663 // Load low word. |
| 5650 Mint::value_offset() - kHeapObjectTag); | 5664 __ LoadFromOffset(kWord, |
| 5665 result1, | |
| 5666 value, | |
| 5667 Mint::value_offset() - kHeapObjectTag); | |
| 5668 // Load high word. | |
| 5669 __ LoadFromOffset(kWord, | |
| 5670 result2, | |
| 5671 value, | |
| 5672 Mint::value_offset() - kHeapObjectTag + kWordSize); | |
| 5651 } else if (value_cid == kSmiCid) { | 5673 } else if (value_cid == kSmiCid) { |
| 5652 Register temp = locs()->temp(0).reg(); | 5674 // Load Smi into result1. |
| 5653 __ SmiUntag(value); | 5675 __ mov(result1, ShifterOperand(value)); |
| 5654 // Sign extend value into temp. | 5676 // Untag. |
| 5655 __ Asr(temp, value, 31); | 5677 __ SmiUntag(result1); |
| 5656 __ vmovdrr(EvenDRegisterOf(result), value, temp); | 5678 __ SignFill(result2, result1); |
| 5657 } else { | 5679 } else { |
| 5658 Register temp = locs()->temp(0).reg(); | 5680 Register temp = locs()->temp(0).reg(); |
| 5659 Label* deopt = compiler->AddDeoptStub(deopt_id_, | 5681 Label* deopt = compiler->AddDeoptStub(deopt_id_, |
| 5660 ICData::kDeoptUnboxInteger); | 5682 ICData::kDeoptUnboxInteger); |
| 5661 Label is_smi, done; | 5683 Label is_smi, done; |
| 5662 __ tst(value, ShifterOperand(kSmiTagMask)); | 5684 __ tst(value, ShifterOperand(kSmiTagMask)); |
| 5663 __ b(&is_smi, EQ); | 5685 __ b(&is_smi, EQ); |
| 5664 __ CompareClassId(value, kMintCid, temp); | 5686 __ CompareClassId(value, kMintCid, temp); |
| 5665 __ b(deopt, NE); | 5687 __ b(deopt, NE); |
| 5666 | 5688 |
| 5667 // It's a Mint. | 5689 // It's a Mint. |
| 5668 __ LoadDFromOffset(EvenDRegisterOf(result), value, | 5690 // Load low word. |
| 5669 Mint::value_offset() - kHeapObjectTag); | 5691 __ LoadFromOffset(kWord, |
| 5692 result1, | |
| 5693 value, | |
| 5694 Mint::value_offset() - kHeapObjectTag); | |
| 5695 // Load high word. | |
| 5696 __ LoadFromOffset(kWord, | |
| 5697 result2, | |
| 5698 value, | |
| 5699 Mint::value_offset() - kHeapObjectTag + kWordSize); | |
| 5670 __ b(&done); | 5700 __ b(&done); |
| 5671 | 5701 |
| 5672 // It's a Smi. | 5702 // It's a Smi. |
| 5673 __ Bind(&is_smi); | 5703 __ Bind(&is_smi); |
| 5674 __ SmiUntag(value); | 5704 // Load Smi into result1. |
| 5675 // Sign extend into temp. | 5705 __ mov(result1, ShifterOperand(value)); |
| 5676 __ Asr(temp, value, 31); | 5706 // Untag. |
| 5677 __ vmovdrr(EvenDRegisterOf(result), value, temp); | 5707 __ SmiUntag(result1); |
| 5708 // Sign extend result1 into result2. | |
| 5709 __ SignFill(result2, result1); | |
| 5678 __ Bind(&done); | 5710 __ Bind(&done); |
| 5679 } | 5711 } |
| 5680 } | 5712 } |
| 5681 | 5713 |
| 5682 | 5714 |
| 5683 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { | 5715 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { |
| 5684 const intptr_t kNumInputs = 1; | 5716 const intptr_t kNumInputs = 1; |
| 5685 const intptr_t kNumTemps = 2; | 5717 const intptr_t kNumTemps = 1; |
| 5686 LocationSummary* summary = | 5718 LocationSummary* summary = |
| 5687 new LocationSummary(kNumInputs, | 5719 new LocationSummary(kNumInputs, |
| 5688 kNumTemps, | 5720 kNumTemps, |
| 5689 LocationSummary::kCallOnSlowPath); | 5721 LocationSummary::kCallOnSlowPath); |
| 5690 summary->set_in(0, Location::RequiresFpuRegister()); | 5722 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5723 Location::RequiresRegister())); | |
| 5691 summary->set_temp(0, Location::RequiresRegister()); | 5724 summary->set_temp(0, Location::RequiresRegister()); |
| 5692 summary->set_temp(1, Location::RequiresRegister()); | |
| 5693 summary->set_out(0, Location::RequiresRegister()); | 5725 summary->set_out(0, Location::RequiresRegister()); |
| 5694 return summary; | 5726 return summary; |
| 5695 } | 5727 } |
| 5696 | 5728 |
| 5697 | 5729 |
| 5698 class BoxIntegerSlowPath : public SlowPathCode { | 5730 class BoxIntegerSlowPath : public SlowPathCode { |
| 5699 public: | 5731 public: |
| 5700 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) | 5732 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) |
| 5701 : instruction_(instruction) { } | 5733 : instruction_(instruction) { } |
| 5702 | 5734 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 5724 } | 5756 } |
| 5725 | 5757 |
| 5726 private: | 5758 private: |
| 5727 BoxIntegerInstr* instruction_; | 5759 BoxIntegerInstr* instruction_; |
| 5728 }; | 5760 }; |
| 5729 | 5761 |
| 5730 | 5762 |
| 5731 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5763 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5732 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); | 5764 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); |
| 5733 compiler->AddSlowPathCode(slow_path); | 5765 compiler->AddSlowPathCode(slow_path); |
| 5734 | 5766 PairLocation* value_pair = locs()->in(0).AsPairLocation(); |
| 5767 Register value1 = value_pair->At(0).reg(); | |
|
zra
2014/05/14 18:27:41
optional: lo/hi instead of 1/2 as above
Cutch
2014/05/15 18:26:08
Done.
| |
| 5768 Register value2 = value_pair->At(1).reg(); | |
| 5769 Register tmp = locs()->temp(0).reg(); | |
| 5735 Register out_reg = locs()->out(0).reg(); | 5770 Register out_reg = locs()->out(0).reg(); |
| 5736 QRegister value = locs()->in(0).fpu_reg(); | |
| 5737 DRegister dvalue0 = EvenDRegisterOf(value); | |
| 5738 Register lo = locs()->temp(0).reg(); | |
| 5739 Register hi = locs()->temp(1).reg(); | |
| 5740 | 5771 |
| 5741 // Unboxed operations produce smis or mint-sized values. | 5772 // Unboxed operations produce smis or mint-sized values. |
| 5742 // Check if value fits into a smi. | 5773 // Check if value fits into a smi. |
| 5743 __ Comment("BoxIntegerInstr"); | 5774 __ Comment("BoxIntegerInstr"); |
| 5744 Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi; | 5775 Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi; |
| 5745 __ vmovrrd(lo, hi, dvalue0); | 5776 // Check high word. |
|
zra
2014/05/14 18:27:41
Can you rewrite this to mirror the ia32 implementa
Cutch
2014/05/15 18:26:08
I took a stab at this but kept getting test failur
zra
2014/05/15 18:30:45
sgtm
| |
| 5746 __ CompareImmediate(hi, 0); | 5777 __ CompareImmediate(value2, 0); |
| 5747 __ b(&maybe_pos_smi, EQ); | 5778 __ b(&maybe_pos_smi, EQ); |
| 5748 | 5779 |
| 5749 __ CompareImmediate(hi, -1); | 5780 __ CompareImmediate(value2, -1); |
| 5750 __ b(&maybe_neg_smi, EQ); | 5781 __ b(&maybe_neg_smi, EQ); |
| 5751 __ b(¬_smi); | 5782 __ b(¬_smi); |
| 5752 | 5783 |
| 5753 __ Bind(&maybe_pos_smi); | 5784 __ Bind(&maybe_pos_smi); |
| 5754 __ CompareImmediate(lo, kSmiMax); | 5785 __ CompareImmediate(value1, kSmiMax); |
| 5755 __ b(&is_smi, LS); // unsigned lower or same. | 5786 __ b(&is_smi, LS); // unsigned lower or same. |
| 5756 __ b(¬_smi); | 5787 __ b(¬_smi); |
| 5757 | 5788 |
| 5758 __ Bind(&maybe_neg_smi); | 5789 __ Bind(&maybe_neg_smi); |
| 5759 __ CompareImmediate(lo, 0); | 5790 __ CompareImmediate(value1, 0); |
| 5760 __ b(¬_smi, GE); | 5791 __ b(¬_smi, GE); |
| 5761 __ CompareImmediate(lo, kSmiMin); | 5792 __ CompareImmediate(value1, kSmiMin); |
| 5762 __ b(¬_smi, LT); | 5793 __ b(¬_smi, LT); |
| 5763 | 5794 |
| 5764 // lo is a Smi. Tag it and return. | 5795 // lo is a Smi. Tag it and return. |
| 5765 __ Bind(&is_smi); | 5796 __ Bind(&is_smi); |
| 5766 __ SmiTag(lo); | 5797 __ mov(out_reg, ShifterOperand(value1)); |
| 5767 __ mov(out_reg, ShifterOperand(lo)); | 5798 __ SmiTag(out_reg); |
| 5768 __ b(&done); | 5799 __ b(&done); |
| 5769 | 5800 |
| 5770 // Not a smi. Box it. | 5801 // Not a smi. Box it. |
| 5771 __ Bind(¬_smi); | 5802 __ Bind(¬_smi); |
| 5772 __ TryAllocate( | 5803 __ TryAllocate( |
| 5773 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), | 5804 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), |
| 5774 slow_path->entry_label(), | 5805 slow_path->entry_label(), |
| 5775 out_reg, | 5806 out_reg, |
| 5776 lo); | 5807 tmp); |
| 5777 __ Bind(slow_path->exit_label()); | 5808 __ Bind(slow_path->exit_label()); |
| 5778 __ StoreDToOffset(dvalue0, out_reg, Mint::value_offset() - kHeapObjectTag); | 5809 __ StoreToOffset(kWord, |
| 5810 value1, | |
| 5811 out_reg, | |
| 5812 Mint::value_offset() - kHeapObjectTag); | |
| 5813 __ StoreToOffset(kWord, | |
| 5814 value2, | |
| 5815 out_reg, | |
| 5816 Mint::value_offset() - kHeapObjectTag + kWordSize); | |
| 5779 __ Bind(&done); | 5817 __ Bind(&done); |
| 5780 } | 5818 } |
| 5781 | 5819 |
| 5782 | 5820 |
| 5783 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { | 5821 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { |
| 5784 const intptr_t kNumInputs = 2; | 5822 const intptr_t kNumInputs = 2; |
| 5785 const intptr_t kNumTemps = | 5823 const intptr_t kNumTemps = 0; |
| 5786 FLAG_throw_on_javascript_int_overflow ? 2 : 0; | |
| 5787 LocationSummary* summary = | 5824 LocationSummary* summary = |
| 5788 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5825 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5789 summary->set_in(0, Location::RequiresFpuRegister()); | 5826 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5790 summary->set_in(1, Location::RequiresFpuRegister()); | 5827 Location::RequiresRegister())); |
| 5791 if (FLAG_throw_on_javascript_int_overflow) { | 5828 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 5792 summary->set_temp(0, Location::RequiresRegister()); | 5829 Location::RequiresRegister())); |
| 5793 summary->set_temp(1, Location::RequiresRegister()); | 5830 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 5794 } | 5831 Location::RequiresRegister())); |
| 5795 if ((op_kind() == Token::kADD) || (op_kind() == Token::kSUB)) { | |
| 5796 // Need another temp for checking for overflow. | |
| 5797 summary->AddTemp(Location::RequiresFpuRegister()); | |
| 5798 summary->AddTemp(Location::FpuRegisterLocation(Q7)); | |
| 5799 } | |
| 5800 summary->set_out(0, Location::RequiresFpuRegister()); | |
| 5801 return summary; | 5832 return summary; |
| 5802 } | 5833 } |
| 5803 | 5834 |
| 5804 | 5835 |
| 5805 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5836 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5806 QRegister left = locs()->in(0).fpu_reg(); | 5837 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| 5807 QRegister right = locs()->in(1).fpu_reg(); | 5838 Register left1 = left_pair->At(0).reg(); |
| 5808 QRegister out = locs()->out(0).fpu_reg(); | 5839 Register left2 = left_pair->At(1).reg(); |
| 5840 PairLocation* right_pair = locs()->in(1).AsPairLocation(); | |
| 5841 Register right1 = right_pair->At(0).reg(); | |
| 5842 Register right2 = right_pair->At(1).reg(); | |
| 5843 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | |
| 5844 Register out1 = out_pair->At(0).reg(); | |
| 5845 Register out2 = out_pair->At(1).reg(); | |
| 5809 | 5846 |
| 5810 Label* deopt = NULL; | 5847 Label* deopt = NULL; |
| 5811 if (FLAG_throw_on_javascript_int_overflow) { | 5848 if (FLAG_throw_on_javascript_int_overflow) { |
| 5812 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5849 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 5813 } | 5850 } |
| 5814 switch (op_kind()) { | 5851 switch (op_kind()) { |
| 5815 case Token::kBIT_AND: __ vandq(out, left, right); break; | 5852 case Token::kBIT_AND: { |
| 5816 case Token::kBIT_OR: __ vorrq(out, left, right); break; | 5853 __ and_(out1, left1, ShifterOperand(right1)); |
| 5817 case Token::kBIT_XOR: __ veorq(out, left, right); break; | 5854 __ and_(out2, left2, ShifterOperand(right2)); |
| 5855 } | |
| 5856 break; | |
| 5857 case Token::kBIT_OR: { | |
| 5858 __ orr(out1, left1, ShifterOperand(right1)); | |
| 5859 __ orr(out2, left2, ShifterOperand(right2)); | |
| 5860 } | |
| 5861 break; | |
| 5862 case Token::kBIT_XOR: { | |
| 5863 __ eor(out1, left1, ShifterOperand(right1)); | |
| 5864 __ eor(out2, left2, ShifterOperand(right2)); | |
| 5865 } | |
| 5866 break; | |
| 5818 case Token::kADD: | 5867 case Token::kADD: |
| 5819 case Token::kSUB: { | 5868 case Token::kSUB: { |
| 5820 const intptr_t tmpidx = FLAG_throw_on_javascript_int_overflow ? 2 : 0; | |
| 5821 QRegister tmp = locs()->temp(tmpidx).fpu_reg(); | |
| 5822 QRegister ro = locs()->temp(tmpidx + 1).fpu_reg(); | |
| 5823 ASSERT(ro == Q7); | |
| 5824 if (!FLAG_throw_on_javascript_int_overflow) { | 5869 if (!FLAG_throw_on_javascript_int_overflow) { |
| 5825 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5870 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 5826 } | 5871 } |
| 5827 if (op_kind() == Token::kADD) { | 5872 if (op_kind() == Token::kADD) { |
| 5828 __ vaddqi(kWordPair, out, left, right); | 5873 __ adds(out1, left1, ShifterOperand(right1)); |
| 5874 __ adcs(out2, left2, ShifterOperand(right2)); | |
| 5829 } else { | 5875 } else { |
| 5830 ASSERT(op_kind() == Token::kSUB); | 5876 ASSERT(op_kind() == Token::kSUB); |
| 5831 __ vsubqi(kWordPair, out, left, right); | 5877 __ subs(out1, left1, ShifterOperand(right1)); |
| 5878 __ sbcs(out2, left2, ShifterOperand(right2)); | |
| 5832 } | 5879 } |
| 5833 __ veorq(ro, out, left); | 5880 // Deopt on overflow. |
| 5834 __ veorq(tmp, left, right); | 5881 __ b(deopt, VS); |
| 5835 __ vandq(ro, tmp, ro); | |
| 5836 __ vmovrs(TMP, OddSRegisterOf(EvenDRegisterOf(ro))); | |
| 5837 // If TMP < 0, there was overflow. | |
| 5838 __ cmp(TMP, ShifterOperand(0)); | |
| 5839 __ b(deopt, LT); | |
| 5840 break; | 5882 break; |
| 5841 } | 5883 } |
| 5842 default: UNREACHABLE(); break; | 5884 default: |
| 5885 UNREACHABLE(); | |
| 5886 break; | |
| 5843 } | 5887 } |
| 5844 if (FLAG_throw_on_javascript_int_overflow) { | 5888 if (FLAG_throw_on_javascript_int_overflow) { |
| 5845 Register tmp1 = locs()->temp(0).reg(); | 5889 EmitJavascriptIntOverflowCheck(compiler, deopt, out1, out2); |
| 5846 Register tmp2 = locs()->temp(1).reg(); | |
| 5847 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2); | |
| 5848 } | 5890 } |
| 5849 } | 5891 } |
| 5850 | 5892 |
| 5851 | 5893 |
| 5852 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { | 5894 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { |
| 5853 const intptr_t kNumInputs = 2; | 5895 const intptr_t kNumInputs = 2; |
| 5854 const intptr_t kNumTemps = | 5896 const intptr_t kNumTemps = 1; |
| 5855 FLAG_throw_on_javascript_int_overflow ? 2 : 1; | |
| 5856 LocationSummary* summary = | 5897 LocationSummary* summary = |
| 5857 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5898 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5858 summary->set_in(0, Location::RequiresFpuRegister()); | 5899 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5900 Location::RequiresRegister())); | |
| 5859 summary->set_in(1, Location::WritableRegister()); | 5901 summary->set_in(1, Location::WritableRegister()); |
| 5860 summary->set_temp(0, Location::FpuRegisterLocation(Q7)); | 5902 summary->set_temp(0, Location::RequiresRegister()); |
| 5861 if (FLAG_throw_on_javascript_int_overflow) { | 5903 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 5862 summary->set_temp(1, Location::RequiresRegister()); | 5904 Location::RequiresRegister())); |
| 5863 } | |
| 5864 summary->set_out(0, Location::RequiresFpuRegister()); | |
| 5865 return summary; | 5905 return summary; |
| 5866 } | 5906 } |
| 5867 | 5907 |
| 5868 | 5908 |
| 5869 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5909 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5870 QRegister value = locs()->in(0).fpu_reg(); | 5910 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| 5911 Register left1 = left_pair->At(0).reg(); | |
| 5912 Register left2 = left_pair->At(1).reg(); | |
| 5871 Register shift = locs()->in(1).reg(); | 5913 Register shift = locs()->in(1).reg(); |
| 5872 QRegister temp = locs()->temp(0).fpu_reg(); | 5914 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 5873 ASSERT(temp == Q7); | 5915 Register out1 = out_pair->At(0).reg(); |
| 5874 QRegister out = locs()->out(0).fpu_reg(); | 5916 Register out2 = out_pair->At(1).reg(); |
| 5875 DRegister dtemp0 = EvenDRegisterOf(temp); | 5917 Register temp = locs()->temp(0).reg(); |
| 5876 SRegister stemp0 = EvenSRegisterOf(dtemp0); | |
| 5877 SRegister stemp1 = OddSRegisterOf(dtemp0); | |
| 5878 | 5918 |
| 5879 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); | 5919 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
| 5880 Label done; | 5920 Label done, early_out; |
| 5881 | 5921 |
| 5922 // Early out if shift is 0. | |
| 5882 __ CompareImmediate(shift, 0); | 5923 __ CompareImmediate(shift, 0); |
| 5883 __ vmovq(out, value); | 5924 __ b(&early_out, EQ); |
| 5884 __ b(&done, EQ); | 5925 |
| 5926 // Untag shift count. | |
| 5885 __ SmiUntag(shift); | 5927 __ SmiUntag(shift); |
| 5886 | 5928 |
| 5887 // vshlq takes the shift value from low byte. Deopt if shift is | 5929 // Deopt if shift is negative. |
| 5888 // outside of [0, 63]. | 5930 __ CompareImmediate(shift, 1); |
| 5889 __ CompareImmediate(shift, 63); | |
| 5890 __ b(deopt, GT); | |
| 5891 __ CompareImmediate(shift, 0); | |
| 5892 __ b(deopt, LT); | 5931 __ b(deopt, LT); |
| 5893 | 5932 |
| 5894 __ veorq(temp, temp, temp); // Zero out temp. | 5933 // Deopt if shift is larger than 32. |
|
zra
2014/05/14 18:27:41
Are there funky things that happen for >= 32 as pa
Cutch
2014/05/15 18:26:08
Done.
| |
| 5934 __ CompareImmediate(shift, 32); | |
| 5935 __ b(deopt, GT); | |
| 5936 | |
| 5895 switch (op_kind()) { | 5937 switch (op_kind()) { |
| 5896 case Token::kSHR: { | 5938 case Token::kSHR: { |
| 5897 __ rsb(shift, shift, ShifterOperand(0)); // Negate shift. | 5939 /* |
| 5898 __ vmovsr(stemp0, shift); // Move the shift into the low S register. | 5940 * Perform right shift, in pseudo C: |
| 5899 __ vshlqi(kWordPair, out, value, temp); | 5941 * temp = 32 - N; |
| 5942 * temp = left2 <<L temp; | |
| 5943 * out1 = temp | (left1 L>> N); | |
| 5944 * out2 = left2 A>> N; | |
| 5945 */ | |
| 5946 __ rsb(temp, shift, ShifterOperand(32)); | |
| 5947 __ mov(temp, ShifterOperand(left2, LSL, temp)); | |
| 5948 __ orr(out1, temp, ShifterOperand(left1, LSR, shift)); | |
| 5949 __ mov(out2, ShifterOperand(left2, ASR, shift)); | |
| 5950 // Finished. | |
| 5951 __ b(&done); | |
| 5900 break; | 5952 break; |
| 5901 } | 5953 } |
| 5902 case Token::kSHL: { | 5954 case Token::kSHL: { |
| 5903 __ vmovsr(stemp0, shift); // Move the shift into the low S register. | 5955 /* |
| 5904 __ vshlqu(kWordPair, out, value, temp); | 5956 * Perform left shift, in pseudo C: |
| 5957 * temp = 32 - N; | |
| 5958 * out2 = left2 <<L shift; | |
| 5959 * out2 = out2 | (left1 L>> temp); | |
| 5960 * out1 = left1 <<L shift; | |
| 5961 */ | |
| 5962 __ rsb(temp, shift, ShifterOperand(32)); | |
| 5963 __ mov(out2, ShifterOperand(left2, LSL, shift)); | |
| 5964 __ orr(out2, out2, ShifterOperand(left1, LSR, temp)); | |
| 5965 __ mov(out1, ShifterOperand(left1, LSL, shift)); | |
| 5905 | 5966 |
| 5906 // check for overflow by shifting back and comparing. | 5967 // Check for overflow. |
| 5907 __ rsb(shift, shift, ShifterOperand(0)); | 5968 |
| 5908 __ vmovsr(stemp0, shift); | 5969 // Copy high word from output. |
| 5909 __ vshlqi(kWordPair, temp, out, temp); | 5970 __ mov(temp, ShifterOperand(out2)); |
| 5910 __ vceqqi(kWord, temp, temp, value); | 5971 // Shift copy right. |
| 5911 // Low 64 bits of temp should be all 1's, otherwise temp != value and | 5972 __ Asr(temp, temp, shift); |
| 5912 // we deopt. | 5973 // Compare with high word from input. |
| 5913 __ vmovrs(shift, stemp0); | 5974 __ cmp(temp, ShifterOperand(left2)); |
| 5914 __ CompareImmediate(shift, -1); | 5975 // Overflow if they aren't equal. |
| 5915 __ b(deopt, NE); | 5976 __ b(deopt, NE); |
| 5916 __ vmovrs(shift, stemp1); | 5977 // Finished. |
| 5917 __ CompareImmediate(shift, -1); | 5978 __ b(&done); |
| 5918 __ b(deopt, NE); | |
| 5919 break; | 5979 break; |
| 5920 } | 5980 } |
| 5921 default: | 5981 default: |
| 5922 UNREACHABLE(); | 5982 UNREACHABLE(); |
| 5923 break; | 5983 break; |
| 5924 } | 5984 } |
| 5925 | 5985 |
| 5986 __ Bind(&early_out); | |
| 5987 __ mov(out1, ShifterOperand(left1)); | |
| 5988 __ mov(out2, ShifterOperand(left2)); | |
| 5989 | |
| 5926 __ Bind(&done); | 5990 __ Bind(&done); |
| 5927 if (FLAG_throw_on_javascript_int_overflow) { | 5991 if (FLAG_throw_on_javascript_int_overflow) { |
| 5928 Register tmp1 = locs()->in(1).reg(); | 5992 EmitJavascriptIntOverflowCheck(compiler, deopt, out1, out2); |
| 5929 Register tmp2 = locs()->temp(1).reg(); | |
| 5930 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2); | |
| 5931 } | 5993 } |
| 5932 } | 5994 } |
| 5933 | 5995 |
| 5934 | 5996 |
| 5935 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { | 5997 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { |
| 5936 const intptr_t kNumInputs = 1; | 5998 const intptr_t kNumInputs = 1; |
| 5937 const intptr_t kNumTemps = | 5999 const intptr_t kNumTemps = 0; |
| 5938 FLAG_throw_on_javascript_int_overflow ? 2 : 0; | |
| 5939 LocationSummary* summary = | 6000 LocationSummary* summary = |
| 5940 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6001 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5941 summary->set_in(0, Location::RequiresFpuRegister()); | 6002 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5942 summary->set_out(0, Location::RequiresFpuRegister()); | 6003 Location::RequiresRegister())); |
| 5943 if (FLAG_throw_on_javascript_int_overflow) { | 6004 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 5944 summary->set_temp(0, Location::RequiresRegister()); | 6005 Location::RequiresRegister())); |
| 5945 summary->set_temp(1, Location::RequiresRegister()); | |
| 5946 } | |
| 5947 return summary; | 6006 return summary; |
| 5948 } | 6007 } |
| 5949 | 6008 |
| 5950 | 6009 |
| 5951 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6010 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5952 ASSERT(op_kind() == Token::kBIT_NOT); | 6011 ASSERT(op_kind() == Token::kBIT_NOT); |
| 5953 QRegister value = locs()->in(0).fpu_reg(); | 6012 |
| 5954 QRegister out = locs()->out(0).fpu_reg(); | 6013 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| 6014 Register left1 = left_pair->At(0).reg(); | |
| 6015 Register left2 = left_pair->At(1).reg(); | |
| 6016 | |
| 6017 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | |
| 6018 Register out1 = out_pair->At(0).reg(); | |
| 6019 Register out2 = out_pair->At(1).reg(); | |
| 6020 | |
| 5955 Label* deopt = NULL; | 6021 Label* deopt = NULL; |
| 6022 | |
| 5956 if (FLAG_throw_on_javascript_int_overflow) { | 6023 if (FLAG_throw_on_javascript_int_overflow) { |
| 5957 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); | 6024 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); |
| 5958 } | 6025 } |
| 5959 __ vmvnq(out, value); | 6026 __ mvn(out1, ShifterOperand(left1)); |
| 6027 __ mvn(out2, ShifterOperand(left2)); | |
| 5960 if (FLAG_throw_on_javascript_int_overflow) { | 6028 if (FLAG_throw_on_javascript_int_overflow) { |
| 5961 Register tmp1 = locs()->temp(0).reg(); | 6029 EmitJavascriptIntOverflowCheck(compiler, deopt, out1, out2); |
| 5962 Register tmp2 = locs()->temp(1).reg(); | |
| 5963 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2); | |
| 5964 } | 6030 } |
| 5965 } | 6031 } |
| 5966 | 6032 |
| 5967 | 6033 |
| 5968 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { | 6034 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { |
| 5969 return new LocationSummary(0, 0, LocationSummary::kCall); | 6035 return new LocationSummary(0, 0, LocationSummary::kCall); |
| 5970 } | 6036 } |
| 5971 | 6037 |
| 5972 | 6038 |
| 5973 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6039 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6163 compiler->GenerateCall(token_pos(), | 6229 compiler->GenerateCall(token_pos(), |
| 6164 &label, | 6230 &label, |
| 6165 PcDescriptors::kOther, | 6231 PcDescriptors::kOther, |
| 6166 locs()); | 6232 locs()); |
| 6167 __ Drop(ArgumentCount()); // Discard arguments. | 6233 __ Drop(ArgumentCount()); // Discard arguments. |
| 6168 } | 6234 } |
| 6169 | 6235 |
| 6170 } // namespace dart | 6236 } // namespace dart |
| 6171 | 6237 |
| 6172 #endif // defined TARGET_ARCH_ARM | 6238 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |