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

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

Issue 17131002: Enables language tests for SIMMIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 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/instructions_mips.cc ('k') | runtime/vm/intrinsifier_mips.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_MIPS. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS.
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 if (!compiler->is_optimizing()) { 380 if (!compiler->is_optimizing()) {
381 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 381 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
382 deopt_id, 382 deopt_id,
383 token_pos); 383 token_pos);
384 } 384 }
385 const int kNumberOfArguments = 2; 385 const int kNumberOfArguments = 2;
386 const Array& kNoArgumentNames = Array::Handle(); 386 const Array& kNoArgumentNames = Array::Handle();
387 const int kNumArgumentsChecked = 2; 387 const int kNumArgumentsChecked = 2;
388 388
389 __ TraceSimMsg("EmitEqualityAsInstanceCall"); 389 __ TraceSimMsg("EmitEqualityAsInstanceCall");
390 __ Comment("EmitEqualityAsInstanceCall");
390 Label check_identity; 391 Label check_identity;
391 __ lw(A1, Address(SP, 1 * kWordSize)); 392 __ lw(A1, Address(SP, 1 * kWordSize));
392 __ lw(A0, Address(SP, 0 * kWordSize)); 393 __ lw(A0, Address(SP, 0 * kWordSize));
393 __ beq(A1, NULLREG, &check_identity); 394 __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null()));
394 __ beq(A0, NULLREG, &check_identity); 395 __ beq(A1, TMP, &check_identity);
396 __ beq(A0, TMP, &check_identity);
395 397
396 ICData& equality_ic_data = ICData::ZoneHandle(); 398 ICData& equality_ic_data = ICData::ZoneHandle();
397 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { 399 if (compiler->is_optimizing() && FLAG_propagate_ic_data) {
398 ASSERT(!original_ic_data.IsNull()); 400 ASSERT(!original_ic_data.IsNull());
399 if (original_ic_data.NumberOfChecks() == 0) { 401 if (original_ic_data.NumberOfChecks() == 0) {
400 // IC call for reoptimization populates original ICData. 402 // IC call for reoptimization populates original ICData.
401 equality_ic_data = original_ic_data.raw(); 403 equality_ic_data = original_ic_data.raw();
402 } else { 404 } else {
403 // Megamorphic call. 405 // Megamorphic call.
404 equality_ic_data = original_ic_data.AsUnaryClassChecks(); 406 equality_ic_data = original_ic_data.AsUnaryClassChecks();
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 ASSERT(ic_data.NumberOfChecks() > 0); 531 ASSERT(ic_data.NumberOfChecks() > 0);
530 ASSERT(ic_data.num_args_tested() == 1); 532 ASSERT(ic_data.num_args_tested() == 1);
531 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); 533 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
532 Register left = locs->in(0).reg(); 534 Register left = locs->in(0).reg();
533 Register right = locs->in(1).reg(); 535 Register right = locs->in(1).reg();
534 ASSERT(left == A1); 536 ASSERT(left == A1);
535 ASSERT(right == A0); 537 ASSERT(right == A0);
536 Register temp = locs->temp(0).reg(); 538 Register temp = locs->temp(0).reg();
537 539
538 __ TraceSimMsg("EmitEqualityAsPolymorphicCall"); 540 __ TraceSimMsg("EmitEqualityAsPolymorphicCall");
541 __ Comment("EmitEqualityAsPolymorphicCall");
539 542
540 LoadValueCid(compiler, temp, left, 543 LoadValueCid(compiler, temp, left,
541 (ic_data.GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt); 544 (ic_data.GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
542 // 'temp' contains class-id of the left argument. 545 // 'temp' contains class-id of the left argument.
543 ObjectStore* object_store = Isolate::Current()->object_store(); 546 ObjectStore* object_store = Isolate::Current()->object_store();
544 Condition cond = TokenKindToSmiCondition(kind); 547 Condition cond = TokenKindToSmiCondition(kind);
545 Label done; 548 Label done;
546 const intptr_t len = ic_data.NumberOfChecks(); 549 const intptr_t len = ic_data.NumberOfChecks();
547 for (intptr_t i = 0; i < len; i++) { 550 for (intptr_t i = 0; i < len; i++) {
548 // Assert that the Smi is at position 0, if at all. 551 // Assert that the Smi is at position 0, if at all.
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 __ b(&done); 604 __ b(&done);
602 __ Bind(&next_test); 605 __ Bind(&next_test);
603 } 606 }
604 } 607 }
605 __ Bind(&done); 608 __ Bind(&done);
606 } 609 }
607 610
608 611
609 // Emit code when ICData's targets are all Object == (which is ===). 612 // Emit code when ICData's targets are all Object == (which is ===).
610 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, 613 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler,
611 const ICData& ic_data, 614 const ICData& orig_ic_data,
612 const LocationSummary& locs, 615 const LocationSummary& locs,
613 Token::Kind kind, 616 Token::Kind kind,
614 BranchInstr* branch, 617 BranchInstr* branch,
615 intptr_t deopt_id) { 618 intptr_t deopt_id) {
616 UNIMPLEMENTED(); 619 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
620 Register left = locs.in(0).reg();
621 Register right = locs.in(1).reg();
622 Register temp = locs.temp(0).reg();
623 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
624
625 __ Comment("CheckedStrictEqual");
626
627 __ andi(CMPRES, left, Immediate(kSmiTagMask));
628 __ beq(CMPRES, ZR, deopt);
629 // 'left' is not Smi.
630 Label identity_compare;
631 __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null()));
632 __ beq(right, TMP, &identity_compare);
633 __ beq(left, TMP, &identity_compare);
634
635 __ LoadClassId(temp, left);
636 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks());
637 const intptr_t len = ic_data.NumberOfChecks();
638 for (intptr_t i = 0; i < len; i++) {
639 if (i == (len - 1)) {
640 __ BranchNotEqual(temp, ic_data.GetReceiverClassIdAt(i), deopt);
641 } else {
642 __ BranchEqual(temp, ic_data.GetReceiverClassIdAt(i), &identity_compare);
643 }
644 }
645 __ Bind(&identity_compare);
646 __ subu(CMPRES, left, right);
647 if (branch == NULL) {
648 Label done, is_equal;
649 Register result = locs.out().reg();
650 __ beq(CMPRES, ZR, &is_equal);
651 // Not equal.
652 __ LoadObject(result,
653 (kind == Token::kEQ) ? Bool::False() : Bool::True());
654 __ b(&done);
655 __ Bind(&is_equal);
656 __ LoadObject(result,
657 (kind == Token::kEQ) ? Bool::True() : Bool::False());
658 __ Bind(&done);
659
660 } else {
661 Condition cond = TokenKindToSmiCondition(kind);
662 __ mov(TMP, ZR);
663 branch->EmitBranchOnCondition(compiler, cond);
664 }
617 } 665 }
618 666
619 667
620 // First test if receiver is NULL, in which case === is applied. 668 // First test if receiver is NULL, in which case === is applied.
621 // If type feedback was provided (lists of <class-id, target>), do a 669 // If type feedback was provided (lists of <class-id, target>), do a
622 // type by type check (either === or static call to the operator. 670 // type by type check (either === or static call to the operator.
623 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, 671 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler,
624 LocationSummary* locs, 672 LocationSummary* locs,
625 Token::Kind kind, 673 Token::Kind kind,
626 BranchInstr* branch, 674 BranchInstr* branch,
627 const ICData& ic_data, 675 const ICData& ic_data,
628 intptr_t deopt_id, 676 intptr_t deopt_id,
629 intptr_t token_pos) { 677 intptr_t token_pos) {
630 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); 678 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
631 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); 679 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
632 Register left = locs->in(0).reg(); 680 Register left = locs->in(0).reg();
633 Register right = locs->in(1).reg(); 681 Register right = locs->in(1).reg();
634 Label done, identity_compare, non_null_compare; 682 Label done, identity_compare, non_null_compare;
635 __ TraceSimMsg("EmitGenericEqualityCompare"); 683 __ TraceSimMsg("EmitGenericEqualityCompare");
636 __ beq(right, NULLREG, &identity_compare); 684 __ Comment("EmitGenericEqualityCompare");
637 __ bne(left, NULLREG, &non_null_compare); 685 __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null()));
686 __ beq(right, TMP, &identity_compare);
687 __ bne(left, TMP, &non_null_compare);
638 688
639 // Comparison with NULL is "===". 689 // Comparison with NULL is "===".
640 __ Bind(&identity_compare); 690 __ Bind(&identity_compare);
641 Condition cond = TokenKindToSmiCondition(kind); 691 Condition cond = TokenKindToSmiCondition(kind);
642 __ slt(CMPRES, left, right); 692 __ slt(CMPRES, left, right);
643 __ slt(TMP1, right, left); 693 __ slt(TMP1, right, left);
644 if (branch != NULL) { 694 if (branch != NULL) {
645 branch->EmitBranchOnCondition(compiler, cond); 695 branch->EmitBranchOnCondition(compiler, cond);
646 } else { 696 } else {
647 Register result = locs->out().reg(); 697 Register result = locs->out().reg();
(...skipping 30 matching lines...) Expand all
678 return EQ; 728 return EQ;
679 } 729 }
680 } 730 }
681 731
682 732
683 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 733 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
684 const LocationSummary& locs, 734 const LocationSummary& locs,
685 Token::Kind kind, 735 Token::Kind kind,
686 BranchInstr* branch) { 736 BranchInstr* branch) {
687 __ TraceSimMsg("EmitSmiComparisonOp"); 737 __ TraceSimMsg("EmitSmiComparisonOp");
738 __ Comment("EmitSmiComparisonOp");
688 Location left = locs.in(0); 739 Location left = locs.in(0);
689 Location right = locs.in(1); 740 Location right = locs.in(1);
690 ASSERT(!left.IsConstant() || !right.IsConstant()); 741 ASSERT(!left.IsConstant() || !right.IsConstant());
691 742
692 Condition true_condition = TokenKindToSmiCondition(kind); 743 Condition true_condition = TokenKindToSmiCondition(kind);
693 744
694 if (left.IsConstant()) { 745 if (left.IsConstant()) {
695 __ CompareObject(CMPRES, TMP1, right.reg(), left.constant()); 746 __ CompareObject(CMPRES, TMP1, right.reg(), left.constant());
696 true_condition = FlipCondition(true_condition); 747 true_condition = FlipCondition(true_condition);
697 } else if (right.IsConstant()) { 748 } else if (right.IsConstant()) {
(...skipping 27 matching lines...) Expand all
725 776
726 777
727 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, 778 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
728 const LocationSummary& locs, 779 const LocationSummary& locs,
729 Token::Kind kind, 780 Token::Kind kind,
730 BranchInstr* branch) { 781 BranchInstr* branch) {
731 UNIMPLEMENTED(); 782 UNIMPLEMENTED();
732 } 783 }
733 784
734 785
786 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
787 switch (kind) {
788 case Token::kEQ: return EQ;
789 case Token::kNE: return NE;
790 case Token::kLT: return LT;
791 case Token::kGT: return GT;
792 case Token::kLTE: return LE;
793 case Token::kGTE: return GE;
794 default:
795 UNREACHABLE();
796 return VS;
797 }
798 }
799
800
735 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 801 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
736 const LocationSummary& locs, 802 const LocationSummary& locs,
737 Token::Kind kind, 803 Token::Kind kind,
738 BranchInstr* branch) { 804 BranchInstr* branch) {
739 UNIMPLEMENTED(); 805 DRegister left = locs.in(0).fpu_reg();
806 DRegister right = locs.in(1).fpu_reg();
807
808 __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right);
809
810 Condition true_condition = TokenKindToDoubleCondition(kind);
811 if (branch != NULL) {
812 compiler->EmitDoubleCompareBranch(
813 true_condition, left, right, branch);
814 } else {
815 compiler->EmitDoubleCompareBool(
816 true_condition, left, right, locs.out().reg());
817 }
740 } 818 }
741 819
742 820
743 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 821 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
744 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 822 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
745 BranchInstr* kNoBranch = NULL; 823 BranchInstr* kNoBranch = NULL;
824 __ Comment("EqualityCompareInstr");
746 if (receiver_class_id() == kSmiCid) { 825 if (receiver_class_id() == kSmiCid) {
747 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); 826 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch);
748 return; 827 return;
749 } 828 }
750 if (receiver_class_id() == kMintCid) { 829 if (receiver_class_id() == kMintCid) {
751 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch); 830 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch);
752 return; 831 return;
753 } 832 }
754 if (receiver_class_id() == kDoubleCid) { 833 if (receiver_class_id() == kDoubleCid) {
755 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); 834 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
(...skipping 22 matching lines...) Expand all
778 kind(), 857 kind(),
779 locs(), 858 locs(),
780 *ic_data()); 859 *ic_data());
781 ASSERT(locs()->out().reg() == V0); 860 ASSERT(locs()->out().reg() == V0);
782 } 861 }
783 862
784 863
785 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 864 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
786 BranchInstr* branch) { 865 BranchInstr* branch) {
787 __ TraceSimMsg("EqualityCompareInstr"); 866 __ TraceSimMsg("EqualityCompareInstr");
867 __ Comment("EqualityCompareInstr:BranchCode");
788 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 868 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
789 if (receiver_class_id() == kSmiCid) { 869 if (receiver_class_id() == kSmiCid) {
790 // Deoptimizes if both arguments not Smi. 870 // Deoptimizes if both arguments not Smi.
791 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); 871 EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
792 return; 872 return;
793 } 873 }
794 if (receiver_class_id() == kMintCid) { 874 if (receiver_class_id() == kMintCid) {
795 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch); 875 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch);
796 return; 876 return;
797 } 877 }
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
994 __ AddImmediate(A2, FP, (kParamEndSlotFromFp + 1074 __ AddImmediate(A2, FP, (kParamEndSlotFromFp +
995 function().NumParameters()) * kWordSize); 1075 function().NumParameters()) * kWordSize);
996 } else { 1076 } else {
997 __ AddImmediate(A2, FP, kFirstLocalSlotFromFp * kWordSize); 1077 __ AddImmediate(A2, FP, kFirstLocalSlotFromFp * kWordSize);
998 } 1078 }
999 // Compute the effective address. When running under the simulator, 1079 // Compute the effective address. When running under the simulator,
1000 // this is a redirection address that forces the simulator to call 1080 // this is a redirection address that forces the simulator to call
1001 // into the runtime system. 1081 // into the runtime system.
1002 uword entry = reinterpret_cast<uword>(native_c_function()); 1082 uword entry = reinterpret_cast<uword>(native_c_function());
1003 #if defined(USING_SIMULATOR) 1083 #if defined(USING_SIMULATOR)
1004 entry = Simulator::RedirectExternalReference(entry, Simulator::kNativeCall); 1084 entry = Simulator::RedirectExternalReference(entry,
1085 Simulator::kNativeCall,
1086 function().NumParameters());
1005 #endif 1087 #endif
1006 __ LoadImmediate(T5, entry); 1088 __ LoadImmediate(T5, entry);
1007 __ LoadImmediate(A1, NativeArguments::ComputeArgcTag(function())); 1089 __ LoadImmediate(A1, NativeArguments::ComputeArgcTag(function()));
1008 compiler->GenerateCall(token_pos(), 1090 compiler->GenerateCall(token_pos(),
1009 &StubCode::CallNativeCFunctionLabel(), 1091 &StubCode::CallNativeCFunctionLabel(),
1010 PcDescriptors::kOther, 1092 PcDescriptors::kOther,
1011 locs()); 1093 locs());
1012 __ Pop(result); 1094 __ Pop(result);
1013 } 1095 }
1014 1096
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1198 UNREACHABLE(); 1280 UNREACHABLE();
1199 } 1281 }
1200 __ addu(index.reg(), array, index.reg()); 1282 __ addu(index.reg(), array, index.reg());
1201 element_address = Address(index.reg(), 1283 element_address = Address(index.reg(),
1202 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); 1284 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
1203 } 1285 }
1204 1286
1205 if ((representation() == kUnboxedDouble) || 1287 if ((representation() == kUnboxedDouble) ||
1206 (representation() == kUnboxedMint) || 1288 (representation() == kUnboxedMint) ||
1207 (representation() == kUnboxedFloat32x4)) { 1289 (representation() == kUnboxedFloat32x4)) {
1208 UNIMPLEMENTED(); 1290 DRegister result = locs()->out().fpu_reg();
1291 switch (class_id()) {
1292 case kTypedDataInt32ArrayCid:
1293 UNIMPLEMENTED();
1294 break;
1295 case kTypedDataUint32ArrayCid:
1296 UNIMPLEMENTED();
1297 break;
1298 case kTypedDataFloat32ArrayCid:
1299 // Load single precision float and promote to double.
1300 __ lwc1(STMP1, element_address);
1301 __ cvtds(result, STMP1);
1302 break;
1303 case kTypedDataFloat64ArrayCid:
1304 __ LoadDFromOffset(result, index.reg(),
1305 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
1306 break;
1307 case kTypedDataFloat32x4ArrayCid:
1308 UNIMPLEMENTED();
1309 break;
1310 }
1311 return;
1209 } 1312 }
1210 1313
1211 Register result = locs()->out().reg(); 1314 Register result = locs()->out().reg();
1212 switch (class_id()) { 1315 switch (class_id()) {
1213 case kTypedDataInt8ArrayCid: 1316 case kTypedDataInt8ArrayCid:
1214 ASSERT(index_scale() == 1); 1317 ASSERT(index_scale() == 1);
1215 __ lb(result, element_address); 1318 __ lb(result, element_address);
1216 __ SmiTag(result); 1319 __ SmiTag(result);
1217 break; 1320 break;
1218 case kTypedDataUint8ArrayCid: 1321 case kTypedDataUint8ArrayCid:
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
1575 1678
1576 if (field_cid != kSmiCid) { 1679 if (field_cid != kSmiCid) {
1577 __ beq(CMPRES, ZR, fail); 1680 __ beq(CMPRES, ZR, fail);
1578 __ LoadClassId(value_cid_reg, value_reg); 1681 __ LoadClassId(value_cid_reg, value_reg);
1579 __ LoadImmediate(TMP1, field_cid); 1682 __ LoadImmediate(TMP1, field_cid);
1580 __ subu(CMPRES, value_cid_reg, TMP1); 1683 __ subu(CMPRES, value_cid_reg, TMP1);
1581 } 1684 }
1582 1685
1583 if (field().is_nullable() && (field_cid != kNullCid)) { 1686 if (field().is_nullable() && (field_cid != kNullCid)) {
1584 __ beq(CMPRES, ZR, &ok); 1687 __ beq(CMPRES, ZR, &ok);
1585 __ subu(CMPRES, value_reg, NULLREG); 1688 __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null()));
1689 __ subu(CMPRES, value_reg, TMP);
1586 } 1690 }
1587 1691
1588 if (ok_is_fall_through) { 1692 if (ok_is_fall_through) {
1589 __ bne(CMPRES, ZR, fail); 1693 __ bne(CMPRES, ZR, fail);
1590 } else { 1694 } else {
1591 __ beq(CMPRES, ZR, &ok); 1695 __ beq(CMPRES, ZR, &ok);
1592 } 1696 }
1593 } else { 1697 } else {
1594 // Both value's and field's class id is known. 1698 // Both value's and field's class id is known.
1595 if ((value_cid != field_cid) && (value_cid != nullability)) { 1699 if ((value_cid != field_cid) && (value_cid != nullability)) {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1696 __ StoreIntoObject(temp, 1800 __ StoreIntoObject(temp,
1697 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi()); 1801 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi());
1698 } else { 1802 } else {
1699 __ StoreIntoObjectNoBarrier( 1803 __ StoreIntoObjectNoBarrier(
1700 temp, FieldAddress(temp, Field::value_offset()), value); 1804 temp, FieldAddress(temp, Field::value_offset()), value);
1701 } 1805 }
1702 } 1806 }
1703 1807
1704 1808
1705 LocationSummary* InstanceOfInstr::MakeLocationSummary() const { 1809 LocationSummary* InstanceOfInstr::MakeLocationSummary() const {
1706 UNIMPLEMENTED(); 1810 const intptr_t kNumInputs = 3;
1707 return NULL; 1811 const intptr_t kNumTemps = 0;
1812 LocationSummary* summary =
1813 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
1814 summary->set_in(0, Location::RegisterLocation(A0));
1815 summary->set_in(1, Location::RegisterLocation(A2));
1816 summary->set_in(2, Location::RegisterLocation(A1));
1817 summary->set_out(Location::RegisterLocation(V0));
1818 return summary;
1708 } 1819 }
1709 1820
1710 1821
1711 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1822 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1712 UNIMPLEMENTED(); 1823 ASSERT(locs()->in(0).reg() == A0); // Value.
1824 ASSERT(locs()->in(1).reg() == A2); // Instantiator.
1825 ASSERT(locs()->in(2).reg() == A1); // Instantiator type arguments.
1826
1827 __ Comment("InstanceOfInstr");
1828 compiler->GenerateInstanceOf(token_pos(),
1829 deopt_id(),
1830 type(),
1831 negate_result(),
1832 locs());
1833 ASSERT(locs()->out().reg() == V0);
1713 } 1834 }
1714 1835
1715 1836
1716 LocationSummary* CreateArrayInstr::MakeLocationSummary() const { 1837 LocationSummary* CreateArrayInstr::MakeLocationSummary() const {
1717 const intptr_t kNumInputs = 1; 1838 const intptr_t kNumInputs = 1;
1718 const intptr_t kNumTemps = 0; 1839 const intptr_t kNumTemps = 0;
1719 LocationSummary* locs = 1840 LocationSummary* locs =
1720 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 1841 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
1721 locs->set_in(0, Location::RegisterLocation(A0)); 1842 locs->set_in(0, Location::RegisterLocation(A0));
1722 locs->set_out(Location::RegisterLocation(V0)); 1843 locs->set_out(Location::RegisterLocation(V0));
1723 return locs; 1844 return locs;
1724 } 1845 }
1725 1846
1726 1847
1727 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1848 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1728 __ TraceSimMsg("CreateArrayInstr"); 1849 __ TraceSimMsg("CreateArrayInstr");
1729 // Allocate the array. A1 = length, A0 = element type. 1850 // Allocate the array. A1 = length, A0 = element type.
1730 ASSERT(locs()->in(0).reg() == A0); 1851 ASSERT(locs()->in(0).reg() == A0);
1731 __ LoadImmediate(A1, Smi::RawValue(num_elements())); 1852 __ LoadImmediate(A1, Smi::RawValue(num_elements()));
1732 compiler->GenerateCall(token_pos(), 1853 compiler->GenerateCall(token_pos(),
1733 &StubCode::AllocateArrayLabel(), 1854 &StubCode::AllocateArrayLabel(),
1734 PcDescriptors::kOther, 1855 PcDescriptors::kOther,
1735 locs()); 1856 locs());
1736 ASSERT(locs()->out().reg() == V0); 1857 ASSERT(locs()->out().reg() == V0);
1737 } 1858 }
1738 1859
1739 1860
1740 LocationSummary* 1861 LocationSummary*
1741 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const { 1862 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const {
1742 UNIMPLEMENTED(); 1863 return MakeCallSummary();
1743 return NULL;
1744 } 1864 }
1745 1865
1746 1866
1747 void AllocateObjectWithBoundsCheckInstr::EmitNativeCode( 1867 void AllocateObjectWithBoundsCheckInstr::EmitNativeCode(
1748 FlowGraphCompiler* compiler) { 1868 FlowGraphCompiler* compiler) {
1749 UNIMPLEMENTED(); 1869 compiler->GenerateCallRuntime(token_pos(),
1870 deopt_id(),
1871 kAllocateObjectWithBoundsCheckRuntimeEntry,
1872 locs());
1873 __ Drop(3);
1874 ASSERT(locs()->out().reg() == V0);
1875 __ Pop(V0); // Pop new instance.
1750 } 1876 }
1751 1877
1752 1878
1753 LocationSummary* LoadFieldInstr::MakeLocationSummary() const { 1879 LocationSummary* LoadFieldInstr::MakeLocationSummary() const {
1754 return LocationSummary::Make(1, 1880 return LocationSummary::Make(1,
1755 Location::RequiresRegister(), 1881 Location::RequiresRegister(),
1756 LocationSummary::kNoCall); 1882 LocationSummary::kNoCall);
1757 } 1883 }
1758 1884
1759 1885
(...skipping 26 matching lines...) Expand all
1786 // (or null). 1912 // (or null).
1787 ASSERT(!type_arguments().IsUninstantiatedIdentity() && 1913 ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
1788 !type_arguments().CanShareInstantiatorTypeArguments( 1914 !type_arguments().CanShareInstantiatorTypeArguments(
1789 instantiator_class())); 1915 instantiator_class()));
1790 // If the instantiator is null and if the type argument vector 1916 // If the instantiator is null and if the type argument vector
1791 // instantiated from null becomes a vector of dynamic, then use null as 1917 // instantiated from null becomes a vector of dynamic, then use null as
1792 // the type arguments. 1918 // the type arguments.
1793 Label type_arguments_instantiated; 1919 Label type_arguments_instantiated;
1794 const intptr_t len = type_arguments().Length(); 1920 const intptr_t len = type_arguments().Length();
1795 if (type_arguments().IsRawInstantiatedRaw(len)) { 1921 if (type_arguments().IsRawInstantiatedRaw(len)) {
1796 __ beq(instantiator_reg, NULLREG, &type_arguments_instantiated); 1922 __ BranchEqual(instantiator_reg, reinterpret_cast<int32_t>(Object::null()),
1923 &type_arguments_instantiated);
1797 } 1924 }
1798 // Instantiate non-null type arguments. 1925 // Instantiate non-null type arguments.
1799 // A runtime call to instantiate the type arguments is required. 1926 // A runtime call to instantiate the type arguments is required.
1800 __ addiu(SP, SP, Immediate(-3 * kWordSize)); 1927 __ addiu(SP, SP, Immediate(-3 * kWordSize));
1801 __ LoadObject(TMP1, Object::ZoneHandle()); 1928 __ LoadObject(TMP1, Object::ZoneHandle());
1802 __ sw(TMP1, Address(SP, 2 * kWordSize)); // Make room for the result. 1929 __ sw(TMP1, Address(SP, 2 * kWordSize)); // Make room for the result.
1803 __ LoadObject(TMP1, type_arguments()); 1930 __ LoadObject(TMP1, type_arguments());
1804 __ sw(TMP1, Address(SP, 1 * kWordSize)); 1931 __ sw(TMP1, Address(SP, 1 * kWordSize));
1805 // Push instantiator type arguments. 1932 // Push instantiator type arguments.
1806 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); 1933 __ sw(instantiator_reg, Address(SP, 0 * kWordSize));
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1839 // instantiator_reg is the instantiator type argument vector, i.e. an 1966 // instantiator_reg is the instantiator type argument vector, i.e. an
1840 // AbstractTypeArguments object (or null). 1967 // AbstractTypeArguments object (or null).
1841 ASSERT(!type_arguments().IsUninstantiatedIdentity() && 1968 ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
1842 !type_arguments().CanShareInstantiatorTypeArguments( 1969 !type_arguments().CanShareInstantiatorTypeArguments(
1843 instantiator_class())); 1970 instantiator_class()));
1844 // If the instantiator is null and if the type argument vector 1971 // If the instantiator is null and if the type argument vector
1845 // instantiated from null becomes a vector of dynamic, then use null as 1972 // instantiated from null becomes a vector of dynamic, then use null as
1846 // the type arguments. 1973 // the type arguments.
1847 Label type_arguments_instantiated; 1974 Label type_arguments_instantiated;
1848 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); 1975 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
1849 __ beq(instantiator_reg, NULLREG, &type_arguments_instantiated); 1976 __ BranchEqual(instantiator_reg, reinterpret_cast<int32_t>(Object::null()),
1977 &type_arguments_instantiated);
1850 // Instantiate non-null type arguments. 1978 // Instantiate non-null type arguments.
1851 // In the non-factory case, we rely on the allocation stub to 1979 // In the non-factory case, we rely on the allocation stub to
1852 // instantiate the type arguments. 1980 // instantiate the type arguments.
1853 __ LoadObject(result_reg, type_arguments()); 1981 __ LoadObject(result_reg, type_arguments());
1854 // result_reg: uninstantiated type arguments. 1982 // result_reg: uninstantiated type arguments.
1855 __ Bind(&type_arguments_instantiated); 1983 __ Bind(&type_arguments_instantiated);
1856 1984
1857 // result_reg: uninstantiated or instantiated type arguments. 1985 // result_reg: uninstantiated or instantiated type arguments.
1858 } 1986 }
1859 1987
(...skipping 19 matching lines...) Expand all
1879 // (or null). 2007 // (or null).
1880 ASSERT(!type_arguments().IsUninstantiatedIdentity() && 2008 ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
1881 !type_arguments().CanShareInstantiatorTypeArguments( 2009 !type_arguments().CanShareInstantiatorTypeArguments(
1882 instantiator_class())); 2010 instantiator_class()));
1883 2011
1884 // If the instantiator is null and if the type argument vector 2012 // If the instantiator is null and if the type argument vector
1885 // instantiated from null becomes a vector of dynamic, then use null as 2013 // instantiated from null becomes a vector of dynamic, then use null as
1886 // the type arguments and do not pass the instantiator. 2014 // the type arguments and do not pass the instantiator.
1887 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); 2015 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
1888 Label instantiator_not_null; 2016 Label instantiator_not_null;
1889 __ bne(instantiator_reg, NULLREG, &instantiator_not_null); 2017 __ BranchNotEqual(instantiator_reg, reinterpret_cast<int32_t>(Object::null()),
2018 &instantiator_not_null);
1890 // Null was used in VisitExtractConstructorTypeArguments as the 2019 // Null was used in VisitExtractConstructorTypeArguments as the
1891 // instantiated type arguments, no proper instantiator needed. 2020 // instantiated type arguments, no proper instantiator needed.
1892 __ LoadImmediate(instantiator_reg, 2021 __ LoadImmediate(instantiator_reg,
1893 Smi::RawValue(StubCode::kNoInstantiator)); 2022 Smi::RawValue(StubCode::kNoInstantiator));
1894 __ Bind(&instantiator_not_null); 2023 __ Bind(&instantiator_not_null);
1895 // instantiator_reg: instantiator or kNoInstantiator. 2024 // instantiator_reg: instantiator or kNoInstantiator.
1896 } 2025 }
1897 2026
1898 2027
1899 LocationSummary* AllocateContextInstr::MakeLocationSummary() const { 2028 LocationSummary* AllocateContextInstr::MakeLocationSummary() const {
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
2060 2189
2061 __ TraceSimMsg("EmitSmiShiftLeft"); 2190 __ TraceSimMsg("EmitSmiShiftLeft");
2062 2191
2063 if (locs.in(1).IsConstant()) { 2192 if (locs.in(1).IsConstant()) {
2064 const Object& constant = locs.in(1).constant(); 2193 const Object& constant = locs.in(1).constant();
2065 ASSERT(constant.IsSmi()); 2194 ASSERT(constant.IsSmi());
2066 // Immediate shift operation takes 5 bits for the count. 2195 // Immediate shift operation takes 5 bits for the count.
2067 const intptr_t kCountLimit = 0x1F; 2196 const intptr_t kCountLimit = 0x1F;
2068 const intptr_t value = Smi::Cast(constant).Value(); 2197 const intptr_t value = Smi::Cast(constant).Value();
2069 if (value == 0) { 2198 if (value == 0) {
2070 // No code needed. 2199 if (result != left) {
2200 __ mov(result, left);
2201 }
2071 } else if ((value < 0) || (value >= kCountLimit)) { 2202 } else if ((value < 0) || (value >= kCountLimit)) {
2072 // This condition may not be known earlier in some cases because 2203 // This condition may not be known earlier in some cases because
2073 // of constant propagation, inlining, etc. 2204 // of constant propagation, inlining, etc.
2074 if ((value >= kCountLimit) && is_truncating) { 2205 if ((value >= kCountLimit) && is_truncating) {
2075 __ mov(result, ZR); 2206 __ mov(result, ZR);
2076 } else { 2207 } else {
2077 // Result is Mint or exception. 2208 // Result is Mint or exception.
2078 __ b(deopt); 2209 __ b(deopt);
2079 } 2210 }
2080 } else { 2211 } else {
(...skipping 13 matching lines...) Expand all
2094 Register right = locs.in(1).reg(); 2225 Register right = locs.in(1).reg();
2095 Range* right_range = shift_left->right()->definition()->range(); 2226 Range* right_range = shift_left->right()->definition()->range();
2096 if (shift_left->left()->BindsToConstant() && !is_truncating) { 2227 if (shift_left->left()->BindsToConstant() && !is_truncating) {
2097 // TODO(srdjan): Implement code below for is_truncating(). 2228 // TODO(srdjan): Implement code below for is_truncating().
2098 // If left is constant, we know the maximal allowed size for right. 2229 // If left is constant, we know the maximal allowed size for right.
2099 const Object& obj = shift_left->left()->BoundConstant(); 2230 const Object& obj = shift_left->left()->BoundConstant();
2100 if (obj.IsSmi()) { 2231 if (obj.IsSmi()) {
2101 const intptr_t left_int = Smi::Cast(obj).Value(); 2232 const intptr_t left_int = Smi::Cast(obj).Value();
2102 if (left_int == 0) { 2233 if (left_int == 0) {
2103 __ bltz(right, deopt); 2234 __ bltz(right, deopt);
2235 __ mov(result, ZR);
2104 return; 2236 return;
2105 } 2237 }
2106 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); 2238 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
2107 const bool right_needs_check = 2239 const bool right_needs_check =
2108 (right_range == NULL) || 2240 (right_range == NULL) ||
2109 !right_range->IsWithin(0, max_right - 1); 2241 !right_range->IsWithin(0, max_right - 1);
2110 if (right_needs_check) { 2242 if (right_needs_check) {
2111 __ BranchUnsignedGreaterEqual( 2243 __ BranchUnsignedGreaterEqual(
2112 right, reinterpret_cast<int32_t>(Smi::New(max_right)), deopt); 2244 right, reinterpret_cast<int32_t>(Smi::New(max_right)), deopt);
2113 } 2245 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2156 __ srav(TMP1, TMP1, right); 2288 __ srav(TMP1, TMP1, right);
2157 __ bne(TMP1, left, deopt); // Overflow. 2289 __ bne(TMP1, left, deopt); // Overflow.
2158 // Shift for result now we know there is no overflow. 2290 // Shift for result now we know there is no overflow.
2159 __ sllv(result, left, right); 2291 __ sllv(result, left, right);
2160 } 2292 }
2161 } 2293 }
2162 2294
2163 2295
2164 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { 2296 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
2165 const intptr_t kNumInputs = 2; 2297 const intptr_t kNumInputs = 2;
2298 const intptr_t kNumTemps = op_kind() == Token::kADD ? 1 : 0;
2299 LocationSummary* summary =
2300 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2166 if (op_kind() == Token::kTRUNCDIV) { 2301 if (op_kind() == Token::kTRUNCDIV) {
2167 UNIMPLEMENTED(); 2302 if (RightIsPowerOfTwoConstant()) {
2168 return NULL; 2303 summary->set_in(0, Location::RequiresRegister());
2169 } else { 2304 ConstantInstr* right_constant = right()->definition()->AsConstant();
2170 const intptr_t kNumTemps = op_kind() == Token::kADD ? 1 : 0; 2305 summary->set_in(1, Location::Constant(right_constant->value()));
2171 LocationSummary* summary = 2306 summary->set_out(Location::RequiresRegister());
2172 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2307 } else {
2173 summary->set_in(0, Location::RequiresRegister()); 2308 // Both inputs must be writable because they will be untagged.
2174 summary->set_in(1, Location::RegisterOrSmiConstant(right())); 2309 summary->set_in(0, Location::WritableRegister());
2175 if (op_kind() == Token::kADD) { 2310 summary->set_in(1, Location::WritableRegister());
2176 // Need an extra temp for the overflow detection code. 2311 summary->set_out(Location::RequiresRegister());
2177 summary->set_temp(0, Location::RequiresRegister());
2178 } 2312 }
2179 // We make use of 3-operand instructions by not requiring result register
2180 // to be identical to first input register as on Intel.
2181 summary->set_out(Location::RequiresRegister());
2182 return summary; 2313 return summary;
2183 } 2314 }
2315 summary->set_in(0, Location::RequiresRegister());
2316 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
2317 if (op_kind() == Token::kADD) {
2318 // Need an extra temp for the overflow detection code.
2319 summary->set_temp(0, Location::RequiresRegister());
2320 }
2321 // We make use of 3-operand instructions by not requiring result register
2322 // to be identical to first input register as on Intel.
2323 summary->set_out(Location::RequiresRegister());
2324 return summary;
2184 } 2325 }
2185 2326
2186 2327
2187 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2328 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2188 __ TraceSimMsg("BinarySmiOpInstr"); 2329 __ TraceSimMsg("BinarySmiOpInstr");
2189 if (op_kind() == Token::kSHL) { 2330 if (op_kind() == Token::kSHL) {
2190 EmitSmiShiftLeft(compiler, this); 2331 EmitSmiShiftLeft(compiler, this);
2191 return; 2332 return;
2192 } 2333 }
2193 2334
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2244 __ mult(left, TMP1); 2385 __ mult(left, TMP1);
2245 __ mflo(result); 2386 __ mflo(result);
2246 __ mfhi(TMP1); 2387 __ mfhi(TMP1);
2247 } 2388 }
2248 __ sra(CMPRES, result, 31); 2389 __ sra(CMPRES, result, 31);
2249 __ bne(TMP1, CMPRES, deopt); 2390 __ bne(TMP1, CMPRES, deopt);
2250 } 2391 }
2251 break; 2392 break;
2252 } 2393 }
2253 case Token::kTRUNCDIV: { 2394 case Token::kTRUNCDIV: {
2254 UNIMPLEMENTED(); 2395 const intptr_t value = Smi::Cast(constant).Value();
2396 if (value == 1) {
2397 if (result != left) {
2398 __ mov(result, left);
2399 }
2400 break;
2401 } else if (value == -1) {
2402 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
2403 // case we cannot negate the result.
2404 __ BranchEqual(left, 0x80000000, deopt);
2405 __ subu(result, ZR, left);
2406 break;
2407 }
2408 ASSERT((value != 0) && Utils::IsPowerOfTwo(Utils::Abs(value)));
2409 const intptr_t shift_count =
2410 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
2411 ASSERT(kSmiTagSize == 1);
2412 __ sra(TMP, left, 31);
2413 ASSERT(shift_count > 1); // 1, -1 case handled above.
2414 __ sll(TMP, TMP, 32 - shift_count);
2415 __ addu(left, left, TMP);
2416 ASSERT(shift_count > 0);
2417 __ sra(result, left, shift_count);
2418 if (value < 0) {
2419 __ subu(result, ZR, result);
2420 }
2421 __ SmiTag(result);
2255 break; 2422 break;
2256 } 2423 }
2257 case Token::kBIT_AND: { 2424 case Token::kBIT_AND: {
2258 // No overflow check. 2425 // No overflow check.
2259 if (Utils::IsUint(kImmBits, imm)) { 2426 if (Utils::IsUint(kImmBits, imm)) {
2260 __ andi(result, left, Immediate(imm)); 2427 __ andi(result, left, Immediate(imm));
2261 } else { 2428 } else {
2262 __ LoadImmediate(TMP1, imm); 2429 __ LoadImmediate(TMP1, imm);
2263 __ and_(result, left, TMP1); 2430 __ and_(result, left, TMP1);
2264 } 2431 }
(...skipping 21 matching lines...) Expand all
2286 } 2453 }
2287 case Token::kSHR: { 2454 case Token::kSHR: {
2288 // sarl operation masks the count to 5 bits. 2455 // sarl operation masks the count to 5 bits.
2289 const intptr_t kCountLimit = 0x1F; 2456 const intptr_t kCountLimit = 0x1F;
2290 intptr_t value = Smi::Cast(constant).Value(); 2457 intptr_t value = Smi::Cast(constant).Value();
2291 2458
2292 __ TraceSimMsg("kSHR"); 2459 __ TraceSimMsg("kSHR");
2293 2460
2294 if (value == 0) { 2461 if (value == 0) {
2295 // TODO(vegorov): should be handled outside. 2462 // TODO(vegorov): should be handled outside.
2296 __ break_(0); 2463 if (result != left) {
2464 __ mov(result, left);
2465 }
2297 break; 2466 break;
2298 } else if (value < 0) { 2467 } else if (value < 0) {
2299 // TODO(vegorov): should be handled outside. 2468 // TODO(vegorov): should be handled outside.
2300 __ b(deopt); 2469 __ b(deopt);
2301 break; 2470 break;
2302 } 2471 }
2303 2472
2304 value = value + kSmiTagSize; 2473 value = value + kSmiTagSize;
2305 if (value >= kCountLimit) value = kCountLimit; 2474 if (value >= kCountLimit) value = kCountLimit;
2306 2475
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2359 // No overflow check. 2528 // No overflow check.
2360 __ or_(result, left, right); 2529 __ or_(result, left, right);
2361 break; 2530 break;
2362 } 2531 }
2363 case Token::kBIT_XOR: { 2532 case Token::kBIT_XOR: {
2364 // No overflow check. 2533 // No overflow check.
2365 __ xor_(result, left, right); 2534 __ xor_(result, left, right);
2366 break; 2535 break;
2367 } 2536 }
2368 case Token::kTRUNCDIV: { 2537 case Token::kTRUNCDIV: {
2369 UNIMPLEMENTED(); 2538 // Handle divide by zero in runtime.
2539 __ beq(right, ZR, deopt);
2540 __ SmiUntag(left);
2541 __ SmiUntag(right);
2542 __ div(left, right);
2543 __ mflo(result);
2544 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
2545 // case we cannot tag the result.
2546 __ BranchEqual(V0, 0x40000000, deopt);
2547 __ SmiTag(result);
2370 break; 2548 break;
2371 } 2549 }
2372 case Token::kSHR: { 2550 case Token::kSHR: {
2373 UNIMPLEMENTED(); 2551 UNIMPLEMENTED();
2374 break; 2552 break;
2375 } 2553 }
2376 case Token::kDIV: { 2554 case Token::kDIV: {
2377 // Dispatches to 'Double./'. 2555 // Dispatches to 'Double./'.
2378 // TODO(srdjan): Implement as conversion to double and double division. 2556 // TODO(srdjan): Implement as conversion to double and double division.
2379 UNREACHABLE(); 2557 UNREACHABLE();
(...skipping 12 matching lines...) Expand all
2392 break; 2570 break;
2393 } 2571 }
2394 default: 2572 default:
2395 UNREACHABLE(); 2573 UNREACHABLE();
2396 break; 2574 break;
2397 } 2575 }
2398 } 2576 }
2399 2577
2400 2578
2401 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const { 2579 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
2402 UNIMPLEMENTED(); 2580 intptr_t left_cid = left()->Type()->ToCid();
2403 return NULL; 2581 intptr_t right_cid = right()->Type()->ToCid();
2582 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
2583 const intptr_t kNumInputs = 2;
2584 const intptr_t kNumTemps = 0;
2585 LocationSummary* summary =
2586 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2587 summary->set_in(0, Location::RequiresRegister());
2588 summary->set_in(1, Location::RequiresRegister());
2589 return summary;
2404 } 2590 }
2405 2591
2406 2592
2407 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2593 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2408 UNIMPLEMENTED(); 2594 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryDoubleOp);
2595 intptr_t left_cid = left()->Type()->ToCid();
2596 intptr_t right_cid = right()->Type()->ToCid();
2597 Register left = locs()->in(0).reg();
2598 Register right = locs()->in(1).reg();
2599 if (left_cid == kSmiCid) {
2600 __ andi(CMPRES, right, Immediate(kSmiTagMask));
2601 } else if (right_cid == kSmiCid) {
2602 __ andi(CMPRES, left, Immediate(kSmiTagMask));
2603 } else {
2604 __ or_(TMP, left, right);
2605 __ andi(CMPRES, TMP, Immediate(kSmiTagMask));
2606 }
2607 __ beq(CMPRES, ZR, deopt);
2409 } 2608 }
2410 2609
2411 2610
2412 LocationSummary* BoxDoubleInstr::MakeLocationSummary() const { 2611 LocationSummary* BoxDoubleInstr::MakeLocationSummary() const {
2413 UNIMPLEMENTED(); 2612 const intptr_t kNumInputs = 1;
2414 return NULL; 2613 const intptr_t kNumTemps = 0;
2614 LocationSummary* summary =
2615 new LocationSummary(kNumInputs,
2616 kNumTemps,
2617 LocationSummary::kCallOnSlowPath);
2618 summary->set_in(0, Location::RequiresFpuRegister());
2619 summary->set_out(Location::RequiresRegister());
2620 return summary;
2415 } 2621 }
2416 2622
2417 2623
2624 class BoxDoubleSlowPath : public SlowPathCode {
2625 public:
2626 explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction)
2627 : instruction_(instruction) { }
2628
2629 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
2630 __ Comment("BoxDoubleSlowPath");
2631 __ Bind(entry_label());
2632 const Class& double_class = compiler->double_class();
2633 const Code& stub =
2634 Code::Handle(StubCode::GetAllocationStubForClass(double_class));
2635 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
2636
2637 LocationSummary* locs = instruction_->locs();
2638 locs->live_registers()->Remove(locs->out());
2639
2640 compiler->SaveLiveRegisters(locs);
2641 compiler->GenerateCall(Scanner::kDummyTokenIndex, // No token position.
2642 &label,
2643 PcDescriptors::kOther,
2644 locs);
2645 if (locs->out().reg() != V0) {
2646 __ mov(locs->out().reg(), V0);
2647 }
2648 compiler->RestoreLiveRegisters(locs);
2649
2650 __ b(exit_label());
2651 }
2652
2653 private:
2654 BoxDoubleInstr* instruction_;
2655 };
2656
2657
2418 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2658 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2419 UNIMPLEMENTED(); 2659 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
2660 compiler->AddSlowPathCode(slow_path);
2661
2662 Register out_reg = locs()->out().reg();
2663 DRegister value = locs()->in(0).fpu_reg();
2664
2665 __ TryAllocate(compiler->double_class(),
2666 slow_path->entry_label(),
2667 out_reg);
2668 __ Bind(slow_path->exit_label());
2669 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag);
2420 } 2670 }
2421 2671
2422 2672
2423 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { 2673 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const {
2424 UNIMPLEMENTED(); 2674 const intptr_t kNumInputs = 1;
2425 return NULL; 2675 const intptr_t value_cid = value()->Type()->ToCid();
2676 const bool needs_writable_input = (value_cid == kSmiCid);
2677 const intptr_t kNumTemps = 0;
2678 LocationSummary* summary =
2679 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2680 summary->set_in(0, needs_writable_input
2681 ? Location::WritableRegister()
2682 : Location::RequiresRegister());
2683 summary->set_out(Location::RequiresFpuRegister());
2684 return summary;
2426 } 2685 }
2427 2686
2428 2687
2429 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2688 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2430 UNIMPLEMENTED(); 2689 const intptr_t value_cid = value()->Type()->ToCid();
2690 const Register value = locs()->in(0).reg();
2691 const DRegister result = locs()->out().fpu_reg();
2692
2693 if (value_cid == kDoubleCid) {
2694 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag);
2695 } else if (value_cid == kSmiCid) {
2696 __ SmiUntag(value); // Untag input before conversion.
2697 __ mtc1(value, STMP1);
2698 __ cvtdw(result, STMP1);
2699 } else {
2700 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp);
2701 Label is_smi, done;
2702
2703 __ andi(CMPRES, value, Immediate(kSmiTagMask));
2704 __ beq(CMPRES, ZR, &is_smi);
2705 __ LoadClassId(TMP, value);
2706 __ BranchNotEqual(TMP, kDoubleCid, deopt);
2707 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag);
2708 __ b(&done);
2709 __ Bind(&is_smi);
2710 // TODO(regis): Why do we preserve value here but not above?
2711 __ sra(TMP, value, 1);
2712 __ mtc1(TMP, STMP1);
2713 __ cvtdw(result, STMP1);
2714 __ Bind(&done);
2715 }
2431 } 2716 }
2432 2717
2433 2718
2434 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary() const { 2719 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary() const {
2435 UNIMPLEMENTED(); 2720 UNIMPLEMENTED();
2436 return NULL; 2721 return NULL;
2437 } 2722 }
2438 2723
2439 2724
2440 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 2725 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 28 matching lines...) Expand all
2469 return NULL; 2754 return NULL;
2470 } 2755 }
2471 2756
2472 2757
2473 void UnboxUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 2758 void UnboxUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
2474 UNIMPLEMENTED(); 2759 UNIMPLEMENTED();
2475 } 2760 }
2476 2761
2477 2762
2478 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const { 2763 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const {
2479 UNIMPLEMENTED(); 2764 const intptr_t kNumInputs = 2;
2480 return NULL; 2765 const intptr_t kNumTemps = 0;
2766 LocationSummary* summary =
2767 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2768 summary->set_in(0, Location::RequiresFpuRegister());
2769 summary->set_in(1, Location::RequiresFpuRegister());
2770 summary->set_out(Location::RequiresFpuRegister());
2771 return summary;
2481 } 2772 }
2482 2773
2483 2774
2484 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2775 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2485 UNIMPLEMENTED(); 2776 DRegister left = locs()->in(0).fpu_reg();
2777 DRegister right = locs()->in(1).fpu_reg();
2778 DRegister result = locs()->out().fpu_reg();
2779 switch (op_kind()) {
2780 case Token::kADD: __ addd(result, left, right); break;
2781 case Token::kSUB: __ subd(result, left, right); break;
2782 case Token::kMUL: __ muld(result, left, right); break;
2783 case Token::kDIV: __ divd(result, left, right); break;
2784 default: UNREACHABLE();
2785 }
2486 } 2786 }
2487 2787
2488 2788
2489 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary() const { 2789 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary() const {
2490 UNIMPLEMENTED(); 2790 UNIMPLEMENTED();
2491 return NULL; 2791 return NULL;
2492 } 2792 }
2493 2793
2494 2794
2495 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2795 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
2700 return NULL; 3000 return NULL;
2701 } 3001 }
2702 3002
2703 3003
2704 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3004 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2705 UNIMPLEMENTED(); 3005 UNIMPLEMENTED();
2706 } 3006 }
2707 3007
2708 3008
2709 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { 3009 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const {
2710 UNIMPLEMENTED(); 3010 const intptr_t kNumInputs = 1;
2711 return NULL; 3011 const intptr_t kNumTemps = 0;
3012 LocationSummary* summary =
3013 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3014 summary->set_in(0, Location::RequiresRegister());
3015 // We make use of 3-operand instructions by not requiring result register
3016 // to be identical to first input register as on Intel.
3017 summary->set_out(Location::RequiresRegister());
3018 return summary;
2712 } 3019 }
2713 3020
2714 3021
2715 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3022 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2716 UNIMPLEMENTED(); 3023 Register value = locs()->in(0).reg();
3024 Register result = locs()->out().reg();
3025 switch (op_kind()) {
3026 case Token::kNEGATE: {
3027 Label* deopt = compiler->AddDeoptStub(deopt_id(),
3028 kDeoptUnaryOp);
3029 __ SubuDetectOverflow(result, ZR, value, CMPRES);
3030 __ bltz(CMPRES, deopt);
3031 break;
3032 }
3033 case Token::kBIT_NOT:
3034 __ nor(result, value, ZR);
3035 __ addiu(result, result, Immediate(-1)); // Remove inverted smi-tag.
3036 break;
3037 default:
3038 UNREACHABLE();
3039 }
2717 } 3040 }
2718 3041
2719 3042
2720 LocationSummary* SmiToDoubleInstr::MakeLocationSummary() const { 3043 LocationSummary* SmiToDoubleInstr::MakeLocationSummary() const {
2721 UNIMPLEMENTED(); 3044 const intptr_t kNumInputs = 1;
2722 return NULL; 3045 const intptr_t kNumTemps = 0;
3046 LocationSummary* result =
3047 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3048 result->set_in(0, Location::WritableRegister());
3049 result->set_out(Location::RequiresFpuRegister());
3050 return result;
2723 } 3051 }
2724 3052
2725 3053
2726 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3054 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2727 UNIMPLEMENTED(); 3055 Register value = locs()->in(0).reg();
3056 FpuRegister result = locs()->out().fpu_reg();
3057 __ SmiUntag(value);
3058 __ mtc1(value, STMP1);
3059 __ cvtdw(result, STMP1);
2728 } 3060 }
2729 3061
2730 3062
2731 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary() const { 3063 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary() const {
2732 UNIMPLEMENTED(); 3064 UNIMPLEMENTED();
2733 return NULL; 3065 return NULL;
2734 } 3066 }
2735 3067
2736 3068
2737 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3069 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 17 matching lines...) Expand all
2755 return NULL; 3087 return NULL;
2756 } 3088 }
2757 3089
2758 3090
2759 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3091 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2760 UNIMPLEMENTED(); 3092 UNIMPLEMENTED();
2761 } 3093 }
2762 3094
2763 3095
2764 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const { 3096 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const {
2765 UNIMPLEMENTED(); 3097 ASSERT((InputCount() == 1) || (InputCount() == 2));
2766 return NULL; 3098 const intptr_t kNumTemps = 0;
3099 LocationSummary* result =
3100 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall);
3101 result->set_in(0, Location::FpuRegisterLocation(D6));
3102 if (InputCount() == 2) {
3103 result->set_in(1, Location::FpuRegisterLocation(D7));
3104 }
3105 result->set_out(Location::FpuRegisterLocation(D0));
3106 return result;
2767 } 3107 }
2768 3108
2769 3109
2770 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3110 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2771 UNIMPLEMENTED(); 3111 // For pow-function return NAN if exponent is NAN.
3112 Label do_call, skip_call;
3113 if (recognized_kind() == MethodRecognizer::kDoublePow) {
3114 DRegister exp = locs()->in(1).fpu_reg();
3115 __ cund(exp, exp);
3116 __ bc1f(&do_call);
3117 // Exponent is NaN, return NaN.
3118 __ movd(locs()->out().fpu_reg(), exp);
3119 __ b(&skip_call);
3120 }
3121 __ Bind(&do_call);
3122 // double values are passed and returned in vfp registers.
3123 __ CallRuntime(TargetFunction());
3124 __ Bind(&skip_call);
2772 } 3125 }
2773 3126
2774 3127
2775 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { 3128 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const {
2776 return MakeCallSummary(); 3129 return MakeCallSummary();
2777 } 3130 }
2778 3131
2779 3132
2780 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3133 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2781 Label* deopt = compiler->AddDeoptStub(deopt_id(), 3134 Label* deopt = compiler->AddDeoptStub(deopt_id(),
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2837 summary->AddTemp(Location::RequiresRegister()); 3190 summary->AddTemp(Location::RequiresRegister());
2838 } 3191 }
2839 return summary; 3192 return summary;
2840 } 3193 }
2841 3194
2842 3195
2843 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3196 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2844 if (null_check()) { 3197 if (null_check()) {
2845 Label* deopt = compiler->AddDeoptStub(deopt_id(), 3198 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2846 kDeoptCheckClass); 3199 kDeoptCheckClass);
2847 __ beq(locs()->in(0).reg(), NULLREG, deopt); 3200 __ BranchEqual(locs()->in(0).reg(),
3201 reinterpret_cast<int32_t>(Object::null()), deopt);
2848 return; 3202 return;
2849 } 3203 }
2850 3204
2851 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || 3205 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) ||
2852 (unary_checks().NumberOfChecks() > 1)); 3206 (unary_checks().NumberOfChecks() > 1));
2853 Register value = locs()->in(0).reg(); 3207 Register value = locs()->in(0).reg();
2854 Register temp = locs()->temp(0).reg(); 3208 Register temp = locs()->temp(0).reg();
2855 Label* deopt = compiler->AddDeoptStub(deopt_id(), 3209 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2856 kDeoptCheckClass); 3210 kDeoptCheckClass);
2857 Label is_ok; 3211 Label is_ok;
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
3124 locs->set_in(0, Location::RegisterOrConstant(left())); 3478 locs->set_in(0, Location::RegisterOrConstant(left()));
3125 locs->set_in(1, Location::RegisterOrConstant(right())); 3479 locs->set_in(1, Location::RegisterOrConstant(right()));
3126 locs->set_out(Location::RequiresRegister()); 3480 locs->set_out(Location::RequiresRegister());
3127 return locs; 3481 return locs;
3128 } 3482 }
3129 3483
3130 3484
3131 // Special code for numbers (compare values instead of references.) 3485 // Special code for numbers (compare values instead of references.)
3132 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3486 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3133 __ TraceSimMsg("StrictCompareInstr"); 3487 __ TraceSimMsg("StrictCompareInstr");
3488 __ Comment("StrictCompareInstr");
3134 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); 3489 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
3135 Location left = locs()->in(0); 3490 Location left = locs()->in(0);
3136 Location right = locs()->in(1); 3491 Location right = locs()->in(1);
3137 if (left.IsConstant() && right.IsConstant()) { 3492 if (left.IsConstant() && right.IsConstant()) {
3138 // TODO(vegorov): should be eliminated earlier by constant propagation. 3493 // TODO(vegorov): should be eliminated earlier by constant propagation.
3139 const bool result = (kind() == Token::kEQ_STRICT) ? 3494 const bool result = (kind() == Token::kEQ_STRICT) ?
3140 left.constant().raw() == right.constant().raw() : 3495 left.constant().raw() == right.constant().raw() :
3141 left.constant().raw() != right.constant().raw(); 3496 left.constant().raw() != right.constant().raw();
3142 __ LoadObject(locs()->out().reg(), result ? Bool::True() : Bool::False()); 3497 __ LoadObject(locs()->out().reg(), result ? Bool::True() : Bool::False());
3143 return; 3498 return;
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
3274 } 3629 }
3275 3630
3276 3631
3277 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { 3632 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const {
3278 return MakeCallSummary(); 3633 return MakeCallSummary();
3279 } 3634 }
3280 3635
3281 3636
3282 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3637 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3283 __ TraceSimMsg("AllocateObjectInstr"); 3638 __ TraceSimMsg("AllocateObjectInstr");
3639 __ Comment("AllocateObjectInstr");
3284 const Class& cls = Class::ZoneHandle(constructor().Owner()); 3640 const Class& cls = Class::ZoneHandle(constructor().Owner());
3285 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); 3641 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls));
3286 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); 3642 const ExternalLabel label(cls.ToCString(), stub.EntryPoint());
3287 compiler->GenerateCall(token_pos(), 3643 compiler->GenerateCall(token_pos(),
3288 &label, 3644 &label,
3289 PcDescriptors::kOther, 3645 PcDescriptors::kOther,
3290 locs()); 3646 locs());
3291 __ Drop(ArgumentCount()); // Discard arguments. 3647 __ Drop(ArgumentCount()); // Discard arguments.
3292 } 3648 }
3293 3649
3294 3650
3295 LocationSummary* CreateClosureInstr::MakeLocationSummary() const { 3651 LocationSummary* CreateClosureInstr::MakeLocationSummary() const {
3296 return MakeCallSummary(); 3652 return MakeCallSummary();
3297 } 3653 }
3298 3654
3299 3655
3300 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3656 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3657 __ Comment("CreateClosureInstr");
3301 const Function& closure_function = function(); 3658 const Function& closure_function = function();
3302 ASSERT(!closure_function.IsImplicitStaticClosureFunction()); 3659 ASSERT(!closure_function.IsImplicitStaticClosureFunction());
3303 const Code& stub = Code::Handle( 3660 const Code& stub = Code::Handle(
3304 StubCode::GetAllocationStubForClosure(closure_function)); 3661 StubCode::GetAllocationStubForClosure(closure_function));
3305 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); 3662 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint());
3306 compiler->GenerateCall(token_pos(), 3663 compiler->GenerateCall(token_pos(),
3307 &label, 3664 &label,
3308 PcDescriptors::kOther, 3665 PcDescriptors::kOther,
3309 locs()); 3666 locs());
3310 __ Drop(2); // Discard type arguments and receiver. 3667 __ Drop(2); // Discard type arguments and receiver.
3311 } 3668 }
3312 3669
3313 } // namespace dart 3670 } // namespace dart
3314 3671
3315 #endif // defined TARGET_ARCH_MIPS 3672 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/instructions_mips.cc ('k') | runtime/vm/intrinsifier_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698