OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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? | |
zra
2013/04/05 16:25:02
I guess this would always be an overflow?
regis
2013/04/05 16:46:37
I am not sure. 0xffffffff - 0x80000000 -> 0x7fffff
| |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |