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

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

Issue 13671004: Support UseDartApi vm test on ARM. (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_arm.cc ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 UNIMPLEMENTED(); 215 UNIMPLEMENTED();
216 return NULL; 216 return NULL;
217 } 217 }
218 218
219 219
220 void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 220 void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
221 UNIMPLEMENTED(); 221 UNIMPLEMENTED();
222 } 222 }
223 223
224 224
225 static Condition TokenKindToSmiCondition(Token::Kind kind) {
226 switch (kind) {
227 case Token::kEQ: return EQ;
228 case Token::kNE: return NE;
229 case Token::kLT: return LT;
230 case Token::kGT: return GT;
231 case Token::kLTE: return LE;
232 case Token::kGTE: return GE;
233 default:
234 UNREACHABLE();
235 return VS;
236 }
237 }
238
239
225 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { 240 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
226 const intptr_t kNumInputs = 2; 241 const intptr_t kNumInputs = 2;
227 const bool is_checked_strict_equal = 242 const bool is_checked_strict_equal =
228 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); 243 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
229 if (receiver_class_id() == kMintCid) { 244 if (receiver_class_id() == kMintCid) {
230 const intptr_t kNumTemps = 1; 245 const intptr_t kNumTemps = 1;
231 LocationSummary* locs = 246 LocationSummary* locs =
232 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 247 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
233 locs->set_in(0, Location::RequiresFpuRegister()); 248 locs->set_in(0, Location::RequiresFpuRegister());
234 locs->set_in(1, Location::RequiresFpuRegister()); 249 locs->set_in(1, Location::RequiresFpuRegister());
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 __ LoadObject(R0, Bool::True()); 388 __ LoadObject(R0, Bool::True());
374 __ b(&done); 389 __ b(&done);
375 __ Bind(&true_label); 390 __ Bind(&true_label);
376 __ LoadObject(R0, Bool::False()); 391 __ LoadObject(R0, Bool::False());
377 __ Bind(&done); 392 __ Bind(&done);
378 } 393 }
379 __ Bind(&equality_done); 394 __ Bind(&equality_done);
380 } 395 }
381 396
382 397
398 static void LoadValueCid(FlowGraphCompiler* compiler,
399 Register value_cid_reg,
400 Register value_reg,
401 Label* value_is_smi = NULL) {
402 Label done;
403 if (value_is_smi == NULL) {
404 __ mov(value_cid_reg, ShifterOperand(kSmiCid));
405 }
406 __ tst(value_reg, ShifterOperand(kSmiTagMask));
407 if (value_is_smi == NULL) {
408 __ b(&done, EQ);
409 } else {
410 __ b(value_is_smi, EQ);
411 }
412 __ LoadClassId(value_cid_reg, value_reg);
413 __ Bind(&done);
414 }
415
416
383 // Emit code when ICData's targets are all Object == (which is ===). 417 // Emit code when ICData's targets are all Object == (which is ===).
384 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, 418 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler,
385 const ICData& ic_data, 419 const ICData& ic_data,
386 const LocationSummary& locs, 420 const LocationSummary& locs,
387 Token::Kind kind, 421 Token::Kind kind,
388 BranchInstr* branch, 422 BranchInstr* branch,
389 intptr_t deopt_id) { 423 intptr_t deopt_id) {
390 UNIMPLEMENTED(); 424 UNIMPLEMENTED();
391 } 425 }
392 426
393 427
394 // First test if receiver is NULL, in which case === is applied. 428 // First test if receiver is NULL, in which case === is applied.
395 // If type feedback was provided (lists of <class-id, target>), do a 429 // If type feedback was provided (lists of <class-id, target>), do a
396 // type by type check (either === or static call to the operator. 430 // type by type check (either === or static call to the operator.
397 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, 431 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler,
398 LocationSummary* locs, 432 LocationSummary* locs,
399 Token::Kind kind, 433 Token::Kind kind,
400 BranchInstr* branch, 434 BranchInstr* branch,
401 const ICData& ic_data, 435 const ICData& ic_data,
402 intptr_t deopt_id, 436 intptr_t deopt_id,
403 intptr_t token_pos) { 437 intptr_t token_pos) {
404 UNIMPLEMENTED(); 438 UNIMPLEMENTED();
405 } 439 }
406 440
407 441
408 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 442 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
409 const LocationSummary& locs, 443 const LocationSummary& locs,
410 Token::Kind kind, 444 Token::Kind kind,
411 BranchInstr* branch) { 445 BranchInstr* branch) {
412 UNIMPLEMENTED(); 446 Location left = locs.in(0);
447 Location right = locs.in(1);
448 ASSERT(!left.IsConstant() || !right.IsConstant());
449
450 Condition true_condition = TokenKindToSmiCondition(kind);
451
452 if (left.IsConstant()) {
453 __ CompareObject(right.reg(), left.constant());
454 true_condition = FlowGraphCompiler::FlipCondition(true_condition);
455 } else if (right.IsConstant()) {
456 __ CompareObject(left.reg(), right.constant());
457 } else {
458 __ cmp(left.reg(), ShifterOperand(right.reg()));
459 }
460
461 if (branch != NULL) {
462 branch->EmitBranchOnCondition(compiler, true_condition);
463 } else {
464 Register result = locs.out().reg();
465 Label done, is_true;
466 __ b(&is_true, true_condition);
467 __ LoadObject(result, Bool::False());
468 __ b(&done);
469 __ Bind(&is_true);
470 __ LoadObject(result, Bool::True());
471 __ Bind(&done);
472 }
413 } 473 }
414 474
415 475
416 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, 476 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
417 const LocationSummary& locs, 477 const LocationSummary& locs,
418 Token::Kind kind, 478 Token::Kind kind,
419 BranchInstr* branch) { 479 BranchInstr* branch) {
420 UNIMPLEMENTED(); 480 UNIMPLEMENTED();
421 } 481 }
422 482
423 483
484 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
485 const LocationSummary& locs,
486 Token::Kind kind,
487 BranchInstr* branch) {
488 UNIMPLEMENTED();
489 }
490
491
424 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 492 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
425 const LocationSummary& locs, 493 const LocationSummary& locs,
426 Token::Kind kind, 494 Token::Kind kind,
427 BranchInstr* branch) { 495 BranchInstr* branch) {
428 UNIMPLEMENTED(); 496 UNIMPLEMENTED();
429 } 497 }
430 498
431 499
432 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 500 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
433 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 501 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 if (branch->is_checked()) { 579 if (branch->is_checked()) {
512 EmitAssertBoolean(R0, token_pos(), deopt_id(), locs(), compiler); 580 EmitAssertBoolean(R0, token_pos(), deopt_id(), locs(), compiler);
513 } 581 }
514 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ; 582 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ;
515 __ CompareObject(R0, Bool::True()); 583 __ CompareObject(R0, Bool::True());
516 branch->EmitBranchOnCondition(compiler, branch_condition); 584 branch->EmitBranchOnCondition(compiler, branch_condition);
517 } 585 }
518 586
519 587
520 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { 588 LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
521 UNIMPLEMENTED(); 589 const intptr_t kNumInputs = 2;
522 return NULL; 590 const intptr_t kNumTemps = 0;
591 if (operands_class_id() == kMintCid) {
592 const intptr_t kNumTemps = 2;
593 LocationSummary* locs =
594 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
595 locs->set_in(0, Location::RequiresFpuRegister());
596 locs->set_in(1, Location::RequiresFpuRegister());
597 locs->set_temp(0, Location::RequiresRegister());
598 locs->set_temp(1, Location::RequiresRegister());
599 locs->set_out(Location::RequiresRegister());
600 return locs;
601 }
602 if (operands_class_id() == kDoubleCid) {
603 LocationSummary* summary =
604 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
605 summary->set_in(0, Location::RequiresFpuRegister());
606 summary->set_in(1, Location::RequiresFpuRegister());
607 summary->set_out(Location::RequiresRegister());
608 return summary;
609 } else if (operands_class_id() == kSmiCid) {
610 LocationSummary* summary =
611 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
612 summary->set_in(0, Location::RegisterOrConstant(left()));
613 // Only one input can be a constant operand. The case of two constant
614 // operands should be handled by constant propagation.
615 summary->set_in(1, summary->in(0).IsConstant()
616 ? Location::RequiresRegister()
617 : Location::RegisterOrConstant(right()));
618 summary->set_out(Location::RequiresRegister());
619 return summary;
620 }
621 LocationSummary* locs =
622 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
623 // Pick arbitrary fixed input registers because this is a call.
624 locs->set_in(0, Location::RegisterLocation(R0));
625 locs->set_in(1, Location::RegisterLocation(R1));
626 locs->set_out(Location::RegisterLocation(R0));
627 return locs;
523 } 628 }
524 629
525 630
526 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 631 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
527 UNIMPLEMENTED(); 632 if (operands_class_id() == kSmiCid) {
633 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL);
634 return;
635 }
636 if (operands_class_id() == kMintCid) {
637 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL);
638 return;
639 }
640 if (operands_class_id() == kDoubleCid) {
641 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL);
642 return;
643 }
644
645 // Push arguments for the call.
646 // TODO(fschneider): Split this instruction into different types to avoid
647 // explicitly pushing arguments to the call here.
648 Register left = locs()->in(0).reg();
649 Register right = locs()->in(1).reg();
650 __ Push(left);
651 __ Push(right);
652 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
653 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptRelationalOp);
654 // Load class into R2. Since this is a call, any register except
655 // the fixed input registers would be ok.
656 ASSERT((left != R2) && (right != R2));
657 const intptr_t kNumArguments = 2;
658 LoadValueCid(compiler, R2, left);
659 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()),
660 R2, // Class id register.
661 kNumArguments,
662 Array::Handle(), // No named arguments.
663 deopt, // Deoptimize target.
664 deopt_id(),
665 token_pos(),
666 locs());
667 return;
668 }
669 const String& function_name =
670 String::ZoneHandle(Symbols::New(Token::Str(kind())));
671 if (!compiler->is_optimizing()) {
672 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
673 deopt_id(),
674 token_pos());
675 }
676 const intptr_t kNumArguments = 2;
677 const intptr_t kNumArgsChecked = 2; // Type-feedback.
678 ICData& relational_ic_data = ICData::ZoneHandle(ic_data()->raw());
679 if (compiler->is_optimizing() && FLAG_propagate_ic_data) {
680 ASSERT(!ic_data()->IsNull());
681 if (ic_data()->NumberOfChecks() == 0) {
682 // IC call for reoptimization populates original ICData.
683 relational_ic_data = ic_data()->raw();
684 } else {
685 // Megamorphic call.
686 relational_ic_data = ic_data()->AsUnaryClassChecks();
687 }
688 } else {
689 relational_ic_data = ICData::New(compiler->parsed_function().function(),
690 function_name,
691 deopt_id(),
692 kNumArgsChecked);
693 }
694 compiler->GenerateInstanceCall(deopt_id(),
695 token_pos(),
696 kNumArguments,
697 Array::ZoneHandle(), // No optional arguments.
698 locs(),
699 relational_ic_data);
528 } 700 }
529 701
530 702
531 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, 703 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
532 BranchInstr* branch) { 704 BranchInstr* branch) {
533 UNIMPLEMENTED(); 705 if (operands_class_id() == kSmiCid) {
706 EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
707 return;
708 }
709 if (operands_class_id() == kMintCid) {
710 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch);
711 return;
712 }
713 if (operands_class_id() == kDoubleCid) {
714 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
715 return;
716 }
717 EmitNativeCode(compiler);
718 __ CompareObject(R0, Bool::True());
719 branch->EmitBranchOnCondition(compiler, EQ);
534 } 720 }
535 721
536 722
537 LocationSummary* NativeCallInstr::MakeLocationSummary() const { 723 LocationSummary* NativeCallInstr::MakeLocationSummary() const {
538 const intptr_t kNumInputs = 0; 724 const intptr_t kNumInputs = 0;
539 const intptr_t kNumTemps = 3; 725 const intptr_t kNumTemps = 3;
540 LocationSummary* locs = 726 LocationSummary* locs =
541 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 727 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
542 locs->set_temp(0, Location::RegisterLocation(R1)); 728 locs->set_temp(0, Location::RegisterLocation(R1));
543 locs->set_temp(1, Location::RegisterLocation(R2)); 729 locs->set_temp(1, Location::RegisterLocation(R2));
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 1033
848 __ LoadImmediate(IP, Isolate::Current()->stack_limit_address()); 1034 __ LoadImmediate(IP, Isolate::Current()->stack_limit_address());
849 __ ldr(IP, Address(IP)); 1035 __ ldr(IP, Address(IP));
850 __ cmp(SP, ShifterOperand(IP)); 1036 __ cmp(SP, ShifterOperand(IP));
851 __ b(slow_path->entry_label(), LS); 1037 __ b(slow_path->entry_label(), LS);
852 __ Bind(slow_path->exit_label()); 1038 __ Bind(slow_path->exit_label());
853 } 1039 }
854 1040
855 1041
856 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { 1042 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
857 UNIMPLEMENTED(); 1043 const intptr_t kNumInputs = 2;
858 return NULL; 1044 if (op_kind() == Token::kTRUNCDIV) {
1045 UNIMPLEMENTED();
1046 return NULL;
1047 } else {
1048 const intptr_t kNumTemps = 0;
1049 LocationSummary* summary =
1050 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1051 summary->set_in(0, Location::RequiresRegister());
1052 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
1053 // We make use of 3-operand instructions by not requiring result register
1054 // to be identical to first input register as on Intel.
1055 summary->set_out(Location::RequiresRegister());
1056 return summary;
1057 }
859 } 1058 }
860 1059
861 1060
862 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1061 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
863 UNIMPLEMENTED(); 1062 if (op_kind() == Token::kSHL) {
1063 UNIMPLEMENTED();
1064 return;
1065 }
1066
1067 ASSERT(!is_truncating());
1068 Register left = locs()->in(0).reg();
1069 Register result = locs()->out().reg();
1070 Label* deopt = NULL;
1071 if (CanDeoptimize()) {
1072 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
1073 }
1074
1075 if (locs()->in(1).IsConstant()) {
1076 const Object& constant = locs()->in(1).constant();
1077 ASSERT(constant.IsSmi());
1078 int32_t imm = reinterpret_cast<int32_t>(constant.raw());
1079 switch (op_kind()) {
1080 case Token::kSUB: {
1081 imm = -imm; // TODO(regis): What if deopt != NULL && imm == 0x80000000?
1082 // Fall through.
1083 }
1084 case Token::kADD: {
1085 if (deopt == NULL) {
1086 __ AddImmediate(result, left, imm);
1087 } else {
1088 __ AddImmediateSetFlags(result, left, imm);
1089 __ b(deopt, VS);
1090 }
1091 break;
1092 }
1093 case Token::kMUL: {
1094 // Keep left value tagged and untag right value.
1095 const intptr_t value = Smi::Cast(constant).Value();
1096 if (value == 2) {
1097 __ mov(result, ShifterOperand(left, LSL, 1));
1098 } else {
1099 __ LoadImmediate(IP, value);
1100 __ mul(result, left, IP);
1101 }
1102 if (deopt != NULL) {
1103 UNIMPLEMENTED();
1104 }
1105 break;
1106 }
1107 case Token::kTRUNCDIV: {
1108 UNIMPLEMENTED();
1109 break;
1110 }
1111 case Token::kBIT_AND: {
1112 // No overflow check.
1113 ShifterOperand shifter_op;
1114 if (ShifterOperand::CanHold(imm, &shifter_op)) {
1115 __ and_(result, left, shifter_op);
1116 } else {
1117 // TODO(regis): Try to use bic.
1118 __ LoadImmediate(IP, imm);
1119 __ and_(result, left, ShifterOperand(IP));
1120 }
1121 break;
1122 }
1123 case Token::kBIT_OR: {
1124 // No overflow check.
1125 ShifterOperand shifter_op;
1126 if (ShifterOperand::CanHold(imm, &shifter_op)) {
1127 __ orr(result, left, shifter_op);
1128 } else {
1129 // TODO(regis): Try to use orn.
1130 __ LoadImmediate(IP, imm);
1131 __ orr(result, left, ShifterOperand(IP));
1132 }
1133 break;
1134 }
1135 case Token::kBIT_XOR: {
1136 // No overflow check.
1137 ShifterOperand shifter_op;
1138 if (ShifterOperand::CanHold(imm, &shifter_op)) {
1139 __ eor(result, left, shifter_op);
1140 } else {
1141 __ LoadImmediate(IP, imm);
1142 __ eor(result, left, ShifterOperand(IP));
1143 }
1144 break;
1145 }
1146 case Token::kSHR: {
1147 UNIMPLEMENTED();
1148 break;
1149 }
1150
1151 default:
1152 UNREACHABLE();
1153 break;
1154 }
1155 return;
1156 }
1157
1158 Register right = locs()->in(1).reg();
1159 switch (op_kind()) {
1160 case Token::kADD: {
1161 if (deopt == NULL) {
1162 __ add(result, left, ShifterOperand(right));
1163 } else {
1164 __ adds(result, left, ShifterOperand(right));
1165 __ b(deopt, VS);
1166 }
1167 break;
1168 }
1169 case Token::kSUB: {
1170 if (deopt == NULL) {
1171 __ sub(result, left, ShifterOperand(right));
1172 } else {
1173 __ subs(result, left, ShifterOperand(right));
1174 __ b(deopt, VS);
1175 }
1176 break;
1177 }
1178 case Token::kMUL: {
1179 __ SmiUntag(left);
1180 __ mul(result, left, right);
1181 if (deopt != NULL) {
1182 UNIMPLEMENTED();
1183 }
1184 break;
1185 }
1186 case Token::kBIT_AND: {
1187 // No overflow check.
1188 __ and_(result, left, ShifterOperand(right));
1189 break;
1190 }
1191 case Token::kBIT_OR: {
1192 // No overflow check.
1193 __ orr(result, left, ShifterOperand(right));
1194 break;
1195 }
1196 case Token::kBIT_XOR: {
1197 // No overflow check.
1198 __ eor(result, left, ShifterOperand(right));
1199 break;
1200 }
1201 case Token::kTRUNCDIV: {
1202 UNIMPLEMENTED();
1203 break;
1204 }
1205 case Token::kSHR: {
1206 UNIMPLEMENTED();
1207 break;
1208 }
1209 case Token::kDIV: {
1210 // Dispatches to 'Double./'.
1211 // TODO(srdjan): Implement as conversion to double and double division.
1212 UNREACHABLE();
1213 break;
1214 }
1215 case Token::kMOD: {
1216 // TODO(srdjan): Implement.
1217 UNREACHABLE();
1218 break;
1219 }
1220 case Token::kOR:
1221 case Token::kAND: {
1222 // Flow graph builder has dissected this operation to guarantee correct
1223 // behavior (short-circuit evaluation).
1224 UNREACHABLE();
1225 break;
1226 }
1227 default:
1228 UNREACHABLE();
1229 break;
1230 }
864 } 1231 }
865 1232
866 1233
867 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const { 1234 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
868 UNIMPLEMENTED(); 1235 UNIMPLEMENTED();
869 return NULL; 1236 return NULL;
870 } 1237 }
871 1238
872 1239
873 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1240 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
979 return NULL; 1346 return NULL;
980 } 1347 }
981 1348
982 1349
983 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1350 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
984 UNIMPLEMENTED(); 1351 UNIMPLEMENTED();
985 } 1352 }
986 1353
987 1354
988 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { 1355 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const {
989 UNIMPLEMENTED(); 1356 return MakeCallSummary();
990 return NULL;
991 } 1357 }
992 1358
993 1359
994 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1360 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
995 UNIMPLEMENTED(); 1361 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1362 kDeoptPolymorphicInstanceCallTestFail);
1363 if (ic_data().NumberOfChecks() == 0) {
1364 __ b(deopt);
1365 return;
1366 }
1367 ASSERT(ic_data().num_args_tested() == 1);
1368 if (!with_checks()) {
1369 ASSERT(ic_data().HasOneTarget());
1370 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
1371 compiler->GenerateStaticCall(instance_call()->deopt_id(),
1372 instance_call()->token_pos(),
1373 target,
1374 instance_call()->ArgumentCount(),
1375 instance_call()->argument_names(),
1376 locs());
1377 return;
1378 }
1379
1380 // Load receiver into R0.
1381 __ ldr(R0, Address(SP, (instance_call()->ArgumentCount() - 1) * kWordSize));
1382
1383 LoadValueCid(compiler, R2, R0,
1384 (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
1385
1386 compiler->EmitTestAndCall(ic_data(),
1387 R2, // Class id register.
1388 instance_call()->ArgumentCount(),
1389 instance_call()->argument_names(),
1390 deopt,
1391 instance_call()->deopt_id(),
1392 instance_call()->token_pos(),
1393 locs());
996 } 1394 }
997 1395
998 1396
999 LocationSummary* BranchInstr::MakeLocationSummary() const { 1397 LocationSummary* BranchInstr::MakeLocationSummary() const {
1000 UNREACHABLE(); 1398 UNREACHABLE();
1001 return NULL; 1399 return NULL;
1002 } 1400 }
1003 1401
1004 1402
1005 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1403 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1006 comparison()->EmitBranchCode(compiler, this); 1404 comparison()->EmitBranchCode(compiler, this);
1007 } 1405 }
1008 1406
1009 1407
1010 LocationSummary* CheckClassInstr::MakeLocationSummary() const { 1408 LocationSummary* CheckClassInstr::MakeLocationSummary() const {
1011 UNIMPLEMENTED(); 1409 UNIMPLEMENTED();
1012 return NULL; 1410 return NULL;
1013 } 1411 }
1014 1412
1015 1413
1016 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1414 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1017 UNIMPLEMENTED(); 1415 UNIMPLEMENTED();
1018 } 1416 }
1019 1417
1020 1418
1021 LocationSummary* CheckSmiInstr::MakeLocationSummary() const { 1419 LocationSummary* CheckSmiInstr::MakeLocationSummary() const {
1022 UNIMPLEMENTED(); 1420 const intptr_t kNumInputs = 1;
1023 return NULL; 1421 const intptr_t kNumTemps = 0;
1422 LocationSummary* summary =
1423 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1424 summary->set_in(0, Location::RequiresRegister());
1425 return summary;
1024 } 1426 }
1025 1427
1026 1428
1027 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1429 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1028 UNIMPLEMENTED(); 1430 Register value = locs()->in(0).reg();
1431 Label* deopt = compiler->AddDeoptStub(deopt_id(),
1432 kDeoptCheckSmi);
1433 __ tst(value, ShifterOperand(kSmiTagMask));
1434 __ b(deopt, NE);
1029 } 1435 }
1030 1436
1031 1437
1032 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const { 1438 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const {
1033 UNIMPLEMENTED(); 1439 UNIMPLEMENTED();
1034 return NULL; 1440 return NULL;
1035 } 1441 }
1036 1442
1037 1443
1038 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1444 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
1349 1755
1350 1756
1351 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1757 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1352 UNIMPLEMENTED(); 1758 UNIMPLEMENTED();
1353 } 1759 }
1354 1760
1355 } // namespace dart 1761 } // namespace dart
1356 1762
1357 #endif // defined TARGET_ARCH_ARM 1763 #endif // defined TARGET_ARCH_ARM
1358 1764
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698