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? |
| 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 |