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

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());
regis 2013/04/12 21:18:04 Do you still have a reason to dedicate a register
zra 2013/04/12 22:19:59 Yah, I think it's probably less error-prone to kee
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 imm = -imm; // TODO(regis): What if deopt != NULL && imm == 0x80000000?
1116 // Fall through.
regis 2013/04/12 21:18:04 I merged the kSUB case with kADD case on ARM. Sinc
zra 2013/04/12 22:19:59 Done.
1117 }
1118 case Token::kADD: {
1119 if (deopt == NULL) {
1120 __ AddImmediate(result, left, imm);
1121 } else {
1122 __ AddImmediateDetectOverflow(result, left, imm, CMPRES);
1123 __ bltz(CMPRES, deopt);
1124 }
1125 break;
1126 }
1127 case Token::kMUL: {
1128 // Keep left value tagged and untag right value.
1129 const intptr_t value = Smi::Cast(constant).Value();
1130 if (value == 2) {
1131 __ sll(result, left, 1);
1132 } else {
1133 __ LoadImmediate(TMP, value);
1134 __ mult(left, TMP);
1135 __ mflo(result);
1136 }
1137 if (deopt != NULL) {
1138 UNIMPLEMENTED();
1139 }
1140 break;
1141 }
1142 case Token::kTRUNCDIV: {
1143 UNIMPLEMENTED();
1144 break;
1145 }
1146 case Token::kBIT_AND: {
1147 // No overflow check.
1148 if (Utils::IsUint(kImmBits, imm)) {
1149 __ andi(result, left, Immediate(imm));
1150 } else {
1151 __ LoadImmediate(TMP1, imm);
1152 __ and_(result, left, TMP1);
1153 }
1154 break;
1155 }
1156 case Token::kBIT_OR: {
1157 // No overflow check.
1158 if (Utils::IsUint(kImmBits, imm)) {
1159 __ ori(result, left, Immediate(imm));
1160 } else {
1161 __ LoadImmediate(TMP1, imm);
1162 __ or_(result, left, TMP1);
1163 }
1164 break;
1165 }
1166 case Token::kBIT_XOR: {
1167 // No overflow check.
1168 if (Utils::IsUint(kImmBits, imm)) {
1169 __ xori(result, left, Immediate(imm));
1170 } else {
1171 __ LoadImmediate(TMP1, imm);
1172 __ xor_(result, left, TMP1);
1173 }
1174 break;
1175 }
1176 case Token::kSHR: {
1177 UNIMPLEMENTED();
1178 break;
1179 }
1180
1181 default:
1182 UNREACHABLE();
1183 break;
1184 }
1185 return;
1186 }
1187
1188 Register right = locs()->in(1).reg();
1189 switch (op_kind()) {
1190 case Token::kADD: {
1191 if (deopt == NULL) {
1192 __ addu(result, left, right);
1193 } else {
1194 __ AdduDetectOverflow(result, left, right, CMPRES);
1195 __ bltz(CMPRES, deopt);
1196 }
1197 break;
1198 }
1199 case Token::kSUB: {
1200 if (deopt == NULL) {
1201 __ subu(result, left, right);
1202 } else {
1203 __ SubuDetectOverflow(result, left, right, CMPRES);
1204 __ bltz(CMPRES, deopt);
1205 }
1206 break;
1207 }
1208 case Token::kMUL: {
1209 __ SmiUntag(left);
1210 __ mult(left, right);
1211 __ mflo(result);
1212 if (deopt != NULL) {
1213 UNIMPLEMENTED();
1214 }
1215 break;
1216 }
1217 case Token::kBIT_AND: {
1218 // No overflow check.
1219 __ and_(result, left, right);
1220 break;
1221 }
1222 case Token::kBIT_OR: {
1223 // No overflow check.
1224 __ or_(result, left, right);
1225 break;
1226 }
1227 case Token::kBIT_XOR: {
1228 // No overflow check.
1229 __ xor_(result, left, right);
1230 break;
1231 }
1232 case Token::kTRUNCDIV: {
1233 UNIMPLEMENTED();
1234 break;
1235 }
1236 case Token::kSHR: {
1237 UNIMPLEMENTED();
1238 break;
1239 }
1240 case Token::kDIV: {
1241 // Dispatches to 'Double./'.
1242 // TODO(srdjan): Implement as conversion to double and double division.
1243 UNREACHABLE();
1244 break;
1245 }
1246 case Token::kMOD: {
1247 // TODO(srdjan): Implement.
1248 UNREACHABLE();
1249 break;
1250 }
1251 case Token::kOR:
1252 case Token::kAND: {
1253 // Flow graph builder has dissected this operation to guarantee correct
1254 // behavior (short-circuit evaluation).
1255 UNREACHABLE();
1256 break;
1257 }
1258 default:
1259 UNREACHABLE();
1260 break;
1261 }
890 } 1262 }
891 1263
892 1264
893 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const { 1265 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
894 UNIMPLEMENTED(); 1266 UNIMPLEMENTED();
895 return NULL; 1267 return NULL;
896 } 1268 }
897 1269
898 1270
899 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1271 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1027 return NULL; 1399 return NULL;
1028 } 1400 }
1029 1401
1030 1402
1031 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1403 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1032 UNIMPLEMENTED(); 1404 UNIMPLEMENTED();
1033 } 1405 }
1034 1406
1035 1407
1036 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { 1408 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const {
1037 UNIMPLEMENTED(); 1409 return MakeCallSummary();
1038 return NULL;
1039 } 1410 }
1040 1411
1041 1412
1042 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1413 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1043 UNIMPLEMENTED(); 1414 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1415 kDeoptPolymorphicInstanceCallTestFail);
1416 if (ic_data().NumberOfChecks() == 0) {
1417 __ b(deopt);
1418 return;
1419 }
1420 ASSERT(ic_data().num_args_tested() == 1);
1421 if (!with_checks()) {
1422 ASSERT(ic_data().HasOneTarget());
1423 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
1424 compiler->GenerateStaticCall(instance_call()->deopt_id(),
1425 instance_call()->token_pos(),
1426 target,
1427 instance_call()->ArgumentCount(),
1428 instance_call()->argument_names(),
1429 locs());
1430 return;
1431 }
1432
1433 // Load receiver into R0.
1434 __ lw(T0, Address(SP, (instance_call()->ArgumentCount() - 1) * kWordSize));
1435
1436 LoadValueCid(compiler, T2, T0,
1437 (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
1438
1439 compiler->EmitTestAndCall(ic_data(),
1440 T2, // Class id register.
1441 instance_call()->ArgumentCount(),
1442 instance_call()->argument_names(),
1443 deopt,
1444 instance_call()->deopt_id(),
1445 instance_call()->token_pos(),
1446 locs());
1044 } 1447 }
1045 1448
1046 1449
1047 LocationSummary* BranchInstr::MakeLocationSummary() const { 1450 LocationSummary* BranchInstr::MakeLocationSummary() const {
1048 UNREACHABLE(); 1451 UNREACHABLE();
1049 return NULL; 1452 return NULL;
1050 } 1453 }
1051 1454
1052 1455
1053 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1456 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1054 comparison()->EmitBranchCode(compiler, this); 1457 comparison()->EmitBranchCode(compiler, this);
1055 } 1458 }
1056 1459
1057 1460
1058 LocationSummary* CheckClassInstr::MakeLocationSummary() const { 1461 LocationSummary* CheckClassInstr::MakeLocationSummary() const {
1059 UNIMPLEMENTED(); 1462 UNIMPLEMENTED();
1060 return NULL; 1463 return NULL;
1061 } 1464 }
1062 1465
1063 1466
1064 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1467 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1065 UNIMPLEMENTED(); 1468 UNIMPLEMENTED();
1066 } 1469 }
1067 1470
1068 1471
1069 LocationSummary* CheckSmiInstr::MakeLocationSummary() const { 1472 LocationSummary* CheckSmiInstr::MakeLocationSummary() const {
1070 UNIMPLEMENTED(); 1473 const intptr_t kNumInputs = 1;
1071 return NULL; 1474 const intptr_t kNumTemps = 0;
1475 LocationSummary* summary =
1476 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1477 summary->set_in(0, Location::RequiresRegister());
1478 return summary;
1072 } 1479 }
1073 1480
1074 1481
1075 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1482 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1076 UNIMPLEMENTED(); 1483 Register value = locs()->in(0).reg();
1484 Label* deopt = compiler->AddDeoptStub(deopt_id(),
1485 kDeoptCheckSmi);
1486 __ andi(TMP1, value, Immediate(kSmiTagMask));
1487 __ bne(TMP1, ZR, deopt);
1077 } 1488 }
1078 1489
1079 1490
1080 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const { 1491 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const {
1081 UNIMPLEMENTED(); 1492 UNIMPLEMENTED();
1082 return NULL; 1493 return NULL;
1083 } 1494 }
1084 1495
1085 1496
1086 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1497 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1189 if (!compiler->CanFallThroughTo(successor())) { 1600 if (!compiler->CanFallThroughTo(successor())) {
1190 __ b(compiler->GetJumpLabel(successor())); 1601 __ b(compiler->GetJumpLabel(successor()));
1191 } 1602 }
1192 } 1603 }
1193 1604
1194 1605
1195 static Condition NegateCondition(Condition condition) { 1606 static Condition NegateCondition(Condition condition) {
1196 switch (condition) { 1607 switch (condition) {
1197 case EQ: return NE; 1608 case EQ: return NE;
1198 case NE: return EQ; 1609 case NE: return EQ;
1610 case LT: return GE;
1611 case LE: return GT;
1612 case GT: return LE;
1613 case GE: return LT;
1199 default: 1614 default:
1200 OS::Print("Error: Condition not recognized: %d\n", condition); 1615 OS::Print("Error: Condition not recognized: %d\n", condition);
1201 UNIMPLEMENTED(); 1616 UNIMPLEMENTED();
1202 return EQ; 1617 return EQ;
1203 } 1618 }
1204 } 1619 }
1205 1620
1206 1621
1207 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, 1622 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler,
1208 bool value) { 1623 bool value) {
1209 if (value && !compiler->CanFallThroughTo(true_successor())) { 1624 if (value && !compiler->CanFallThroughTo(true_successor())) {
1210 __ b(compiler->GetJumpLabel(true_successor())); 1625 __ b(compiler->GetJumpLabel(true_successor()));
1211 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { 1626 } else if (!value && !compiler->CanFallThroughTo(false_successor())) {
1212 __ b(compiler->GetJumpLabel(false_successor())); 1627 __ b(compiler->GetJumpLabel(false_successor()));
1213 } 1628 }
1214 } 1629 }
1215 1630
1216 1631
1217 // The comparison result is in CMPRES. 1632 // The comparison result is in CMPRES.
1218 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, 1633 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler,
1219 Condition true_condition) { 1634 Condition true_condition) {
1220 if (compiler->CanFallThroughTo(false_successor())) { 1635 if (compiler->CanFallThroughTo(false_successor())) {
1221 // If the next block is the false successor we will fall through to it. 1636 // If the next block is the false successor we will fall through to it.
1222 if (true_condition == EQ) { 1637 Label* label = compiler->GetJumpLabel(true_successor());
1223 __ beq(CMPRES, ZR, compiler->GetJumpLabel(true_successor())); 1638 switch (true_condition) {
1224 } else { 1639 case EQ: __ beq(CMPRES, ZR, label); break;
1225 ASSERT(true_condition == NE); 1640 case NE: __ bne(CMPRES, ZR, label); break;
1226 __ bne(CMPRES, ZR, compiler->GetJumpLabel(true_successor())); 1641 case GT: __ bgtz(CMPRES, label); break;
1642 case GE: __ bgez(CMPRES, label); break;
1643 case LT: __ bltz(CMPRES, label); break;
1644 case LE: __ blez(CMPRES, label); break;
1645 default:
1646 UNREACHABLE();
1647 break;
1227 } 1648 }
1228 } else { 1649 } else {
1229 // If the next block is the true successor we negate comparison and fall 1650 // If the next block is the true successor we negate comparison and fall
1230 // through to it. 1651 // through to it.
1231 Condition false_condition = NegateCondition(true_condition); 1652 Condition false_condition = NegateCondition(true_condition);
1232 if (false_condition == EQ) { 1653 Label* label = compiler->GetJumpLabel(false_successor());
1233 __ beq(CMPRES, ZR, compiler->GetJumpLabel(false_successor())); 1654 switch (false_condition) {
1234 } else { 1655 case EQ: __ beq(CMPRES, ZR, label); break;
1235 ASSERT(false_condition == NE); 1656 case NE: __ bne(CMPRES, ZR, label); break;
1236 __ bne(CMPRES, ZR, compiler->GetJumpLabel(false_successor())); 1657 case GT: __ bgtz(CMPRES, label); break;
1658 case GE: __ bgez(CMPRES, label); break;
1659 case LT: __ bltz(CMPRES, label); break;
1660 case LE: __ blez(CMPRES, label); break;
1661 default:
1662 UNREACHABLE();
1663 break;
1237 } 1664 }
1238 // Fall through or jump to the true successor. 1665 // Fall through or jump to the true successor.
1239 if (!compiler->CanFallThroughTo(true_successor())) { 1666 if (!compiler->CanFallThroughTo(true_successor())) {
1240 __ b(compiler->GetJumpLabel(true_successor())); 1667 __ b(compiler->GetJumpLabel(true_successor()));
1241 } 1668 }
1242 } 1669 }
1243 } 1670 }
1244 1671
1245 1672
1246 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { 1673 LocationSummary* CurrentContextInstr::MakeLocationSummary() const {
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1403 1830
1404 1831
1405 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1832 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1406 UNIMPLEMENTED(); 1833 UNIMPLEMENTED();
1407 } 1834 }
1408 1835
1409 } // namespace dart 1836 } // namespace dart
1410 1837
1411 #endif // defined TARGET_ARCH_MIPS 1838 #endif // defined TARGET_ARCH_MIPS
1412 1839
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