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

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

Issue 206503005: Implements unboxed Mints on ARM. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 default: 325 default:
326 UNREACHABLE(); 326 UNREACHABLE();
327 return VS; 327 return VS;
328 } 328 }
329 } 329 }
330 330
331 331
332 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { 332 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const {
333 const intptr_t kNumInputs = 2; 333 const intptr_t kNumInputs = 2;
334 if (operation_cid() == kMintCid) { 334 if (operation_cid() == kMintCid) {
335 const intptr_t kNumTemps = 1; 335 const intptr_t kNumTemps = 3;
336 LocationSummary* locs = 336 LocationSummary* locs =
337 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 337 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
338 locs->set_in(0, Location::RequiresFpuRegister()); 338 locs->set_in(0, Location::RequiresFpuRegister());
339 locs->set_in(1, Location::RequiresFpuRegister()); 339 locs->set_in(1, Location::RequiresFpuRegister());
340 locs->set_temp(0, Location::RequiresRegister()); 340 locs->set_temp(0, Location::RequiresFpuRegister());
341 locs->set_temp(1, Location::RequiresRegister());
342 locs->set_temp(2, Location::RequiresRegister());
341 locs->set_out(Location::RequiresRegister()); 343 locs->set_out(Location::RequiresRegister());
342 return locs; 344 return locs;
343 } 345 }
344 if (operation_cid() == kDoubleCid) { 346 if (operation_cid() == kDoubleCid) {
345 const intptr_t kNumTemps = 0; 347 const intptr_t kNumTemps = 0;
346 LocationSummary* locs = 348 LocationSummary* locs =
347 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 349 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
348 locs->set_in(0, Location::RequiresFpuRegister()); 350 locs->set_in(0, Location::RequiresFpuRegister());
349 locs->set_in(1, Location::RequiresFpuRegister()); 351 locs->set_in(1, Location::RequiresFpuRegister());
350 locs->set_out(Location::RequiresRegister()); 352 locs->set_out(Location::RequiresRegister());
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 true_condition = FlipCondition(true_condition); 441 true_condition = FlipCondition(true_condition);
440 } else if (right.IsConstant()) { 442 } else if (right.IsConstant()) {
441 __ CompareObject(left.reg(), right.constant()); 443 __ CompareObject(left.reg(), right.constant());
442 } else { 444 } else {
443 __ cmp(left.reg(), ShifterOperand(right.reg())); 445 __ cmp(left.reg(), ShifterOperand(right.reg()));
444 } 446 }
445 return true_condition; 447 return true_condition;
446 } 448 }
447 449
448 450
451 static Condition TokenKindToMintCondition(Token::Kind kind) {
452 switch (kind) {
453 case Token::kEQ: return EQ;
454 case Token::kNE: return NE;
455 case Token::kLT: return LT;
456 case Token::kGT: return GT;
457 case Token::kLTE: return LE;
458 case Token::kGTE: return GE;
459 default:
460 UNREACHABLE();
461 return VS;
462 }
463 }
464
465
466 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
467 LocationSummary* locs,
468 Token::Kind kind) {
469 ASSERT(Token::IsEqualityOperator(kind));
470 QRegister left = locs->in(0).fpu_reg();
471 QRegister right = locs->in(1).fpu_reg();
472 QRegister tmpq = locs->temp(0).fpu_reg();
473 Register tmp_lo = locs->temp(1).reg();
474 Register tmp_hi = locs->temp(2).reg();
475
476 __ vceqqi(kWord, tmpq, left, right);
477 __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(tmpq));
478 // tmp_lo and tmp_hi must both be 0xffffffff.
479 __ and_(tmp_lo, tmp_lo, ShifterOperand(tmp_hi));
480
481 Condition true_condition = TokenKindToMintCondition(kind);
482 __ CompareImmediate(tmp_lo, 0xffffffff);
483 return true_condition;
484 }
485
486
487 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
488 LocationSummary* locs,
489 Token::Kind kind) {
490 QRegister left = locs->in(0).fpu_reg();
491 QRegister right = locs->in(1).fpu_reg();
492 DRegister dleft0 = EvenDRegisterOf(left);
493 DRegister dright0 = EvenDRegisterOf(right);
494 SRegister sleft0 = EvenSRegisterOf(dleft0);
495 SRegister sleft1 = OddSRegisterOf(dleft0);
496 SRegister sright0 = EvenSRegisterOf(dright0);
497 SRegister sright1 = OddSRegisterOf(dright0);
498
499 Register tmp_left = locs->temp(0).reg();
500 Register tmp_right = locs->temp(1).reg();
501
502 // 64-bit comparison
503 Condition hi_true_cond, hi_false_cond, lo_false_cond;
504 switch (kind) {
505 case Token::kLT:
506 case Token::kLTE:
507 hi_true_cond = LT;
508 hi_false_cond = GT;
509 lo_false_cond = (kind == Token::kLT) ? CS : HI;
510 break;
511 case Token::kGT:
512 case Token::kGTE:
513 hi_true_cond = GT;
514 hi_false_cond = LT;
515 lo_false_cond = (kind == Token::kGT) ? LS : CC;
516 break;
517 default:
518 UNREACHABLE();
519 hi_true_cond = hi_false_cond = lo_false_cond = VS;
520 }
521
522 Label is_true, is_false, done;
523 __ vmovrs(tmp_left, sleft1);
524 __ vmovrs(tmp_right, sright1);
525 __ cmp(tmp_left, ShifterOperand(tmp_right));
526 __ b(&is_false, hi_false_cond);
527 __ b(&is_true, hi_true_cond);
528
529 __ vmovrs(tmp_left, sleft0);
530 __ vmovrs(tmp_right, sright0);
531 __ cmp(tmp_left, ShifterOperand(tmp_right));
532 __ b(&is_false, lo_false_cond);
533 // Else is true.
534 __ b(&is_true);
535
536 __ Bind(&is_false);
537 __ LoadImmediate(tmp_left, 0);
538 __ b(&done);
539 __ Bind(&is_true);
540 __ LoadImmediate(tmp_left, 1);
541 __ Bind(&done);
542 return NegateCondition(lo_false_cond);
543 }
544
545
449 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 546 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
450 switch (kind) { 547 switch (kind) {
451 case Token::kEQ: return EQ; 548 case Token::kEQ: return EQ;
452 case Token::kNE: return NE; 549 case Token::kNE: return NE;
453 case Token::kLT: return LT; 550 case Token::kLT: return LT;
454 case Token::kGT: return GT; 551 case Token::kGT: return GT;
455 case Token::kLTE: return LE; 552 case Token::kLTE: return LE;
456 case Token::kGTE: return GE; 553 case Token::kGTE: return GE;
457 default: 554 default:
458 UNREACHABLE(); 555 UNREACHABLE();
(...skipping 13 matching lines...) Expand all
472 __ vmstat(); 569 __ vmstat();
473 Condition true_condition = TokenKindToDoubleCondition(kind); 570 Condition true_condition = TokenKindToDoubleCondition(kind);
474 return true_condition; 571 return true_condition;
475 } 572 }
476 573
477 574
478 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 575 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
479 BranchLabels labels) { 576 BranchLabels labels) {
480 if (operation_cid() == kSmiCid) { 577 if (operation_cid() == kSmiCid) {
481 return EmitSmiComparisonOp(compiler, locs(), kind()); 578 return EmitSmiComparisonOp(compiler, locs(), kind());
579 } else if (operation_cid() == kMintCid) {
580 return EmitUnboxedMintEqualityOp(compiler, locs(), kind());
482 } else { 581 } else {
483 ASSERT(operation_cid() == kDoubleCid); 582 ASSERT(operation_cid() == kDoubleCid);
484 return EmitDoubleComparisonOp(compiler, locs(), kind()); 583 return EmitDoubleComparisonOp(compiler, locs(), kind());
485 } 584 }
486 } 585 }
487 586
488 587
489 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 588 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
490 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 589 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
491 590
492 // The ARM code does not use true- and false-labels here. 591 // The ARM code does not use true- and false-labels here.
493 BranchLabels labels = { NULL, NULL, NULL }; 592 BranchLabels labels = { NULL, NULL, NULL };
494 Condition true_condition = EmitComparisonCode(compiler, labels); 593 Condition true_condition = EmitComparisonCode(compiler, labels);
495 594
496 Register result = locs()->out().reg(); 595 Register result = locs()->out().reg();
497 if (operation_cid() == kSmiCid) { 596 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) {
498 __ LoadObject(result, Bool::True(), true_condition); 597 __ LoadObject(result, Bool::True(), true_condition);
499 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); 598 __ LoadObject(result, Bool::False(), NegateCondition(true_condition));
500 } else { 599 } else {
501 ASSERT(operation_cid() == kDoubleCid); 600 ASSERT(operation_cid() == kDoubleCid);
502 Label done; 601 Label done;
503 __ LoadObject(result, Bool::False()); 602 __ LoadObject(result, Bool::False());
504 if (true_condition != NE) { 603 if (true_condition != NE) {
505 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. 604 __ b(&done, VS); // x == NaN -> false, x != NaN -> true.
506 } 605 }
507 __ LoadObject(result, Bool::True(), true_condition); 606 __ LoadObject(result, Bool::True(), true_condition);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 : Location::RegisterOrConstant(right())); 701 : Location::RegisterOrConstant(right()));
603 summary->set_out(Location::RequiresRegister()); 702 summary->set_out(Location::RequiresRegister());
604 return summary; 703 return summary;
605 } 704 }
606 705
607 706
608 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 707 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
609 BranchLabels labels) { 708 BranchLabels labels) {
610 if (operation_cid() == kSmiCid) { 709 if (operation_cid() == kSmiCid) {
611 return EmitSmiComparisonOp(compiler, locs(), kind()); 710 return EmitSmiComparisonOp(compiler, locs(), kind());
711 } else if (operation_cid() == kMintCid) {
712 return EmitUnboxedMintComparisonOp(compiler, locs(), kind());
612 } else { 713 } else {
613 ASSERT(operation_cid() == kDoubleCid); 714 ASSERT(operation_cid() == kDoubleCid);
614 return EmitDoubleComparisonOp(compiler, locs(), kind()); 715 return EmitDoubleComparisonOp(compiler, locs(), kind());
615 } 716 }
616 } 717 }
617 718
618 719
619 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 720 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
620 // The ARM code does not use true- and false-labels here. 721 // The ARM code does not use true- and false-labels here.
621 BranchLabels labels = { NULL, NULL, NULL }; 722 BranchLabels labels = { NULL, NULL, NULL };
622 Condition true_condition = EmitComparisonCode(compiler, labels); 723 Condition true_condition = EmitComparisonCode(compiler, labels);
623 724
624 Register result = locs()->out().reg(); 725 Register result = locs()->out().reg();
625 if (operation_cid() == kSmiCid) { 726 if (operation_cid() == kSmiCid) {
626 __ LoadObject(result, Bool::True(), true_condition); 727 __ LoadObject(result, Bool::True(), true_condition);
627 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); 728 __ LoadObject(result, Bool::False(), NegateCondition(true_condition));
729 } else if (operation_cid() == kMintCid) {
730 Register cr = locs()->temp(0).reg();
731 __ LoadObject(result, Bool::True());
732 __ CompareImmediate(cr, 1);
733 __ LoadObject(result, Bool::False(), NE);
628 } else { 734 } else {
629 ASSERT(operation_cid() == kDoubleCid); 735 ASSERT(operation_cid() == kDoubleCid);
630 Label done; 736 Label done;
631 __ LoadObject(result, Bool::False()); 737 __ LoadObject(result, Bool::False());
632 if (true_condition != NE) { 738 if (true_condition != NE) {
633 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. 739 __ b(&done, VS); // x == NaN -> false, x != NaN -> true.
634 } 740 }
635 __ LoadObject(result, Bool::True(), true_condition); 741 __ LoadObject(result, Bool::True(), true_condition);
636 __ Bind(&done); 742 __ Bind(&done);
637 } 743 }
638 } 744 }
639 745
640 746
641 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, 747 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
642 BranchInstr* branch) { 748 BranchInstr* branch) {
643 BranchLabels labels = compiler->CreateBranchLabels(branch); 749 BranchLabels labels = compiler->CreateBranchLabels(branch);
644 Condition true_condition = EmitComparisonCode(compiler, labels); 750 Condition true_condition = EmitComparisonCode(compiler, labels);
645 751
646 if (operation_cid() == kDoubleCid) { 752 if (operation_cid() == kSmiCid) {
753 EmitBranchOnCondition(compiler, true_condition, labels);
754 } else if (operation_cid() == kMintCid) {
755 Register result = locs()->temp(0).reg();
756 __ CompareImmediate(result, 1);
757 __ b(labels.true_label, EQ);
758 __ b(labels.false_label, NE);
759 } else if (operation_cid() == kDoubleCid) {
647 Label* nan_result = (true_condition == NE) ? 760 Label* nan_result = (true_condition == NE) ?
648 labels.true_label : labels.false_label; 761 labels.true_label : labels.false_label;
649 __ b(nan_result, VS); 762 __ b(nan_result, VS);
763 EmitBranchOnCondition(compiler, true_condition, labels);
650 } 764 }
651 EmitBranchOnCondition(compiler, true_condition, labels);
652 } 765 }
653 766
654 767
655 LocationSummary* NativeCallInstr::MakeLocationSummary(bool opt) const { 768 LocationSummary* NativeCallInstr::MakeLocationSummary(bool opt) const {
656 const intptr_t kNumInputs = 0; 769 const intptr_t kNumInputs = 0;
657 const intptr_t kNumTemps = 3; 770 const intptr_t kNumTemps = 3;
658 LocationSummary* locs = 771 LocationSummary* locs =
659 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 772 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
660 locs->set_temp(0, Location::RegisterLocation(R1)); 773 locs->set_temp(0, Location::RegisterLocation(R1));
661 locs->set_temp(1, Location::RegisterLocation(R2)); 774 locs->set_temp(1, Location::RegisterLocation(R2));
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 element_address = Address(array, index.reg(), LSL, 0); 1077 element_address = Address(array, index.reg(), LSL, 0);
965 1078
966 if ((representation() == kUnboxedDouble) || 1079 if ((representation() == kUnboxedDouble) ||
967 (representation() == kUnboxedMint) || 1080 (representation() == kUnboxedMint) ||
968 (representation() == kUnboxedFloat32x4) || 1081 (representation() == kUnboxedFloat32x4) ||
969 (representation() == kUnboxedInt32x4) || 1082 (representation() == kUnboxedInt32x4) ||
970 (representation() == kUnboxedFloat64x2)) { 1083 (representation() == kUnboxedFloat64x2)) {
971 QRegister result = locs()->out().fpu_reg(); 1084 QRegister result = locs()->out().fpu_reg();
972 DRegister dresult0 = EvenDRegisterOf(result); 1085 DRegister dresult0 = EvenDRegisterOf(result);
973 DRegister dresult1 = OddDRegisterOf(result); 1086 DRegister dresult1 = OddDRegisterOf(result);
1087 Register idx = index.reg();
974 switch (class_id()) { 1088 switch (class_id()) {
975 case kTypedDataInt32ArrayCid: 1089 case kTypedDataInt32ArrayCid:
976 UNIMPLEMENTED(); 1090 __ veorq(result, result, result);
1091 __ ldr(TMP, element_address);
1092 // Re-use the index register so we don't have to require a low-numbered
1093 // Q register.
1094 __ eor(idx, idx, ShifterOperand(idx));
regis 2014/03/20 20:39:35 Wouldn't __ LoadImmediate(idx, 0) be clearer?
zra 2014/03/20 23:49:25 Done.
1095 __ cmp(TMP, ShifterOperand(0));
1096 // Sign-extend if the element is < 0;
1097 __ LoadImmediate(idx, -1, LT);
regis 2014/03/20 20:39:35 Instead of the 3 instructions above (including a b
zra 2014/03/20 23:49:25 Done.
1098 __ vmovdrr(dresult0, TMP, idx);
977 break; 1099 break;
978 case kTypedDataUint32ArrayCid: 1100 case kTypedDataUint32ArrayCid:
979 UNIMPLEMENTED(); 1101 __ veorq(result, result, result);
1102 __ ldr(TMP, element_address);
1103 // Re-use the index register so we don't have to require a low-numbered
1104 // Q register.
1105 __ eor(idx, idx, ShifterOperand(idx));
regis 2014/03/20 20:39:35 Wouldn't __ LoadImmediate(idx, 0) be clearer?
zra 2014/03/20 23:49:25 Done.
1106 __ vmovdrr(dresult0, TMP, idx);
980 break; 1107 break;
981 case kTypedDataFloat32ArrayCid: 1108 case kTypedDataFloat32ArrayCid:
982 // Load single precision float. 1109 // Load single precision float.
983 // vldrs does not support indexed addressing. 1110 // vldrs does not support indexed addressing.
984 __ add(index.reg(), index.reg(), ShifterOperand(array)); 1111 __ add(index.reg(), index.reg(), ShifterOperand(array));
985 element_address = Address(index.reg(), 0); 1112 element_address = Address(index.reg(), 0);
986 __ vldrs(EvenSRegisterOf(dresult0), element_address); 1113 __ vldrs(EvenSRegisterOf(dresult0), element_address);
987 break; 1114 break;
988 case kTypedDataFloat64ArrayCid: 1115 case kTypedDataFloat64ArrayCid:
989 // vldrd does not support indexed addressing. 1116 // vldrd does not support indexed addressing.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1034 // Verify that the signed value in 'result' can fit inside a Smi. 1161 // Verify that the signed value in 'result' can fit inside a Smi.
1035 __ CompareImmediate(result, 0xC0000000); 1162 __ CompareImmediate(result, 0xC0000000);
1036 __ b(deopt, MI); 1163 __ b(deopt, MI);
1037 __ SmiTag(result); 1164 __ SmiTag(result);
1038 } 1165 }
1039 break; 1166 break;
1040 case kTypedDataUint32ArrayCid: { 1167 case kTypedDataUint32ArrayCid: {
1041 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptUint32Load); 1168 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptUint32Load);
1042 __ ldr(result, element_address); 1169 __ ldr(result, element_address);
1043 // Verify that the unsigned value in 'result' can fit inside a Smi. 1170 // Verify that the unsigned value in 'result' can fit inside a Smi.
1044 __ tst(result, ShifterOperand(0xC0000000)); 1171 __ TestImmediate(result, 0xC0000000);
1045 __ b(deopt, NE); 1172 __ b(deopt, NE);
1046 __ SmiTag(result); 1173 __ SmiTag(result);
1047 } 1174 }
1048 break; 1175 break;
1049 default: 1176 default:
1050 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); 1177 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid));
1051 __ ldr(result, element_address); 1178 __ ldr(result, element_address);
1052 break; 1179 break;
1053 } 1180 }
1054 } 1181 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 : Location::RegisterOrConstant(value())); 1234 : Location::RegisterOrConstant(value()));
1108 break; 1235 break;
1109 case kExternalTypedDataUint8ArrayCid: 1236 case kExternalTypedDataUint8ArrayCid:
1110 case kExternalTypedDataUint8ClampedArrayCid: 1237 case kExternalTypedDataUint8ClampedArrayCid:
1111 case kTypedDataInt8ArrayCid: 1238 case kTypedDataInt8ArrayCid:
1112 case kTypedDataUint8ArrayCid: 1239 case kTypedDataUint8ArrayCid:
1113 case kTypedDataUint8ClampedArrayCid: 1240 case kTypedDataUint8ClampedArrayCid:
1114 case kOneByteStringCid: 1241 case kOneByteStringCid:
1115 case kTypedDataInt16ArrayCid: 1242 case kTypedDataInt16ArrayCid:
1116 case kTypedDataUint16ArrayCid: 1243 case kTypedDataUint16ArrayCid:
1244 locs->set_in(2, Location::WritableRegister());
1245 break;
1117 case kTypedDataInt32ArrayCid: 1246 case kTypedDataInt32ArrayCid:
1118 case kTypedDataUint32ArrayCid: 1247 case kTypedDataUint32ArrayCid:
1119 locs->set_in(2, Location::WritableRegister()); 1248 // Mints are stored in Q registers. For smis, use a writable register
1249 // because the value must be untagged before storing.
1250 locs->set_in(2, value()->IsSmiValue()
1251 ? Location::WritableRegister()
1252 : Location::FpuRegisterLocation(Q7));
1120 break; 1253 break;
1121 case kTypedDataFloat32ArrayCid: 1254 case kTypedDataFloat32ArrayCid:
1122 // Need low register (<= Q7). 1255 // Need low register (<= Q7).
1123 locs->set_in(2, Location::FpuRegisterLocation(Q7)); 1256 locs->set_in(2, Location::FpuRegisterLocation(Q7));
1124 break; 1257 break;
1125 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. 1258 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants.
1126 case kTypedDataInt32x4ArrayCid: 1259 case kTypedDataInt32x4ArrayCid:
1127 case kTypedDataFloat32x4ArrayCid: 1260 case kTypedDataFloat32x4ArrayCid:
1128 case kTypedDataFloat64x2ArrayCid: 1261 case kTypedDataFloat64x2ArrayCid:
1129 locs->set_in(2, Location::RequiresFpuRegister()); 1262 locs->set_in(2, Location::RequiresFpuRegister());
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1239 break; 1372 break;
1240 } 1373 }
1241 case kTypedDataInt32ArrayCid: 1374 case kTypedDataInt32ArrayCid:
1242 case kTypedDataUint32ArrayCid: { 1375 case kTypedDataUint32ArrayCid: {
1243 if (value()->IsSmiValue()) { 1376 if (value()->IsSmiValue()) {
1244 ASSERT(RequiredInputRepresentation(2) == kTagged); 1377 ASSERT(RequiredInputRepresentation(2) == kTagged);
1245 Register value = locs()->in(2).reg(); 1378 Register value = locs()->in(2).reg();
1246 __ SmiUntag(value); 1379 __ SmiUntag(value);
1247 __ str(value, element_address); 1380 __ str(value, element_address);
1248 } else { 1381 } else {
1249 UNIMPLEMENTED(); 1382 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint);
1383 QRegister value = locs()->in(2).fpu_reg();
1384 ASSERT(value == Q7);
1385 __ vmovrs(TMP, EvenSRegisterOf(EvenDRegisterOf(value)));
1386 __ str(TMP, element_address);
1250 } 1387 }
1251 break; 1388 break;
1252 } 1389 }
1253 case kTypedDataFloat32ArrayCid: { 1390 case kTypedDataFloat32ArrayCid: {
1254 SRegister value = 1391 SRegister value =
1255 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg())); 1392 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg()));
1256 __ add(index.reg(), index.reg(), ShifterOperand(array)); 1393 __ add(index.reg(), index.reg(), ShifterOperand(array));
1257 __ StoreSToOffset(value, index.reg(), 0); 1394 __ StoreSToOffset(value, index.reg(), 0);
1258 break; 1395 break;
1259 } 1396 }
(...skipping 2450 matching lines...) Expand 10 before | Expand all | Expand 10 after
3710 QRegister right = locs()->in(1).fpu_reg(); 3847 QRegister right = locs()->in(1).fpu_reg();
3711 QRegister result = locs()->out().fpu_reg(); 3848 QRegister result = locs()->out().fpu_reg();
3712 3849
3713 switch (op_kind()) { 3850 switch (op_kind()) {
3714 case MethodRecognizer::kFloat32x4Equal: 3851 case MethodRecognizer::kFloat32x4Equal:
3715 __ vceqqs(result, left, right); 3852 __ vceqqs(result, left, right);
3716 break; 3853 break;
3717 case MethodRecognizer::kFloat32x4NotEqual: 3854 case MethodRecognizer::kFloat32x4NotEqual:
3718 __ vceqqs(result, left, right); 3855 __ vceqqs(result, left, right);
3719 // Invert the result. 3856 // Invert the result.
3720 __ veorq(QTMP, QTMP, QTMP); // QTMP <- 0. 3857 __ vmvnq(result, result);
3721 __ vornq(result, QTMP, result); // result <- ~result.
3722 break; 3858 break;
3723 case MethodRecognizer::kFloat32x4GreaterThan: 3859 case MethodRecognizer::kFloat32x4GreaterThan:
3724 __ vcgtqs(result, left, right); 3860 __ vcgtqs(result, left, right);
3725 break; 3861 break;
3726 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: 3862 case MethodRecognizer::kFloat32x4GreaterThanOrEqual:
3727 __ vcgeqs(result, left, right); 3863 __ vcgeqs(result, left, right);
3728 break; 3864 break;
3729 case MethodRecognizer::kFloat32x4LessThan: 3865 case MethodRecognizer::kFloat32x4LessThan:
3730 __ vcgtqs(result, right, left); 3866 __ vcgtqs(result, right, left);
3731 break; 3867 break;
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after
4360 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4496 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4361 QRegister mask = locs()->in(0).fpu_reg(); 4497 QRegister mask = locs()->in(0).fpu_reg();
4362 QRegister trueValue = locs()->in(1).fpu_reg(); 4498 QRegister trueValue = locs()->in(1).fpu_reg();
4363 QRegister falseValue = locs()->in(2).fpu_reg(); 4499 QRegister falseValue = locs()->in(2).fpu_reg();
4364 QRegister out = locs()->out().fpu_reg(); 4500 QRegister out = locs()->out().fpu_reg();
4365 QRegister temp = locs()->temp(0).fpu_reg(); 4501 QRegister temp = locs()->temp(0).fpu_reg();
4366 4502
4367 // Copy mask. 4503 // Copy mask.
4368 __ vmovq(temp, mask); 4504 __ vmovq(temp, mask);
4369 // Invert it. 4505 // Invert it.
4370 __ veorq(QTMP, QTMP, QTMP); // QTMP <- 0. 4506 __ vmvnq(temp, temp);
4371 __ vornq(temp, QTMP, temp); // temp <- ~temp.
4372 // mask = mask & trueValue. 4507 // mask = mask & trueValue.
4373 __ vandq(mask, mask, trueValue); 4508 __ vandq(mask, mask, trueValue);
4374 // temp = temp & falseValue. 4509 // temp = temp & falseValue.
4375 __ vandq(temp, temp, falseValue); 4510 __ vandq(temp, temp, falseValue);
4376 // out = mask | temp. 4511 // out = mask | temp.
4377 __ vorrq(out, mask, temp); 4512 __ vorrq(out, mask, temp);
4378 } 4513 }
4379 4514
4380 4515
4381 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(bool opt) const { 4516 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(bool opt) const {
(...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after
5177 __ b(deopt, CS); 5312 __ b(deopt, CS);
5178 } else { 5313 } else {
5179 Register length = length_loc.reg(); 5314 Register length = length_loc.reg();
5180 Register index = index_loc.reg(); 5315 Register index = index_loc.reg();
5181 __ cmp(index, ShifterOperand(length)); 5316 __ cmp(index, ShifterOperand(length));
5182 __ b(deopt, CS); 5317 __ b(deopt, CS);
5183 } 5318 }
5184 } 5319 }
5185 5320
5186 5321
5322 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
5323 Label* overflow,
5324 QRegister result,
5325 Register tmp_hi, Register tmp_lo) {
5326 __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(result));
5327 // Compare upper half.
5328 Label check_lower;
5329 __ CompareImmediate(tmp_hi, 0x00200000);
5330 __ b(overflow, GT);
5331 __ b(&check_lower, NE);
5332
5333 __ CompareImmediate(tmp_lo, 0);
5334 __ b(overflow, HI);
5335
5336 __ Bind(&check_lower);
5337 __ CompareImmediate(tmp_hi, -0x00200000);
5338 __ b(overflow, LT);
5339 // Anything in the lower part would make the number bigger than the lower
5340 // bound, so we are done.
5341 }
5342
5343
5187 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { 5344 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
5188 UNIMPLEMENTED(); 5345 const intptr_t kNumInputs = 1;
5189 return NULL; 5346 const intptr_t value_cid = value()->Type()->ToCid();
5347 const bool needs_writable_input = (value_cid != kMintCid);
5348 const bool needs_temp = (value_cid != kMintCid);
5349 const intptr_t kNumTemps = needs_temp ? 1 : 0;
5350 LocationSummary* summary =
5351 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5352 summary->set_in(0, needs_writable_input
5353 ? Location::WritableRegister()
5354 : Location::RequiresRegister());
5355 if (needs_temp) {
5356 summary->set_temp(0, Location::RequiresRegister());
5357 }
5358 summary->set_out(Location::RequiresFpuRegister());
5359 return summary;
5190 } 5360 }
5191 5361
5192 5362
5193 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5363 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5194 UNIMPLEMENTED(); 5364 const intptr_t value_cid = value()->Type()->ToCid();
5365 const Register value = locs()->in(0).reg();
5366 const QRegister result = locs()->out().fpu_reg();
5367
5368 __ Comment("UnboxIntegerInstr");
5369 __ veorq(result, result, result);
5370 if (value_cid == kMintCid) {
5371 __ LoadDFromOffset(EvenDRegisterOf(result), value,
5372 Mint::value_offset() - kHeapObjectTag);
5373 } else if (value_cid == kSmiCid) {
5374 Register temp = locs()->temp(0).reg();
5375 __ SmiUntag(value);
5376 __ LoadImmediate(temp, 0);
5377 __ CompareImmediate(value, 0);
5378 __ LoadImmediate(temp, -1, LT);
5379 __ vmovdrr(EvenDRegisterOf(result), value, temp);
regis 2014/03/20 20:39:35 Replace 3 instructions above with: __ Lsl(temp,
zra 2014/03/20 23:49:25 Done.
5380 } else {
5381 Register temp = locs()->temp(0).reg();
5382 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptUnboxInteger);
5383 Label is_smi, done;
5384 __ tst(value, ShifterOperand(kSmiTagMask));
5385 __ b(&is_smi, EQ);
5386 __ CompareClassId(value, kMintCid, temp);
5387 __ b(deopt, NE);
5388
5389 // It's a Mint.
5390 __ LoadDFromOffset(EvenDRegisterOf(result), value,
5391 Mint::value_offset() - kHeapObjectTag);
5392 __ b(&done);
5393
5394 // It's a Smi.
5395 __ Bind(&is_smi);
5396 __ SmiUntag(value);
5397 __ LoadImmediate(temp, 0);
5398 __ CompareImmediate(value, 0);
5399 __ LoadImmediate(temp, -1, LT);
regis 2014/03/20 20:39:35 ditto
zra 2014/03/20 23:49:25 Done.
5400 __ vmovdrr(EvenDRegisterOf(result), value, temp);
5401 __ Bind(&done);
5402 }
5195 } 5403 }
5196 5404
5197 5405
5198 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { 5406 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
5199 UNIMPLEMENTED(); 5407 const intptr_t kNumInputs = 1;
5200 return NULL; 5408 const intptr_t kNumTemps = 2;
5201 } 5409 LocationSummary* summary =
5410 new LocationSummary(kNumInputs,
5411 kNumTemps,
5412 LocationSummary::kCallOnSlowPath);
5413 summary->set_in(0, Location::RequiresFpuRegister());
5414 summary->set_temp(0, Location::RequiresRegister());
5415 summary->set_temp(1, Location::RequiresRegister());
5416 summary->set_out(Location::RequiresRegister());
5417 return summary;
5418 }
5419
5420
5421 class BoxIntegerSlowPath : public SlowPathCode {
5422 public:
5423 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction)
5424 : instruction_(instruction) { }
5425
5426 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
5427 __ Comment("BoxIntegerSlowPath");
5428 __ Bind(entry_label());
5429 const Class& mint_class =
5430 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class());
5431 const Code& stub =
5432 Code::Handle(StubCode::GetAllocationStubForClass(mint_class));
5433 const ExternalLabel label(mint_class.ToCString(), stub.EntryPoint());
5434
5435 LocationSummary* locs = instruction_->locs();
5436 locs->live_registers()->Remove(locs->out());
5437
5438 compiler->SaveLiveRegisters(locs);
5439 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
5440 &label,
5441 PcDescriptors::kOther,
5442 locs);
5443 __ mov(locs->out().reg(), ShifterOperand(R0));
5444 compiler->RestoreLiveRegisters(locs);
5445
5446 __ b(exit_label());
5447 }
5448
5449 private:
5450 BoxIntegerInstr* instruction_;
5451 };
5202 5452
5203 5453
5204 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5454 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5205 UNIMPLEMENTED(); 5455 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
5456 compiler->AddSlowPathCode(slow_path);
5457
5458 Register out_reg = locs()->out().reg();
5459 QRegister value = locs()->in(0).fpu_reg();
5460 DRegister dvalue0 = EvenDRegisterOf(value);
5461 Register lo = locs()->temp(0).reg();
5462 Register hi = locs()->temp(1).reg();
5463
5464 // Unboxed operations produce smis or mint-sized values.
5465 // Check if value fits into a smi.
5466 __ Comment("BoxIntegerInstr");
5467 Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi;
5468 __ vmovrrd(lo, hi, dvalue0);
5469 __ CompareImmediate(hi, 0);
5470 __ b(&maybe_pos_smi, EQ);
5471
5472 __ CompareImmediate(hi, -1);
5473 __ b(&maybe_neg_smi, EQ);
5474 __ b(&not_smi);
5475
5476 __ Bind(&maybe_pos_smi);
5477 __ CompareImmediate(lo, kSmiMax);
5478 __ b(&is_smi, LS); // unsigned lower or same.
5479 __ b(&not_smi);
5480
5481 __ Bind(&maybe_neg_smi);
5482 __ CompareImmediate(lo, 0);
5483 __ b(&not_smi, GE);
5484 __ CompareImmediate(lo, kSmiMin);
5485 __ b(&not_smi, LT);
5486
5487 // lo is a Smi. Tag it and return.
5488 __ Bind(&is_smi);
5489 __ SmiTag(lo);
5490 __ mov(out_reg, ShifterOperand(lo));
5491 __ b(&done);
5492
5493 // Not a smi. Box it.
5494 __ Bind(&not_smi);
5495 __ TryAllocate(
5496 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
5497 slow_path->entry_label(),
5498 out_reg,
5499 lo);
5500 __ Bind(slow_path->exit_label());
5501 __ StoreDToOffset(dvalue0, out_reg, Mint::value_offset() - kHeapObjectTag);
5502 __ Bind(&done);
5206 } 5503 }
5207 5504
5208 5505
5209 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { 5506 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
5210 UNIMPLEMENTED(); 5507 const intptr_t kNumInputs = 2;
5211 return NULL; 5508 const intptr_t kNumTemps =
5509 FLAG_throw_on_javascript_int_overflow ? 2 : 0;
5510 LocationSummary* summary =
5511 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5512 summary->set_in(0, Location::RequiresFpuRegister());
5513 summary->set_in(1, Location::RequiresFpuRegister());
5514 if (FLAG_throw_on_javascript_int_overflow) {
5515 summary->set_temp(0, Location::RequiresRegister());
5516 summary->set_temp(1, Location::RequiresRegister());
5517 }
5518 if ((op_kind() == Token::kADD) || (op_kind() == Token::kSUB)) {
5519 // Need another temp for checking for overflow.
5520 summary->AddTemp(Location::RequiresFpuRegister());
5521 summary->AddTemp(Location::FpuRegisterLocation(Q7));
5522 }
5523 summary->set_out(Location::RequiresFpuRegister());
5524 return summary;
5212 } 5525 }
5213 5526
5214 5527
5215 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5528 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5216 UNIMPLEMENTED(); 5529 QRegister left = locs()->in(0).fpu_reg();
5530 QRegister right = locs()->in(1).fpu_reg();
5531 QRegister out = locs()->out().fpu_reg();
5532
5533 Label* deopt = NULL;
5534 if (FLAG_throw_on_javascript_int_overflow) {
5535 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryMintOp);
5536 }
5537 switch (op_kind()) {
5538 case Token::kBIT_AND: __ vandq(out, left, right); break;
5539 case Token::kBIT_OR: __ vorrq(out, left, right); break;
5540 case Token::kBIT_XOR: __ veorq(out, left, right); break;
5541 case Token::kADD:
5542 case Token::kSUB: {
5543 const intptr_t tmpidx = FLAG_throw_on_javascript_int_overflow ? 2 : 0;
5544 QRegister tmp = locs()->temp(tmpidx).fpu_reg();
5545 QRegister ro = locs()->temp(tmpidx + 1).fpu_reg();
5546 ASSERT(ro == Q7);
5547 if (!FLAG_throw_on_javascript_int_overflow) {
5548 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryMintOp);
5549 }
5550 if (op_kind() == Token::kADD) {
5551 __ vaddqi(kWordPair, out, left, right);
5552 } else {
5553 ASSERT(op_kind() == Token::kSUB);
5554 __ vsubqi(kWordPair, out, left, right);
5555 }
5556 __ veorq(ro, out, left);
5557 __ veorq(tmp, left, right);
5558 __ vandq(ro, tmp, ro);
5559 __ vmovrs(TMP, OddSRegisterOf(EvenDRegisterOf(ro)));
5560 // If TMP < 0, there was overflow.
5561 __ cmp(TMP, ShifterOperand(0));
5562 __ b(deopt, LT);
5563 break;
5564 }
5565 default: UNREACHABLE(); break;
5566 }
5567 if (FLAG_throw_on_javascript_int_overflow) {
5568 Register tmp1 = locs()->temp(0).reg();
5569 Register tmp2 = locs()->temp(1).reg();
5570 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
5571 }
5217 } 5572 }
5218 5573
5219 5574
5220 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { 5575 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
5221 UNIMPLEMENTED(); 5576 const intptr_t kNumInputs = 2;
5222 return NULL; 5577 const intptr_t kNumTemps =
5578 FLAG_throw_on_javascript_int_overflow ? 2 : 1;
5579 LocationSummary* summary =
5580 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5581 summary->set_in(0, Location::RequiresFpuRegister());
5582 summary->set_in(1, Location::WritableRegister());
5583 summary->set_temp(0, Location::FpuRegisterLocation(Q7));
5584 if (FLAG_throw_on_javascript_int_overflow) {
5585 summary->set_temp(1, Location::RequiresRegister());
5586 }
5587 summary->set_out(Location::RequiresFpuRegister());
5588 return summary;
5223 } 5589 }
5224 5590
5225 5591
5226 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5592 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5227 UNIMPLEMENTED(); 5593 QRegister value = locs()->in(0).fpu_reg();
5594 Register shift = locs()->in(1).reg();
5595 QRegister temp = locs()->temp(0).fpu_reg();
5596 ASSERT(temp == Q7);
5597 QRegister out = locs()->out().fpu_reg();
5598 DRegister dtemp0 = EvenDRegisterOf(temp);
5599 SRegister stemp0 = EvenSRegisterOf(dtemp0);
5600 SRegister stemp1 = OddSRegisterOf(dtemp0);
5601
5602 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptShiftMintOp);
5603 Label done;
5604
5605 __ CompareImmediate(shift, 0);
5606 __ vmovq(out, value);
5607 __ b(&done, EQ);
5608 __ SmiUntag(shift);
5609
5610 // vshlq takes the shift value from low byte. Deopt if shift is
5611 // outside of [0, 127].
5612 __ CompareImmediate(shift, 127);
5613 __ b(deopt, GT);
5614 __ CompareImmediate(shift, 0);
5615 __ b(deopt, LT);
5616
5617 __ veorq(temp, temp, temp); // Zero out temp.
5618 switch (op_kind()) {
5619 case Token::kSHR: {
5620 __ rsb(shift, shift, ShifterOperand(0)); // Negate shift.
5621 __ vmovsr(stemp0, shift); // Move the shift into the low S register.
5622 __ vshlqi(kWordPair, out, value, temp);
5623 break;
5624 }
5625 case Token::kSHL: {
5626 __ vmovsr(stemp0, shift); // Move the shift into the low S register.
5627 __ vshlqu(kWordPair, out, value, temp);
5628
5629 // check for overflow by shifting back and comparing.
5630 __ rsb(shift, shift, ShifterOperand(0));
5631 __ vmovsr(stemp0, shift);
5632 __ vshlqi(kWordPair, temp, out, temp);
5633 __ vceqqi(kWord, temp, temp, value);
5634 // Low 64 bits of temp should be all 1's, otherwise temp != value and
5635 // we deopt.
5636 __ vmovrs(shift, stemp0);
5637 __ CompareImmediate(shift, -1);
5638 __ b(deopt, NE);
5639 __ vmovrs(shift, stemp1);
5640 __ CompareImmediate(shift, -1);
5641 __ b(deopt, NE);
5642 break;
5643 }
5644 default:
5645 UNREACHABLE();
5646 break;
5647 }
5648
5649 __ Bind(&done);
5650 if (FLAG_throw_on_javascript_int_overflow) {
5651 Register tmp1 = locs()->in(1).reg();
5652 Register tmp2 = locs()->temp(1).reg();
5653 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
5654 }
5228 } 5655 }
5229 5656
5230 5657
5231 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { 5658 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
5232 UNIMPLEMENTED(); 5659 const intptr_t kNumInputs = 1;
5233 return NULL; 5660 const intptr_t kNumTemps =
5661 FLAG_throw_on_javascript_int_overflow ? 2 : 0;
5662 LocationSummary* summary =
5663 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5664 summary->set_in(0, Location::RequiresFpuRegister());
5665 summary->set_out(Location::RequiresFpuRegister());
5666 if (FLAG_throw_on_javascript_int_overflow) {
5667 summary->set_temp(0, Location::RequiresRegister());
5668 summary->set_temp(1, Location::RequiresRegister());
5669 }
5670 return summary;
5234 } 5671 }
5235 5672
5236 5673
5237 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5674 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5238 UNIMPLEMENTED(); 5675 ASSERT(op_kind() == Token::kBIT_NOT);
5239 } 5676 QRegister value = locs()->in(0).fpu_reg();
5240 5677 QRegister out = locs()->out().fpu_reg();
5241 5678 Label* deopt = NULL;
5679 if (FLAG_throw_on_javascript_int_overflow) {
5680 deopt = compiler->AddDeoptStub(deopt_id(),
5681 kDeoptUnaryMintOp);
5682 }
5683 __ vmvnq(out, value);
5684 if (FLAG_throw_on_javascript_int_overflow) {
5685 Register tmp1 = locs()->temp(0).reg();
5686 Register tmp2 = locs()->temp(1).reg();
5687 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
5688 }
5689 }
5690
5691
5242 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { 5692 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const {
5243 return new LocationSummary(0, 0, LocationSummary::kCall); 5693 return new LocationSummary(0, 0, LocationSummary::kCall);
5244 } 5694 }
5245 5695
5246 5696
5247 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5697 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5248 compiler->GenerateRuntimeCall(token_pos(), 5698 compiler->GenerateRuntimeCall(token_pos(),
5249 deopt_id(), 5699 deopt_id(),
5250 kThrowRuntimeEntry, 5700 kThrowRuntimeEntry,
5251 1, 5701 1,
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
5437 compiler->GenerateCall(token_pos(), 5887 compiler->GenerateCall(token_pos(),
5438 &label, 5888 &label,
5439 PcDescriptors::kOther, 5889 PcDescriptors::kOther,
5440 locs()); 5890 locs());
5441 __ Drop(ArgumentCount()); // Discard arguments. 5891 __ Drop(ArgumentCount()); // Discard arguments.
5442 } 5892 }
5443 5893
5444 } // namespace dart 5894 } // namespace dart
5445 5895
5446 #endif // defined TARGET_ARCH_ARM 5896 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698