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

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: merge 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
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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(0, Location::RequiresRegister()); 343 locs->set_out(0, 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(0, Location::RequiresRegister()); 352 locs->set_out(0, 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(0).reg(); 595 Register result = locs()->out(0).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(0, Location::RequiresRegister()); 702 summary->set_out(0, 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(0).reg(); 725 Register result = locs()->out(0).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(0).fpu_reg(); 1084 QRegister result = locs()->out(0).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 // Sign-extend into idx.
1095 __ Asr(idx, TMP, 31);
1096 __ vmovdrr(dresult0, TMP, idx);
977 break; 1097 break;
978 case kTypedDataUint32ArrayCid: 1098 case kTypedDataUint32ArrayCid:
979 UNIMPLEMENTED(); 1099 __ veorq(result, result, result);
1100 __ ldr(TMP, element_address);
1101 // Re-use the index register so we don't have to require a low-numbered
1102 // Q register.
1103 __ LoadImmediate(idx, 0);
1104 __ vmovdrr(dresult0, TMP, idx);
980 break; 1105 break;
981 case kTypedDataFloat32ArrayCid: 1106 case kTypedDataFloat32ArrayCid:
982 // Load single precision float. 1107 // Load single precision float.
983 // vldrs does not support indexed addressing. 1108 // vldrs does not support indexed addressing.
984 __ add(index.reg(), index.reg(), ShifterOperand(array)); 1109 __ add(index.reg(), index.reg(), ShifterOperand(array));
985 element_address = Address(index.reg(), 0); 1110 element_address = Address(index.reg(), 0);
986 __ vldrs(EvenSRegisterOf(dresult0), element_address); 1111 __ vldrs(EvenSRegisterOf(dresult0), element_address);
987 break; 1112 break;
988 case kTypedDataFloat64ArrayCid: 1113 case kTypedDataFloat64ArrayCid:
989 // vldrd does not support indexed addressing. 1114 // 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. 1159 // Verify that the signed value in 'result' can fit inside a Smi.
1035 __ CompareImmediate(result, 0xC0000000); 1160 __ CompareImmediate(result, 0xC0000000);
1036 __ b(deopt, MI); 1161 __ b(deopt, MI);
1037 __ SmiTag(result); 1162 __ SmiTag(result);
1038 } 1163 }
1039 break; 1164 break;
1040 case kTypedDataUint32ArrayCid: { 1165 case kTypedDataUint32ArrayCid: {
1041 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptUint32Load); 1166 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptUint32Load);
1042 __ ldr(result, element_address); 1167 __ ldr(result, element_address);
1043 // Verify that the unsigned value in 'result' can fit inside a Smi. 1168 // Verify that the unsigned value in 'result' can fit inside a Smi.
1044 __ tst(result, ShifterOperand(0xC0000000)); 1169 __ TestImmediate(result, 0xC0000000);
1045 __ b(deopt, NE); 1170 __ b(deopt, NE);
1046 __ SmiTag(result); 1171 __ SmiTag(result);
1047 } 1172 }
1048 break; 1173 break;
1049 default: 1174 default:
1050 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); 1175 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid));
1051 __ ldr(result, element_address); 1176 __ ldr(result, element_address);
1052 break; 1177 break;
1053 } 1178 }
1054 } 1179 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 : Location::RegisterOrConstant(value())); 1232 : Location::RegisterOrConstant(value()));
1108 break; 1233 break;
1109 case kExternalTypedDataUint8ArrayCid: 1234 case kExternalTypedDataUint8ArrayCid:
1110 case kExternalTypedDataUint8ClampedArrayCid: 1235 case kExternalTypedDataUint8ClampedArrayCid:
1111 case kTypedDataInt8ArrayCid: 1236 case kTypedDataInt8ArrayCid:
1112 case kTypedDataUint8ArrayCid: 1237 case kTypedDataUint8ArrayCid:
1113 case kTypedDataUint8ClampedArrayCid: 1238 case kTypedDataUint8ClampedArrayCid:
1114 case kOneByteStringCid: 1239 case kOneByteStringCid:
1115 case kTypedDataInt16ArrayCid: 1240 case kTypedDataInt16ArrayCid:
1116 case kTypedDataUint16ArrayCid: 1241 case kTypedDataUint16ArrayCid:
1242 locs->set_in(2, Location::WritableRegister());
1243 break;
1117 case kTypedDataInt32ArrayCid: 1244 case kTypedDataInt32ArrayCid:
1118 case kTypedDataUint32ArrayCid: 1245 case kTypedDataUint32ArrayCid:
1119 locs->set_in(2, Location::WritableRegister()); 1246 // Mints are stored in Q registers. For smis, use a writable register
1247 // because the value must be untagged before storing.
1248 locs->set_in(2, value()->IsSmiValue()
1249 ? Location::WritableRegister()
1250 : Location::FpuRegisterLocation(Q7));
1120 break; 1251 break;
1121 case kTypedDataFloat32ArrayCid: 1252 case kTypedDataFloat32ArrayCid:
1122 // Need low register (<= Q7). 1253 // Need low register (<= Q7).
1123 locs->set_in(2, Location::FpuRegisterLocation(Q7)); 1254 locs->set_in(2, Location::FpuRegisterLocation(Q7));
1124 break; 1255 break;
1125 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. 1256 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants.
1126 case kTypedDataInt32x4ArrayCid: 1257 case kTypedDataInt32x4ArrayCid:
1127 case kTypedDataFloat32x4ArrayCid: 1258 case kTypedDataFloat32x4ArrayCid:
1128 case kTypedDataFloat64x2ArrayCid: 1259 case kTypedDataFloat64x2ArrayCid:
1129 locs->set_in(2, Location::RequiresFpuRegister()); 1260 locs->set_in(2, Location::RequiresFpuRegister());
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1239 break; 1370 break;
1240 } 1371 }
1241 case kTypedDataInt32ArrayCid: 1372 case kTypedDataInt32ArrayCid:
1242 case kTypedDataUint32ArrayCid: { 1373 case kTypedDataUint32ArrayCid: {
1243 if (value()->IsSmiValue()) { 1374 if (value()->IsSmiValue()) {
1244 ASSERT(RequiredInputRepresentation(2) == kTagged); 1375 ASSERT(RequiredInputRepresentation(2) == kTagged);
1245 Register value = locs()->in(2).reg(); 1376 Register value = locs()->in(2).reg();
1246 __ SmiUntag(value); 1377 __ SmiUntag(value);
1247 __ str(value, element_address); 1378 __ str(value, element_address);
1248 } else { 1379 } else {
1249 UNIMPLEMENTED(); 1380 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint);
1381 QRegister value = locs()->in(2).fpu_reg();
1382 ASSERT(value == Q7);
1383 __ vmovrs(TMP, EvenSRegisterOf(EvenDRegisterOf(value)));
1384 __ str(TMP, element_address);
1250 } 1385 }
1251 break; 1386 break;
1252 } 1387 }
1253 case kTypedDataFloat32ArrayCid: { 1388 case kTypedDataFloat32ArrayCid: {
1254 SRegister value = 1389 SRegister value =
1255 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg())); 1390 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg()));
1256 __ add(index.reg(), index.reg(), ShifterOperand(array)); 1391 __ add(index.reg(), index.reg(), ShifterOperand(array));
1257 __ StoreSToOffset(value, index.reg(), 0); 1392 __ StoreSToOffset(value, index.reg(), 0);
1258 break; 1393 break;
1259 } 1394 }
(...skipping 2450 matching lines...) Expand 10 before | Expand all | Expand 10 after
3710 QRegister right = locs()->in(1).fpu_reg(); 3845 QRegister right = locs()->in(1).fpu_reg();
3711 QRegister result = locs()->out(0).fpu_reg(); 3846 QRegister result = locs()->out(0).fpu_reg();
3712 3847
3713 switch (op_kind()) { 3848 switch (op_kind()) {
3714 case MethodRecognizer::kFloat32x4Equal: 3849 case MethodRecognizer::kFloat32x4Equal:
3715 __ vceqqs(result, left, right); 3850 __ vceqqs(result, left, right);
3716 break; 3851 break;
3717 case MethodRecognizer::kFloat32x4NotEqual: 3852 case MethodRecognizer::kFloat32x4NotEqual:
3718 __ vceqqs(result, left, right); 3853 __ vceqqs(result, left, right);
3719 // Invert the result. 3854 // Invert the result.
3720 __ veorq(QTMP, QTMP, QTMP); // QTMP <- 0. 3855 __ vmvnq(result, result);
3721 __ vornq(result, QTMP, result); // result <- ~result.
3722 break; 3856 break;
3723 case MethodRecognizer::kFloat32x4GreaterThan: 3857 case MethodRecognizer::kFloat32x4GreaterThan:
3724 __ vcgtqs(result, left, right); 3858 __ vcgtqs(result, left, right);
3725 break; 3859 break;
3726 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: 3860 case MethodRecognizer::kFloat32x4GreaterThanOrEqual:
3727 __ vcgeqs(result, left, right); 3861 __ vcgeqs(result, left, right);
3728 break; 3862 break;
3729 case MethodRecognizer::kFloat32x4LessThan: 3863 case MethodRecognizer::kFloat32x4LessThan:
3730 __ vcgtqs(result, right, left); 3864 __ vcgtqs(result, right, left);
3731 break; 3865 break;
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after
4360 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4494 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4361 QRegister mask = locs()->in(0).fpu_reg(); 4495 QRegister mask = locs()->in(0).fpu_reg();
4362 QRegister trueValue = locs()->in(1).fpu_reg(); 4496 QRegister trueValue = locs()->in(1).fpu_reg();
4363 QRegister falseValue = locs()->in(2).fpu_reg(); 4497 QRegister falseValue = locs()->in(2).fpu_reg();
4364 QRegister out = locs()->out(0).fpu_reg(); 4498 QRegister out = locs()->out(0).fpu_reg();
4365 QRegister temp = locs()->temp(0).fpu_reg(); 4499 QRegister temp = locs()->temp(0).fpu_reg();
4366 4500
4367 // Copy mask. 4501 // Copy mask.
4368 __ vmovq(temp, mask); 4502 __ vmovq(temp, mask);
4369 // Invert it. 4503 // Invert it.
4370 __ veorq(QTMP, QTMP, QTMP); // QTMP <- 0. 4504 __ vmvnq(temp, temp);
4371 __ vornq(temp, QTMP, temp); // temp <- ~temp.
4372 // mask = mask & trueValue. 4505 // mask = mask & trueValue.
4373 __ vandq(mask, mask, trueValue); 4506 __ vandq(mask, mask, trueValue);
4374 // temp = temp & falseValue. 4507 // temp = temp & falseValue.
4375 __ vandq(temp, temp, falseValue); 4508 __ vandq(temp, temp, falseValue);
4376 // out = mask | temp. 4509 // out = mask | temp.
4377 __ vorrq(out, mask, temp); 4510 __ vorrq(out, mask, temp);
4378 } 4511 }
4379 4512
4380 4513
4381 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(bool opt) const { 4514 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(bool opt) const {
(...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after
5177 __ b(deopt, CS); 5310 __ b(deopt, CS);
5178 } else { 5311 } else {
5179 Register length = length_loc.reg(); 5312 Register length = length_loc.reg();
5180 Register index = index_loc.reg(); 5313 Register index = index_loc.reg();
5181 __ cmp(index, ShifterOperand(length)); 5314 __ cmp(index, ShifterOperand(length));
5182 __ b(deopt, CS); 5315 __ b(deopt, CS);
5183 } 5316 }
5184 } 5317 }
5185 5318
5186 5319
5320 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
5321 Label* overflow,
5322 QRegister result,
5323 Register tmp_hi, Register tmp_lo) {
5324 __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(result));
5325 // Compare upper half.
5326 Label check_lower;
5327 __ CompareImmediate(tmp_hi, 0x00200000);
5328 __ b(overflow, GT);
5329 __ b(&check_lower, NE);
5330
5331 __ CompareImmediate(tmp_lo, 0);
5332 __ b(overflow, HI);
5333
5334 __ Bind(&check_lower);
5335 __ CompareImmediate(tmp_hi, -0x00200000);
5336 __ b(overflow, LT);
5337 // Anything in the lower part would make the number bigger than the lower
5338 // bound, so we are done.
5339 }
5340
5341
5187 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { 5342 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
5188 UNIMPLEMENTED(); 5343 const intptr_t kNumInputs = 1;
5189 return NULL; 5344 const intptr_t value_cid = value()->Type()->ToCid();
5345 const bool needs_writable_input = (value_cid != kMintCid);
5346 const bool needs_temp = (value_cid != kMintCid);
5347 const intptr_t kNumTemps = needs_temp ? 1 : 0;
5348 LocationSummary* summary =
5349 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5350 summary->set_in(0, needs_writable_input
5351 ? Location::WritableRegister()
5352 : Location::RequiresRegister());
5353 if (needs_temp) {
5354 summary->set_temp(0, Location::RequiresRegister());
5355 }
5356 summary->set_out(0, Location::RequiresFpuRegister());
5357 return summary;
5190 } 5358 }
5191 5359
5192 5360
5193 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5361 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5194 UNIMPLEMENTED(); 5362 const intptr_t value_cid = value()->Type()->ToCid();
5363 const Register value = locs()->in(0).reg();
5364 const QRegister result = locs()->out(0).fpu_reg();
5365
5366 __ Comment("UnboxIntegerInstr");
5367 __ veorq(result, result, result);
5368 if (value_cid == kMintCid) {
5369 __ LoadDFromOffset(EvenDRegisterOf(result), value,
5370 Mint::value_offset() - kHeapObjectTag);
5371 } else if (value_cid == kSmiCid) {
5372 Register temp = locs()->temp(0).reg();
5373 __ SmiUntag(value);
5374 // Sign extend value into temp.
5375 __ Asr(temp, value, 31);
5376 __ vmovdrr(EvenDRegisterOf(result), value, temp);
5377 } else {
5378 Register temp = locs()->temp(0).reg();
5379 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptUnboxInteger);
5380 Label is_smi, done;
5381 __ tst(value, ShifterOperand(kSmiTagMask));
5382 __ b(&is_smi, EQ);
5383 __ CompareClassId(value, kMintCid, temp);
5384 __ b(deopt, NE);
5385
5386 // It's a Mint.
5387 __ LoadDFromOffset(EvenDRegisterOf(result), value,
5388 Mint::value_offset() - kHeapObjectTag);
5389 __ b(&done);
5390
5391 // It's a Smi.
5392 __ Bind(&is_smi);
5393 __ SmiUntag(value);
5394 // Sign extend into temp.
5395 __ Asr(temp, value, 31);
5396 __ vmovdrr(EvenDRegisterOf(result), value, temp);
5397 __ Bind(&done);
5398 }
5195 } 5399 }
5196 5400
5197 5401
5198 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { 5402 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
5199 UNIMPLEMENTED(); 5403 const intptr_t kNumInputs = 1;
5200 return NULL; 5404 const intptr_t kNumTemps = 2;
5201 } 5405 LocationSummary* summary =
5406 new LocationSummary(kNumInputs,
5407 kNumTemps,
5408 LocationSummary::kCallOnSlowPath);
5409 summary->set_in(0, Location::RequiresFpuRegister());
5410 summary->set_temp(0, Location::RequiresRegister());
5411 summary->set_temp(1, Location::RequiresRegister());
5412 summary->set_out(0, Location::RequiresRegister());
5413 return summary;
5414 }
5415
5416
5417 class BoxIntegerSlowPath : public SlowPathCode {
5418 public:
5419 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction)
5420 : instruction_(instruction) { }
5421
5422 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
5423 __ Comment("BoxIntegerSlowPath");
5424 __ Bind(entry_label());
5425 const Class& mint_class =
5426 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class());
5427 const Code& stub =
5428 Code::Handle(StubCode::GetAllocationStubForClass(mint_class));
5429 const ExternalLabel label(mint_class.ToCString(), stub.EntryPoint());
5430
5431 LocationSummary* locs = instruction_->locs();
5432 locs->live_registers()->Remove(locs->out(0));
5433
5434 compiler->SaveLiveRegisters(locs);
5435 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
5436 &label,
5437 PcDescriptors::kOther,
5438 locs);
5439 __ mov(locs->out(0).reg(), ShifterOperand(R0));
5440 compiler->RestoreLiveRegisters(locs);
5441
5442 __ b(exit_label());
5443 }
5444
5445 private:
5446 BoxIntegerInstr* instruction_;
5447 };
5202 5448
5203 5449
5204 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5450 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5205 UNIMPLEMENTED(); 5451 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
5452 compiler->AddSlowPathCode(slow_path);
5453
5454 Register out_reg = locs()->out(0).reg();
5455 QRegister value = locs()->in(0).fpu_reg();
5456 DRegister dvalue0 = EvenDRegisterOf(value);
5457 Register lo = locs()->temp(0).reg();
5458 Register hi = locs()->temp(1).reg();
5459
5460 // Unboxed operations produce smis or mint-sized values.
5461 // Check if value fits into a smi.
5462 __ Comment("BoxIntegerInstr");
5463 Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi;
5464 __ vmovrrd(lo, hi, dvalue0);
5465 __ CompareImmediate(hi, 0);
5466 __ b(&maybe_pos_smi, EQ);
5467
5468 __ CompareImmediate(hi, -1);
5469 __ b(&maybe_neg_smi, EQ);
5470 __ b(&not_smi);
5471
5472 __ Bind(&maybe_pos_smi);
5473 __ CompareImmediate(lo, kSmiMax);
5474 __ b(&is_smi, LS); // unsigned lower or same.
5475 __ b(&not_smi);
5476
5477 __ Bind(&maybe_neg_smi);
5478 __ CompareImmediate(lo, 0);
5479 __ b(&not_smi, GE);
5480 __ CompareImmediate(lo, kSmiMin);
5481 __ b(&not_smi, LT);
5482
5483 // lo is a Smi. Tag it and return.
5484 __ Bind(&is_smi);
5485 __ SmiTag(lo);
5486 __ mov(out_reg, ShifterOperand(lo));
5487 __ b(&done);
5488
5489 // Not a smi. Box it.
5490 __ Bind(&not_smi);
5491 __ TryAllocate(
5492 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
5493 slow_path->entry_label(),
5494 out_reg,
5495 lo);
5496 __ Bind(slow_path->exit_label());
5497 __ StoreDToOffset(dvalue0, out_reg, Mint::value_offset() - kHeapObjectTag);
5498 __ Bind(&done);
5206 } 5499 }
5207 5500
5208 5501
5209 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { 5502 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
5210 UNIMPLEMENTED(); 5503 const intptr_t kNumInputs = 2;
5211 return NULL; 5504 const intptr_t kNumTemps =
5505 FLAG_throw_on_javascript_int_overflow ? 2 : 0;
5506 LocationSummary* summary =
5507 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5508 summary->set_in(0, Location::RequiresFpuRegister());
5509 summary->set_in(1, Location::RequiresFpuRegister());
5510 if (FLAG_throw_on_javascript_int_overflow) {
5511 summary->set_temp(0, Location::RequiresRegister());
5512 summary->set_temp(1, Location::RequiresRegister());
5513 }
5514 if ((op_kind() == Token::kADD) || (op_kind() == Token::kSUB)) {
5515 // Need another temp for checking for overflow.
5516 summary->AddTemp(Location::RequiresFpuRegister());
5517 summary->AddTemp(Location::FpuRegisterLocation(Q7));
5518 }
5519 summary->set_out(0, Location::RequiresFpuRegister());
5520 return summary;
5212 } 5521 }
5213 5522
5214 5523
5215 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5524 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5216 UNIMPLEMENTED(); 5525 QRegister left = locs()->in(0).fpu_reg();
5526 QRegister right = locs()->in(1).fpu_reg();
5527 QRegister out = locs()->out(0).fpu_reg();
5528
5529 Label* deopt = NULL;
5530 if (FLAG_throw_on_javascript_int_overflow) {
5531 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryMintOp);
5532 }
5533 switch (op_kind()) {
5534 case Token::kBIT_AND: __ vandq(out, left, right); break;
5535 case Token::kBIT_OR: __ vorrq(out, left, right); break;
5536 case Token::kBIT_XOR: __ veorq(out, left, right); break;
5537 case Token::kADD:
5538 case Token::kSUB: {
5539 const intptr_t tmpidx = FLAG_throw_on_javascript_int_overflow ? 2 : 0;
5540 QRegister tmp = locs()->temp(tmpidx).fpu_reg();
5541 QRegister ro = locs()->temp(tmpidx + 1).fpu_reg();
5542 ASSERT(ro == Q7);
5543 if (!FLAG_throw_on_javascript_int_overflow) {
5544 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryMintOp);
5545 }
5546 if (op_kind() == Token::kADD) {
5547 __ vaddqi(kWordPair, out, left, right);
5548 } else {
5549 ASSERT(op_kind() == Token::kSUB);
5550 __ vsubqi(kWordPair, out, left, right);
5551 }
5552 __ veorq(ro, out, left);
5553 __ veorq(tmp, left, right);
5554 __ vandq(ro, tmp, ro);
5555 __ vmovrs(TMP, OddSRegisterOf(EvenDRegisterOf(ro)));
5556 // If TMP < 0, there was overflow.
5557 __ cmp(TMP, ShifterOperand(0));
5558 __ b(deopt, LT);
5559 break;
5560 }
5561 default: UNREACHABLE(); break;
5562 }
5563 if (FLAG_throw_on_javascript_int_overflow) {
5564 Register tmp1 = locs()->temp(0).reg();
5565 Register tmp2 = locs()->temp(1).reg();
5566 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
5567 }
5217 } 5568 }
5218 5569
5219 5570
5220 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { 5571 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
5221 UNIMPLEMENTED(); 5572 const intptr_t kNumInputs = 2;
5222 return NULL; 5573 const intptr_t kNumTemps =
5574 FLAG_throw_on_javascript_int_overflow ? 2 : 1;
5575 LocationSummary* summary =
5576 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5577 summary->set_in(0, Location::RequiresFpuRegister());
5578 summary->set_in(1, Location::WritableRegister());
5579 summary->set_temp(0, Location::FpuRegisterLocation(Q7));
5580 if (FLAG_throw_on_javascript_int_overflow) {
5581 summary->set_temp(1, Location::RequiresRegister());
5582 }
5583 summary->set_out(0, Location::RequiresFpuRegister());
5584 return summary;
5223 } 5585 }
5224 5586
5225 5587
5226 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5588 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5227 UNIMPLEMENTED(); 5589 QRegister value = locs()->in(0).fpu_reg();
5590 Register shift = locs()->in(1).reg();
5591 QRegister temp = locs()->temp(0).fpu_reg();
5592 ASSERT(temp == Q7);
5593 QRegister out = locs()->out(0).fpu_reg();
5594 DRegister dtemp0 = EvenDRegisterOf(temp);
5595 SRegister stemp0 = EvenSRegisterOf(dtemp0);
5596 SRegister stemp1 = OddSRegisterOf(dtemp0);
5597
5598 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptShiftMintOp);
5599 Label done;
5600
5601 __ CompareImmediate(shift, 0);
5602 __ vmovq(out, value);
5603 __ b(&done, EQ);
5604 __ SmiUntag(shift);
5605
5606 // vshlq takes the shift value from low byte. Deopt if shift is
5607 // outside of [0, 127].
5608 __ CompareImmediate(shift, 127);
5609 __ b(deopt, GT);
5610 __ CompareImmediate(shift, 0);
5611 __ b(deopt, LT);
5612
5613 __ veorq(temp, temp, temp); // Zero out temp.
5614 switch (op_kind()) {
5615 case Token::kSHR: {
5616 __ rsb(shift, shift, ShifterOperand(0)); // Negate shift.
5617 __ vmovsr(stemp0, shift); // Move the shift into the low S register.
5618 __ vshlqi(kWordPair, out, value, temp);
5619 break;
5620 }
5621 case Token::kSHL: {
5622 __ vmovsr(stemp0, shift); // Move the shift into the low S register.
5623 __ vshlqu(kWordPair, out, value, temp);
5624
5625 // check for overflow by shifting back and comparing.
5626 __ rsb(shift, shift, ShifterOperand(0));
5627 __ vmovsr(stemp0, shift);
5628 __ vshlqi(kWordPair, temp, out, temp);
5629 __ vceqqi(kWord, temp, temp, value);
5630 // Low 64 bits of temp should be all 1's, otherwise temp != value and
5631 // we deopt.
5632 __ vmovrs(shift, stemp0);
5633 __ CompareImmediate(shift, -1);
5634 __ b(deopt, NE);
5635 __ vmovrs(shift, stemp1);
5636 __ CompareImmediate(shift, -1);
5637 __ b(deopt, NE);
5638 break;
5639 }
5640 default:
5641 UNREACHABLE();
5642 break;
5643 }
5644
5645 __ Bind(&done);
5646 if (FLAG_throw_on_javascript_int_overflow) {
5647 Register tmp1 = locs()->in(1).reg();
5648 Register tmp2 = locs()->temp(1).reg();
5649 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
5650 }
5228 } 5651 }
5229 5652
5230 5653
5231 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { 5654 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
5232 UNIMPLEMENTED(); 5655 const intptr_t kNumInputs = 1;
5233 return NULL; 5656 const intptr_t kNumTemps =
5657 FLAG_throw_on_javascript_int_overflow ? 2 : 0;
5658 LocationSummary* summary =
5659 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5660 summary->set_in(0, Location::RequiresFpuRegister());
5661 summary->set_out(0, Location::RequiresFpuRegister());
5662 if (FLAG_throw_on_javascript_int_overflow) {
5663 summary->set_temp(0, Location::RequiresRegister());
5664 summary->set_temp(1, Location::RequiresRegister());
5665 }
5666 return summary;
5234 } 5667 }
5235 5668
5236 5669
5237 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5670 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5238 UNIMPLEMENTED(); 5671 ASSERT(op_kind() == Token::kBIT_NOT);
5239 } 5672 QRegister value = locs()->in(0).fpu_reg();
5240 5673 QRegister out = locs()->out(0).fpu_reg();
5241 5674 Label* deopt = NULL;
5675 if (FLAG_throw_on_javascript_int_overflow) {
5676 deopt = compiler->AddDeoptStub(deopt_id(),
5677 kDeoptUnaryMintOp);
5678 }
5679 __ vmvnq(out, value);
5680 if (FLAG_throw_on_javascript_int_overflow) {
5681 Register tmp1 = locs()->temp(0).reg();
5682 Register tmp2 = locs()->temp(1).reg();
5683 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
5684 }
5685 }
5686
5687
5242 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { 5688 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const {
5243 return new LocationSummary(0, 0, LocationSummary::kCall); 5689 return new LocationSummary(0, 0, LocationSummary::kCall);
5244 } 5690 }
5245 5691
5246 5692
5247 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5693 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5248 compiler->GenerateRuntimeCall(token_pos(), 5694 compiler->GenerateRuntimeCall(token_pos(),
5249 deopt_id(), 5695 deopt_id(),
5250 kThrowRuntimeEntry, 5696 kThrowRuntimeEntry,
5251 1, 5697 1,
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
5437 compiler->GenerateCall(token_pos(), 5883 compiler->GenerateCall(token_pos(),
5438 &label, 5884 &label,
5439 PcDescriptors::kOther, 5885 PcDescriptors::kOther,
5440 locs()); 5886 locs());
5441 __ Drop(ArgumentCount()); // Discard arguments. 5887 __ Drop(ArgumentCount()); // Discard arguments.
5442 } 5888 }
5443 5889
5444 } // namespace dart 5890 } // namespace dart
5445 5891
5446 #endif // defined TARGET_ARCH_ARM 5892 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698