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

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

Issue 13884017: Adds support for UseDartApi vm test on MIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 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_mips.cc ('k') | runtime/vm/simulator_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 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 __ LoadObject(V0, Bool::True()); 398 __ LoadObject(V0, Bool::True());
399 __ b(&done); 399 __ b(&done);
400 __ Bind(&true_label); 400 __ Bind(&true_label);
401 __ LoadObject(V0, Bool::False()); 401 __ LoadObject(V0, Bool::False());
402 __ Bind(&done); 402 __ Bind(&done);
403 } 403 }
404 __ Bind(&equality_done); 404 __ Bind(&equality_done);
405 } 405 }
406 406
407 407
408 static void LoadValueCid(FlowGraphCompiler* compiler,
409 Register value_cid_reg,
410 Register value_reg,
411 Label* value_is_smi = NULL) {
412 Label done;
413 if (value_is_smi == NULL) {
414 __ LoadImmediate(value_cid_reg, kSmiCid);
415 }
416 __ andi(TMP1, value_reg, Immediate(kSmiTagMask));
417 if (value_is_smi == NULL) {
418 __ beq(TMP1, ZR, &done);
419 } else {
420 __ beq(TMP1, ZR, value_is_smi);
421 }
422 __ LoadClassId(value_cid_reg, value_reg);
423 __ Bind(&done);
424 }
425
426
408 // Emit code when ICData's targets are all Object == (which is ===). 427 // Emit code when ICData's targets are all Object == (which is ===).
409 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, 428 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler,
410 const ICData& ic_data, 429 const ICData& ic_data,
411 const LocationSummary& locs, 430 const LocationSummary& locs,
412 Token::Kind kind, 431 Token::Kind kind,
413 BranchInstr* branch, 432 BranchInstr* branch,
414 intptr_t deopt_id) { 433 intptr_t deopt_id) {
415 UNIMPLEMENTED(); 434 UNIMPLEMENTED();
416 } 435 }
417 436
418 437
419 // First test if receiver is NULL, in which case === is applied. 438 // First test if receiver is NULL, in which case === is applied.
420 // If type feedback was provided (lists of <class-id, target>), do a 439 // If type feedback was provided (lists of <class-id, target>), do a
421 // type by type check (either === or static call to the operator. 440 // type by type check (either === or static call to the operator.
422 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, 441 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler,
423 LocationSummary* locs, 442 LocationSummary* locs,
424 Token::Kind kind, 443 Token::Kind kind,
425 BranchInstr* branch, 444 BranchInstr* branch,
426 const ICData& ic_data, 445 const ICData& ic_data,
427 intptr_t deopt_id, 446 intptr_t deopt_id,
428 intptr_t token_pos) { 447 intptr_t token_pos) {
429 UNIMPLEMENTED(); 448 UNIMPLEMENTED();
430 } 449 }
431 450
432 451
452 static Condition TokenKindToSmiCondition(Token::Kind kind) {
453 switch (kind) {
454 case Token::kEQ: return EQ;
455 case Token::kNE: return NE;
456 case Token::kLT: return LT;
457 case Token::kGT: return GT;
458 case Token::kLTE: return LE;
459 case Token::kGTE: return GE;
460 default:
461 UNREACHABLE();
462 return VS;
463 }
464 }
465
466
433 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 467 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
434 const LocationSummary& locs, 468 const LocationSummary& locs,
435 Token::Kind kind, 469 Token::Kind kind,
436 BranchInstr* branch) { 470 BranchInstr* branch) {
437 UNIMPLEMENTED(); 471 Location left = locs.in(0);
472 Location right = locs.in(1);
473 ASSERT(!left.IsConstant() || !right.IsConstant());
474
475 Condition true_condition = TokenKindToSmiCondition(kind);
476
477 if (left.IsConstant()) {
478 __ CompareObject(CMPRES, right.reg(), left.constant());
479 true_condition = FlowGraphCompiler::FlipCondition(true_condition);
480 } else if (right.IsConstant()) {
481 __ CompareObject(CMPRES, left.reg(), right.constant());
482 } else {
483 __ subu(CMPRES, left.reg(), right.reg());
484 }
485
486 if (branch != NULL) {
487 branch->EmitBranchOnCondition(compiler, true_condition);
488 } else {
489 Register result = locs.out().reg();
490 Label done, is_true;
491 switch (true_condition) {
492 case EQ: __ beq(CMPRES, ZR, &is_true); break;
493 case NE: __ bne(CMPRES, ZR, &is_true); break;
494 case GT: __ bgtz(CMPRES, &is_true); break;
495 case GE: __ bgez(CMPRES, &is_true); break;
496 case LT: __ bltz(CMPRES, &is_true); break;
497 case LE: __ blez(CMPRES, &is_true); break;
498 default:
499 UNREACHABLE();
500 break;
501 }
502 __ LoadObject(result, Bool::False());
503 __ b(&done);
504 __ Bind(&is_true);
505 __ LoadObject(result, Bool::True());
506 __ Bind(&done);
507 }
438 } 508 }
439 509
440 510
441 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, 511 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
442 const LocationSummary& locs, 512 const LocationSummary& locs,
443 Token::Kind kind, 513 Token::Kind kind,
444 BranchInstr* branch) { 514 BranchInstr* branch) {
445 UNIMPLEMENTED(); 515 UNIMPLEMENTED();
446 } 516 }
447 517
448 518
519 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
520 const LocationSummary& locs,
521 Token::Kind kind,
522 BranchInstr* branch) {
523 UNIMPLEMENTED();
524 }
525
526
449 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 527 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
450 const LocationSummary& locs, 528 const LocationSummary& locs,
451 Token::Kind kind, 529 Token::Kind kind,
452 BranchInstr* branch) { 530 BranchInstr* branch) {
453 UNIMPLEMENTED(); 531 UNIMPLEMENTED();
454 } 532 }
455 533
456 534
457 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 535 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
458 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 536 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 if (branch->is_checked()) { 614 if (branch->is_checked()) {
537 EmitAssertBoolean(V0, token_pos(), deopt_id(), locs(), compiler); 615 EmitAssertBoolean(V0, token_pos(), deopt_id(), locs(), compiler);
538 } 616 }
539 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ; 617 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ;
540 __ CompareObject(CMPRES, V0, Bool::True()); 618 __ CompareObject(CMPRES, V0, Bool::True());
541 branch->EmitBranchOnCondition(compiler, branch_condition); 619 branch->EmitBranchOnCondition(compiler, branch_condition);
542 } 620 }
543 621
544 622
545 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { 623 LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
546 UNIMPLEMENTED(); 624 const intptr_t kNumInputs = 2;
547 return NULL; 625 const intptr_t kNumTemps = 0;
626 if (operands_class_id() == kMintCid) {
627 const intptr_t kNumTemps = 2;
628 LocationSummary* locs =
629 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
630 locs->set_in(0, Location::RequiresFpuRegister());
631 locs->set_in(1, Location::RequiresFpuRegister());
632 locs->set_temp(0, Location::RequiresRegister());
633 locs->set_temp(1, Location::RequiresRegister());
634 locs->set_out(Location::RequiresRegister());
635 return locs;
636 }
637 if (operands_class_id() == kDoubleCid) {
638 LocationSummary* summary =
639 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
640 summary->set_in(0, Location::RequiresFpuRegister());
641 summary->set_in(1, Location::RequiresFpuRegister());
642 summary->set_out(Location::RequiresRegister());
643 return summary;
644 } else if (operands_class_id() == kSmiCid) {
645 LocationSummary* summary =
646 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
647 summary->set_in(0, Location::RegisterOrConstant(left()));
648 // Only one input can be a constant operand. The case of two constant
649 // operands should be handled by constant propagation.
650 summary->set_in(1, summary->in(0).IsConstant()
651 ? Location::RequiresRegister()
652 : Location::RegisterOrConstant(right()));
653 summary->set_out(Location::RequiresRegister());
654 return summary;
655 }
656 LocationSummary* locs =
657 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
658 // Pick arbitrary fixed input registers because this is a call.
659 locs->set_in(0, Location::RegisterLocation(A0));
660 locs->set_in(1, Location::RegisterLocation(A1));
661 locs->set_out(Location::RegisterLocation(V0));
662 return locs;
548 } 663 }
549 664
550 665
551 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 666 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
552 UNIMPLEMENTED(); 667 if (operands_class_id() == kSmiCid) {
668 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL);
669 return;
670 }
671 if (operands_class_id() == kMintCid) {
672 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL);
673 return;
674 }
675 if (operands_class_id() == kDoubleCid) {
676 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL);
677 return;
678 }
679
680 // Push arguments for the call.
681 // TODO(fschneider): Split this instruction into different types to avoid
682 // explicitly pushing arguments to the call here.
683 Register left = locs()->in(0).reg();
684 Register right = locs()->in(1).reg();
685 __ Push(left);
686 __ Push(right);
687 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
688 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptRelationalOp);
689 // Load class into A2.
690 const intptr_t kNumArguments = 2;
691 LoadValueCid(compiler, A2, left);
692 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()),
693 A2, // Class id register.
694 kNumArguments,
695 Array::Handle(), // No named arguments.
696 deopt, // Deoptimize target.
697 deopt_id(),
698 token_pos(),
699 locs());
700 return;
701 }
702 const String& function_name =
703 String::ZoneHandle(Symbols::New(Token::Str(kind())));
704 if (!compiler->is_optimizing()) {
705 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
706 deopt_id(),
707 token_pos());
708 }
709 const intptr_t kNumArguments = 2;
710 const intptr_t kNumArgsChecked = 2; // Type-feedback.
711 ICData& relational_ic_data = ICData::ZoneHandle(ic_data()->raw());
712 if (compiler->is_optimizing() && FLAG_propagate_ic_data) {
713 ASSERT(!ic_data()->IsNull());
714 if (ic_data()->NumberOfChecks() == 0) {
715 // IC call for reoptimization populates original ICData.
716 relational_ic_data = ic_data()->raw();
717 } else {
718 // Megamorphic call.
719 relational_ic_data = ic_data()->AsUnaryClassChecks();
720 }
721 } else {
722 relational_ic_data = ICData::New(compiler->parsed_function().function(),
723 function_name,
724 deopt_id(),
725 kNumArgsChecked);
726 }
727 compiler->GenerateInstanceCall(deopt_id(),
728 token_pos(),
729 kNumArguments,
730 Array::ZoneHandle(), // No optional arguments.
731 locs(),
732 relational_ic_data);
553 } 733 }
554 734
555 735
556 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, 736 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
557 BranchInstr* branch) { 737 BranchInstr* branch) {
558 UNIMPLEMENTED(); 738 if (operands_class_id() == kSmiCid) {
739 EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
740 return;
741 }
742 if (operands_class_id() == kMintCid) {
743 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch);
744 return;
745 }
746 if (operands_class_id() == kDoubleCid) {
747 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
748 return;
749 }
750 EmitNativeCode(compiler);
751 __ CompareObject(CMPRES, V0, Bool::True());
752 branch->EmitBranchOnCondition(compiler, EQ);
559 } 753 }
560 754
561 755
562 LocationSummary* NativeCallInstr::MakeLocationSummary() const { 756 LocationSummary* NativeCallInstr::MakeLocationSummary() const {
563 const intptr_t kNumInputs = 0; 757 const intptr_t kNumInputs = 0;
564 const intptr_t kNumTemps = 3; 758 const intptr_t kNumTemps = 3;
565 LocationSummary* locs = 759 LocationSummary* locs =
566 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 760 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
567 locs->set_temp(0, Location::RegisterLocation(A1)); 761 locs->set_temp(0, Location::RegisterLocation(A1));
568 locs->set_temp(1, Location::RegisterLocation(A2)); 762 locs->set_temp(1, Location::RegisterLocation(A2));
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 __ LoadImmediate(TMP1, Isolate::Current()->stack_limit_address()); 1067 __ LoadImmediate(TMP1, Isolate::Current()->stack_limit_address());
874 1068
875 __ lw(TMP1, Address(TMP1)); 1069 __ lw(TMP1, Address(TMP1));
876 __ BranchLessEqual(SP, TMP1, slow_path->entry_label()); 1070 __ BranchLessEqual(SP, TMP1, slow_path->entry_label());
877 1071
878 __ Bind(slow_path->exit_label()); 1072 __ Bind(slow_path->exit_label());
879 } 1073 }
880 1074
881 1075
882 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { 1076 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
883 UNIMPLEMENTED(); 1077 const intptr_t kNumInputs = 2;
884 return NULL; 1078 if (op_kind() == Token::kTRUNCDIV) {
1079 UNIMPLEMENTED();
1080 return NULL;
1081 } else {
1082 const intptr_t kNumTemps = 0;
1083 LocationSummary* summary =
1084 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1085 summary->set_in(0, Location::RequiresRegister());
1086 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
1087 // We make use of 3-operand instructions by not requiring result register
1088 // to be identical to first input register as on Intel.
1089 summary->set_out(Location::RequiresRegister());
1090 return summary;
1091 }
885 } 1092 }
886 1093
887 1094
888 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1095 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
889 UNIMPLEMENTED(); 1096 if (op_kind() == Token::kSHL) {
1097 UNIMPLEMENTED();
1098 return;
1099 }
1100
1101 ASSERT(!is_truncating());
1102 Register left = locs()->in(0).reg();
1103 Register result = locs()->out().reg();
1104 Label* deopt = NULL;
1105 if (CanDeoptimize()) {
1106 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
1107 }
1108
1109 if (locs()->in(1).IsConstant()) {
1110 const Object& constant = locs()->in(1).constant();
1111 ASSERT(constant.IsSmi());
1112 int32_t imm = reinterpret_cast<int32_t>(constant.raw());
1113 switch (op_kind()) {
1114 case Token::kSUB: {
1115 if (deopt == NULL) {
1116 __ AddImmediate(result, left, -imm);
1117 } else {
1118 __ SubImmediateDetectOverflow(result, left, imm, CMPRES);
1119 __ bltz(CMPRES, deopt);
1120 }
1121 break;
1122 }
1123 case Token::kADD: {
1124 if (deopt == NULL) {
1125 __ AddImmediate(result, left, imm);
1126 } else {
1127 __ AddImmediateDetectOverflow(result, left, imm, CMPRES);
1128 __ bltz(CMPRES, deopt);
1129 }
1130 break;
1131 }
1132 case Token::kMUL: {
1133 // Keep left value tagged and untag right value.
1134 const intptr_t value = Smi::Cast(constant).Value();
1135 if (value == 2) {
1136 __ sll(result, left, 1);
1137 } else {
1138 __ LoadImmediate(TMP1, value);
1139 __ mult(left, TMP1);
1140 __ mflo(result);
1141 }
1142 if (deopt != NULL) {
1143 UNIMPLEMENTED();
1144 }
1145 break;
1146 }
1147 case Token::kTRUNCDIV: {
1148 UNIMPLEMENTED();
1149 break;
1150 }
1151 case Token::kBIT_AND: {
1152 // No overflow check.
1153 if (Utils::IsUint(kImmBits, imm)) {
1154 __ andi(result, left, Immediate(imm));
1155 } else {
1156 __ LoadImmediate(TMP1, imm);
1157 __ and_(result, left, TMP1);
1158 }
1159 break;
1160 }
1161 case Token::kBIT_OR: {
1162 // No overflow check.
1163 if (Utils::IsUint(kImmBits, imm)) {
1164 __ ori(result, left, Immediate(imm));
1165 } else {
1166 __ LoadImmediate(TMP1, imm);
1167 __ or_(result, left, TMP1);
1168 }
1169 break;
1170 }
1171 case Token::kBIT_XOR: {
1172 // No overflow check.
1173 if (Utils::IsUint(kImmBits, imm)) {
1174 __ xori(result, left, Immediate(imm));
1175 } else {
1176 __ LoadImmediate(TMP1, imm);
1177 __ xor_(result, left, TMP1);
1178 }
1179 break;
1180 }
1181 case Token::kSHR: {
1182 UNIMPLEMENTED();
1183 break;
1184 }
1185
1186 default:
1187 UNREACHABLE();
1188 break;
1189 }
1190 return;
1191 }
1192
1193 Register right = locs()->in(1).reg();
1194 switch (op_kind()) {
1195 case Token::kADD: {
1196 if (deopt == NULL) {
1197 __ addu(result, left, right);
1198 } else {
1199 __ AdduDetectOverflow(result, left, right, CMPRES);
1200 __ bltz(CMPRES, deopt);
1201 }
1202 break;
1203 }
1204 case Token::kSUB: {
1205 if (deopt == NULL) {
1206 __ subu(result, left, right);
1207 } else {
1208 __ SubuDetectOverflow(result, left, right, CMPRES);
1209 __ bltz(CMPRES, deopt);
1210 }
1211 break;
1212 }
1213 case Token::kMUL: {
1214 __ SmiUntag(left);
1215 __ mult(left, right);
1216 __ mflo(result);
1217 if (deopt != NULL) {
1218 UNIMPLEMENTED();
1219 }
1220 break;
1221 }
1222 case Token::kBIT_AND: {
1223 // No overflow check.
1224 __ and_(result, left, right);
1225 break;
1226 }
1227 case Token::kBIT_OR: {
1228 // No overflow check.
1229 __ or_(result, left, right);
1230 break;
1231 }
1232 case Token::kBIT_XOR: {
1233 // No overflow check.
1234 __ xor_(result, left, right);
1235 break;
1236 }
1237 case Token::kTRUNCDIV: {
1238 UNIMPLEMENTED();
1239 break;
1240 }
1241 case Token::kSHR: {
1242 UNIMPLEMENTED();
1243 break;
1244 }
1245 case Token::kDIV: {
1246 // Dispatches to 'Double./'.
1247 // TODO(srdjan): Implement as conversion to double and double division.
1248 UNREACHABLE();
1249 break;
1250 }
1251 case Token::kMOD: {
1252 // TODO(srdjan): Implement.
1253 UNREACHABLE();
1254 break;
1255 }
1256 case Token::kOR:
1257 case Token::kAND: {
1258 // Flow graph builder has dissected this operation to guarantee correct
1259 // behavior (short-circuit evaluation).
1260 UNREACHABLE();
1261 break;
1262 }
1263 default:
1264 UNREACHABLE();
1265 break;
1266 }
890 } 1267 }
891 1268
892 1269
893 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const { 1270 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
894 UNIMPLEMENTED(); 1271 UNIMPLEMENTED();
895 return NULL; 1272 return NULL;
896 } 1273 }
897 1274
898 1275
899 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1276 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1027 return NULL; 1404 return NULL;
1028 } 1405 }
1029 1406
1030 1407
1031 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1408 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1032 UNIMPLEMENTED(); 1409 UNIMPLEMENTED();
1033 } 1410 }
1034 1411
1035 1412
1036 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { 1413 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const {
1037 UNIMPLEMENTED(); 1414 return MakeCallSummary();
1038 return NULL;
1039 } 1415 }
1040 1416
1041 1417
1042 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1418 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1043 UNIMPLEMENTED(); 1419 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1420 kDeoptPolymorphicInstanceCallTestFail);
1421 if (ic_data().NumberOfChecks() == 0) {
1422 __ b(deopt);
1423 return;
1424 }
1425 ASSERT(ic_data().num_args_tested() == 1);
1426 if (!with_checks()) {
1427 ASSERT(ic_data().HasOneTarget());
1428 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
1429 compiler->GenerateStaticCall(instance_call()->deopt_id(),
1430 instance_call()->token_pos(),
1431 target,
1432 instance_call()->ArgumentCount(),
1433 instance_call()->argument_names(),
1434 locs());
1435 return;
1436 }
1437
1438 // Load receiver into R0.
1439 __ lw(T0, Address(SP, (instance_call()->ArgumentCount() - 1) * kWordSize));
1440
1441 LoadValueCid(compiler, T2, T0,
1442 (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
1443
1444 compiler->EmitTestAndCall(ic_data(),
1445 T2, // Class id register.
1446 instance_call()->ArgumentCount(),
1447 instance_call()->argument_names(),
1448 deopt,
1449 instance_call()->deopt_id(),
1450 instance_call()->token_pos(),
1451 locs());
1044 } 1452 }
1045 1453
1046 1454
1047 LocationSummary* BranchInstr::MakeLocationSummary() const { 1455 LocationSummary* BranchInstr::MakeLocationSummary() const {
1048 UNREACHABLE(); 1456 UNREACHABLE();
1049 return NULL; 1457 return NULL;
1050 } 1458 }
1051 1459
1052 1460
1053 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1461 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1054 comparison()->EmitBranchCode(compiler, this); 1462 comparison()->EmitBranchCode(compiler, this);
1055 } 1463 }
1056 1464
1057 1465
1058 LocationSummary* CheckClassInstr::MakeLocationSummary() const { 1466 LocationSummary* CheckClassInstr::MakeLocationSummary() const {
1059 UNIMPLEMENTED(); 1467 UNIMPLEMENTED();
1060 return NULL; 1468 return NULL;
1061 } 1469 }
1062 1470
1063 1471
1064 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1472 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1065 UNIMPLEMENTED(); 1473 UNIMPLEMENTED();
1066 } 1474 }
1067 1475
1068 1476
1069 LocationSummary* CheckSmiInstr::MakeLocationSummary() const { 1477 LocationSummary* CheckSmiInstr::MakeLocationSummary() const {
1070 UNIMPLEMENTED(); 1478 const intptr_t kNumInputs = 1;
1071 return NULL; 1479 const intptr_t kNumTemps = 0;
1480 LocationSummary* summary =
1481 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1482 summary->set_in(0, Location::RequiresRegister());
1483 return summary;
1072 } 1484 }
1073 1485
1074 1486
1075 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1487 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1076 UNIMPLEMENTED(); 1488 Register value = locs()->in(0).reg();
1489 Label* deopt = compiler->AddDeoptStub(deopt_id(),
1490 kDeoptCheckSmi);
1491 __ andi(TMP1, value, Immediate(kSmiTagMask));
1492 __ bne(TMP1, ZR, deopt);
1077 } 1493 }
1078 1494
1079 1495
1080 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const { 1496 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const {
1081 UNIMPLEMENTED(); 1497 UNIMPLEMENTED();
1082 return NULL; 1498 return NULL;
1083 } 1499 }
1084 1500
1085 1501
1086 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1502 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1189 if (!compiler->CanFallThroughTo(successor())) { 1605 if (!compiler->CanFallThroughTo(successor())) {
1190 __ b(compiler->GetJumpLabel(successor())); 1606 __ b(compiler->GetJumpLabel(successor()));
1191 } 1607 }
1192 } 1608 }
1193 1609
1194 1610
1195 static Condition NegateCondition(Condition condition) { 1611 static Condition NegateCondition(Condition condition) {
1196 switch (condition) { 1612 switch (condition) {
1197 case EQ: return NE; 1613 case EQ: return NE;
1198 case NE: return EQ; 1614 case NE: return EQ;
1615 case LT: return GE;
1616 case LE: return GT;
1617 case GT: return LE;
1618 case GE: return LT;
1199 default: 1619 default:
1200 OS::Print("Error: Condition not recognized: %d\n", condition); 1620 OS::Print("Error: Condition not recognized: %d\n", condition);
1201 UNIMPLEMENTED(); 1621 UNIMPLEMENTED();
1202 return EQ; 1622 return EQ;
1203 } 1623 }
1204 } 1624 }
1205 1625
1206 1626
1207 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, 1627 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler,
1208 bool value) { 1628 bool value) {
1209 if (value && !compiler->CanFallThroughTo(true_successor())) { 1629 if (value && !compiler->CanFallThroughTo(true_successor())) {
1210 __ b(compiler->GetJumpLabel(true_successor())); 1630 __ b(compiler->GetJumpLabel(true_successor()));
1211 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { 1631 } else if (!value && !compiler->CanFallThroughTo(false_successor())) {
1212 __ b(compiler->GetJumpLabel(false_successor())); 1632 __ b(compiler->GetJumpLabel(false_successor()));
1213 } 1633 }
1214 } 1634 }
1215 1635
1216 1636
1217 // The comparison result is in CMPRES. 1637 // The comparison result is in CMPRES.
1218 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, 1638 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler,
1219 Condition true_condition) { 1639 Condition true_condition) {
1220 if (compiler->CanFallThroughTo(false_successor())) { 1640 if (compiler->CanFallThroughTo(false_successor())) {
1221 // If the next block is the false successor we will fall through to it. 1641 // If the next block is the false successor we will fall through to it.
1222 if (true_condition == EQ) { 1642 Label* label = compiler->GetJumpLabel(true_successor());
1223 __ beq(CMPRES, ZR, compiler->GetJumpLabel(true_successor())); 1643 switch (true_condition) {
1224 } else { 1644 case EQ: __ beq(CMPRES, ZR, label); break;
1225 ASSERT(true_condition == NE); 1645 case NE: __ bne(CMPRES, ZR, label); break;
1226 __ bne(CMPRES, ZR, compiler->GetJumpLabel(true_successor())); 1646 case GT: __ bgtz(CMPRES, label); break;
1647 case GE: __ bgez(CMPRES, label); break;
1648 case LT: __ bltz(CMPRES, label); break;
1649 case LE: __ blez(CMPRES, label); break;
1650 default:
1651 UNREACHABLE();
1652 break;
1227 } 1653 }
1228 } else { 1654 } else {
1229 // If the next block is the true successor we negate comparison and fall 1655 // If the next block is the true successor we negate comparison and fall
1230 // through to it. 1656 // through to it.
1231 Condition false_condition = NegateCondition(true_condition); 1657 Condition false_condition = NegateCondition(true_condition);
1232 if (false_condition == EQ) { 1658 Label* label = compiler->GetJumpLabel(false_successor());
1233 __ beq(CMPRES, ZR, compiler->GetJumpLabel(false_successor())); 1659 switch (false_condition) {
1234 } else { 1660 case EQ: __ beq(CMPRES, ZR, label); break;
1235 ASSERT(false_condition == NE); 1661 case NE: __ bne(CMPRES, ZR, label); break;
1236 __ bne(CMPRES, ZR, compiler->GetJumpLabel(false_successor())); 1662 case GT: __ bgtz(CMPRES, label); break;
1663 case GE: __ bgez(CMPRES, label); break;
1664 case LT: __ bltz(CMPRES, label); break;
1665 case LE: __ blez(CMPRES, label); break;
1666 default:
1667 UNREACHABLE();
1668 break;
1237 } 1669 }
1238 // Fall through or jump to the true successor. 1670 // Fall through or jump to the true successor.
1239 if (!compiler->CanFallThroughTo(true_successor())) { 1671 if (!compiler->CanFallThroughTo(true_successor())) {
1240 __ b(compiler->GetJumpLabel(true_successor())); 1672 __ b(compiler->GetJumpLabel(true_successor()));
1241 } 1673 }
1242 } 1674 }
1243 } 1675 }
1244 1676
1245 1677
1246 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { 1678 LocationSummary* CurrentContextInstr::MakeLocationSummary() const {
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1403 1835
1404 1836
1405 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1837 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1406 UNIMPLEMENTED(); 1838 UNIMPLEMENTED();
1407 } 1839 }
1408 1840
1409 } // namespace dart 1841 } // namespace dart
1410 1842
1411 #endif // defined TARGET_ARCH_MIPS 1843 #endif // defined TARGET_ARCH_MIPS
1412 1844
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_mips.cc ('k') | runtime/vm/simulator_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698