| 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 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 257 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 258 Register obj = locs()->in(0).reg(); | 258 Register obj = locs()->in(0).reg(); |
| 259 Register result = locs()->out().reg(); | 259 Register result = locs()->out().reg(); |
| 260 | 260 |
| 261 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 261 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
| 262 ASSERT(obj == result); | 262 ASSERT(obj == result); |
| 263 } | 263 } |
| 264 | 264 |
| 265 | 265 |
| 266 LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const { | 266 LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const { |
| 267 UNIMPLEMENTED(); | 267 const intptr_t kNumInputs = 1; |
| 268 return NULL; | 268 const intptr_t kNumTemps = 0; |
| 269 LocationSummary* locs = |
| 270 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 271 locs->set_in(0, Location::RegisterLocation(R0)); |
| 272 locs->set_out(Location::RegisterLocation(R0)); |
| 273 return locs; |
| 269 } | 274 } |
| 270 | 275 |
| 271 | 276 |
| 272 void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 277 void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 273 UNIMPLEMENTED(); | 278 Register saved_args_desc = locs()->in(0).reg(); |
| 279 Register result = locs()->out().reg(); |
| 280 |
| 281 // Push the result place holder initialized to NULL. |
| 282 __ PushObject(Object::ZoneHandle()); |
| 283 __ LoadImmediate(IP, Smi::RawValue(formal_parameter_index())); |
| 284 __ Push(IP); |
| 285 __ PushObject(formal_parameter_name()); |
| 286 __ Push(saved_args_desc); |
| 287 compiler->GenerateCallRuntime(token_pos(), |
| 288 deopt_id(), |
| 289 kArgumentDefinitionTestRuntimeEntry, |
| 290 locs()); |
| 291 __ Drop(3); |
| 292 __ Pop(result); // Pop bool result. |
| 274 } | 293 } |
| 275 | 294 |
| 276 | 295 |
| 277 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 296 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
| 278 switch (kind) { | 297 switch (kind) { |
| 279 case Token::kEQ: return EQ; | 298 case Token::kEQ: return EQ; |
| 280 case Token::kNE: return NE; | 299 case Token::kNE: return NE; |
| 281 case Token::kLT: return LT; | 300 case Token::kLT: return LT; |
| 282 case Token::kGT: return GT; | 301 case Token::kGT: return GT; |
| 283 case Token::kLTE: return LE; | 302 case Token::kLTE: return LE; |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 } | 577 } |
| 559 | 578 |
| 560 | 579 |
| 561 // Emit code when ICData's targets are all Object == (which is ===). | 580 // Emit code when ICData's targets are all Object == (which is ===). |
| 562 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, | 581 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, |
| 563 const ICData& ic_data, | 582 const ICData& ic_data, |
| 564 const LocationSummary& locs, | 583 const LocationSummary& locs, |
| 565 Token::Kind kind, | 584 Token::Kind kind, |
| 566 BranchInstr* branch, | 585 BranchInstr* branch, |
| 567 intptr_t deopt_id) { | 586 intptr_t deopt_id) { |
| 568 UNIMPLEMENTED(); | 587 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 588 Register left = locs.in(0).reg(); |
| 589 Register right = locs.in(1).reg(); |
| 590 Register temp = locs.temp(0).reg(); |
| 591 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); |
| 592 __ tst(left, ShifterOperand(kSmiTagMask)); |
| 593 __ b(deopt, EQ); |
| 594 // 'left' is not Smi. |
| 595 Label identity_compare; |
| 596 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); |
| 597 __ cmp(right, ShifterOperand(IP)); |
| 598 __ b(&identity_compare, EQ); |
| 599 __ cmp(left, ShifterOperand(IP)); |
| 600 __ b(&identity_compare, EQ); |
| 601 |
| 602 __ LoadClassId(temp, left); |
| 603 const intptr_t len = ic_data.NumberOfChecks(); |
| 604 for (intptr_t i = 0; i < len; i++) { |
| 605 __ CompareImmediate(temp, ic_data.GetReceiverClassIdAt(i)); |
| 606 if (i == (len - 1)) { |
| 607 __ b(deopt, NE); |
| 608 } else { |
| 609 __ b(&identity_compare, EQ); |
| 610 } |
| 611 } |
| 612 __ Bind(&identity_compare); |
| 613 __ cmp(left, ShifterOperand(right)); |
| 614 if (branch == NULL) { |
| 615 Register result = locs.out().reg(); |
| 616 __ LoadObject(result, |
| 617 (kind == Token::kEQ) ? Bool::True() : Bool::False(), EQ); |
| 618 __ LoadObject(result, |
| 619 (kind == Token::kEQ) ? Bool::False() : Bool::True(), NE); |
| 620 } else { |
| 621 Condition cond = TokenKindToSmiCondition(kind); |
| 622 branch->EmitBranchOnCondition(compiler, cond); |
| 623 } |
| 569 } | 624 } |
| 570 | 625 |
| 571 | 626 |
| 572 // First test if receiver is NULL, in which case === is applied. | 627 // First test if receiver is NULL, in which case === is applied. |
| 573 // If type feedback was provided (lists of <class-id, target>), do a | 628 // If type feedback was provided (lists of <class-id, target>), do a |
| 574 // type by type check (either === or static call to the operator. | 629 // type by type check (either === or static call to the operator. |
| 575 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, | 630 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
| 576 LocationSummary* locs, | 631 LocationSummary* locs, |
| 577 Token::Kind kind, | 632 Token::Kind kind, |
| 578 BranchInstr* branch, | 633 BranchInstr* branch, |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 | 727 |
| 673 | 728 |
| 674 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | 729 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
| 675 const LocationSummary& locs, | 730 const LocationSummary& locs, |
| 676 Token::Kind kind, | 731 Token::Kind kind, |
| 677 BranchInstr* branch) { | 732 BranchInstr* branch) { |
| 678 UNIMPLEMENTED(); | 733 UNIMPLEMENTED(); |
| 679 } | 734 } |
| 680 | 735 |
| 681 | 736 |
| 737 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 738 switch (kind) { |
| 739 case Token::kEQ: return EQ; |
| 740 case Token::kNE: return NE; |
| 741 case Token::kLT: return LT; |
| 742 case Token::kGT: return GT; |
| 743 case Token::kLTE: return LE; |
| 744 case Token::kGTE: return GE; |
| 745 default: |
| 746 UNREACHABLE(); |
| 747 return VS; |
| 748 } |
| 749 } |
| 750 |
| 751 |
| 682 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 752 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 683 const LocationSummary& locs, | 753 const LocationSummary& locs, |
| 684 Token::Kind kind, | 754 Token::Kind kind, |
| 685 BranchInstr* branch) { | 755 BranchInstr* branch) { |
| 686 UNIMPLEMENTED(); | 756 DRegister left = locs.in(0).fpu_reg(); |
| 757 DRegister right = locs.in(1).fpu_reg(); |
| 758 |
| 759 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 760 if (branch != NULL) { |
| 761 compiler->EmitDoubleCompareBranch( |
| 762 true_condition, left, right, branch); |
| 763 } else { |
| 764 compiler->EmitDoubleCompareBool( |
| 765 true_condition, left, right, locs.out().reg()); |
| 766 } |
| 687 } | 767 } |
| 688 | 768 |
| 689 | 769 |
| 690 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 770 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 691 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 771 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 692 BranchInstr* kNoBranch = NULL; | 772 BranchInstr* kNoBranch = NULL; |
| 693 if (receiver_class_id() == kSmiCid) { | 773 if (receiver_class_id() == kSmiCid) { |
| 694 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); | 774 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); |
| 695 return; | 775 return; |
| 696 } | 776 } |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 951 __ LoadImmediate(R1, NativeArguments::ComputeArgcTag(function())); | 1031 __ LoadImmediate(R1, NativeArguments::ComputeArgcTag(function())); |
| 952 compiler->GenerateCall(token_pos(), | 1032 compiler->GenerateCall(token_pos(), |
| 953 &StubCode::CallNativeCFunctionLabel(), | 1033 &StubCode::CallNativeCFunctionLabel(), |
| 954 PcDescriptors::kOther, | 1034 PcDescriptors::kOther, |
| 955 locs()); | 1035 locs()); |
| 956 __ Pop(result); | 1036 __ Pop(result); |
| 957 } | 1037 } |
| 958 | 1038 |
| 959 | 1039 |
| 960 LocationSummary* StringFromCharCodeInstr::MakeLocationSummary() const { | 1040 LocationSummary* StringFromCharCodeInstr::MakeLocationSummary() const { |
| 961 UNIMPLEMENTED(); | 1041 const intptr_t kNumInputs = 1; |
| 962 return NULL; | 1042 // TODO(fschneider): Allow immediate operands for the char code. |
| 1043 return LocationSummary::Make(kNumInputs, |
| 1044 Location::RequiresRegister(), |
| 1045 LocationSummary::kNoCall); |
| 963 } | 1046 } |
| 964 | 1047 |
| 965 | 1048 |
| 966 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1049 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 967 UNIMPLEMENTED(); | 1050 Register char_code = locs()->in(0).reg(); |
| 1051 Register result = locs()->out().reg(); |
| 1052 __ LoadImmediate(result, |
| 1053 reinterpret_cast<uword>(Symbols::PredefinedAddress())); |
| 1054 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); |
| 1055 __ ldr(result, Address(result, char_code, LSL, 1)); // Char code is a smi. |
| 968 } | 1056 } |
| 969 | 1057 |
| 970 | 1058 |
| 971 LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const { | 1059 LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const { |
| 972 UNIMPLEMENTED(); | 1060 UNIMPLEMENTED(); |
| 973 return NULL; | 1061 return NULL; |
| 974 } | 1062 } |
| 975 | 1063 |
| 976 | 1064 |
| 977 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1065 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1693 compiler->GenerateCall(token_pos(), | 1781 compiler->GenerateCall(token_pos(), |
| 1694 &StubCode::AllocateArrayLabel(), | 1782 &StubCode::AllocateArrayLabel(), |
| 1695 PcDescriptors::kOther, | 1783 PcDescriptors::kOther, |
| 1696 locs()); | 1784 locs()); |
| 1697 ASSERT(locs()->out().reg() == R0); | 1785 ASSERT(locs()->out().reg() == R0); |
| 1698 } | 1786 } |
| 1699 | 1787 |
| 1700 | 1788 |
| 1701 LocationSummary* | 1789 LocationSummary* |
| 1702 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const { | 1790 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const { |
| 1703 UNIMPLEMENTED(); | 1791 return MakeCallSummary(); |
| 1704 return NULL; | |
| 1705 } | 1792 } |
| 1706 | 1793 |
| 1707 | 1794 |
| 1708 void AllocateObjectWithBoundsCheckInstr::EmitNativeCode( | 1795 void AllocateObjectWithBoundsCheckInstr::EmitNativeCode( |
| 1709 FlowGraphCompiler* compiler) { | 1796 FlowGraphCompiler* compiler) { |
| 1710 UNIMPLEMENTED(); | 1797 compiler->GenerateCallRuntime(token_pos(), |
| 1798 deopt_id(), |
| 1799 kAllocateObjectWithBoundsCheckRuntimeEntry, |
| 1800 locs()); |
| 1801 __ Drop(3); |
| 1802 ASSERT(locs()->out().reg() == R0); |
| 1803 __ Pop(R0); // Pop new instance. |
| 1711 } | 1804 } |
| 1712 | 1805 |
| 1713 | 1806 |
| 1714 LocationSummary* LoadFieldInstr::MakeLocationSummary() const { | 1807 LocationSummary* LoadFieldInstr::MakeLocationSummary() const { |
| 1715 return LocationSummary::Make(1, | 1808 return LocationSummary::Make(1, |
| 1716 Location::RequiresRegister(), | 1809 Location::RequiresRegister(), |
| 1717 LocationSummary::kNoCall); | 1810 LocationSummary::kNoCall); |
| 1718 } | 1811 } |
| 1719 | 1812 |
| 1720 | 1813 |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1875 const ExternalLabel label("alloc_context", | 1968 const ExternalLabel label("alloc_context", |
| 1876 StubCode::AllocateContextEntryPoint()); | 1969 StubCode::AllocateContextEntryPoint()); |
| 1877 compiler->GenerateCall(token_pos(), | 1970 compiler->GenerateCall(token_pos(), |
| 1878 &label, | 1971 &label, |
| 1879 PcDescriptors::kOther, | 1972 PcDescriptors::kOther, |
| 1880 locs()); | 1973 locs()); |
| 1881 } | 1974 } |
| 1882 | 1975 |
| 1883 | 1976 |
| 1884 LocationSummary* CloneContextInstr::MakeLocationSummary() const { | 1977 LocationSummary* CloneContextInstr::MakeLocationSummary() const { |
| 1885 UNIMPLEMENTED(); | 1978 const intptr_t kNumInputs = 1; |
| 1886 return NULL; | 1979 const intptr_t kNumTemps = 0; |
| 1980 LocationSummary* locs = |
| 1981 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1982 locs->set_in(0, Location::RegisterLocation(R0)); |
| 1983 locs->set_out(Location::RegisterLocation(R0)); |
| 1984 return locs; |
| 1887 } | 1985 } |
| 1888 | 1986 |
| 1889 | 1987 |
| 1890 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1988 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1891 UNIMPLEMENTED(); | 1989 Register context_value = locs()->in(0).reg(); |
| 1990 Register result = locs()->out().reg(); |
| 1991 |
| 1992 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1993 __ Push(context_value); |
| 1994 compiler->GenerateCallRuntime(token_pos(), |
| 1995 deopt_id(), |
| 1996 kCloneContextRuntimeEntry, |
| 1997 locs()); |
| 1998 __ Drop(1); // Remove argument. |
| 1999 __ Pop(result); // Get result (cloned context). |
| 1892 } | 2000 } |
| 1893 | 2001 |
| 1894 | 2002 |
| 1895 LocationSummary* CatchEntryInstr::MakeLocationSummary() const { | 2003 LocationSummary* CatchEntryInstr::MakeLocationSummary() const { |
| 1896 return LocationSummary::Make(0, | 2004 return LocationSummary::Make(0, |
| 1897 Location::NoLocation(), | 2005 Location::NoLocation(), |
| 1898 LocationSummary::kNoCall); | 2006 LocationSummary::kNoCall); |
| 1899 } | 2007 } |
| 1900 | 2008 |
| 1901 | 2009 |
| (...skipping 859 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2761 return NULL; | 2869 return NULL; |
| 2762 } | 2870 } |
| 2763 | 2871 |
| 2764 | 2872 |
| 2765 void BinaryUint32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2873 void BinaryUint32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2766 UNIMPLEMENTED(); | 2874 UNIMPLEMENTED(); |
| 2767 } | 2875 } |
| 2768 | 2876 |
| 2769 | 2877 |
| 2770 LocationSummary* MathSqrtInstr::MakeLocationSummary() const { | 2878 LocationSummary* MathSqrtInstr::MakeLocationSummary() const { |
| 2771 UNIMPLEMENTED(); | 2879 const intptr_t kNumInputs = 1; |
| 2772 return NULL; | 2880 const intptr_t kNumTemps = 0; |
| 2881 LocationSummary* summary = |
| 2882 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2883 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2884 summary->set_out(Location::RequiresFpuRegister()); |
| 2885 return summary; |
| 2773 } | 2886 } |
| 2774 | 2887 |
| 2775 | 2888 |
| 2776 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2889 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2777 UNIMPLEMENTED(); | 2890 __ vsqrtd(locs()->out().fpu_reg(), locs()->in(0).fpu_reg()); |
| 2778 } | 2891 } |
| 2779 | 2892 |
| 2780 | 2893 |
| 2781 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { | 2894 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { |
| 2782 const intptr_t kNumInputs = 1; | 2895 const intptr_t kNumInputs = 1; |
| 2783 const intptr_t kNumTemps = 0; | 2896 const intptr_t kNumTemps = 0; |
| 2784 LocationSummary* summary = | 2897 LocationSummary* summary = |
| 2785 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2898 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2786 summary->set_in(0, Location::RequiresRegister()); | 2899 summary->set_in(0, Location::RequiresRegister()); |
| 2787 // We make use of 3-operand instructions by not requiring result register | 2900 // We make use of 3-operand instructions by not requiring result register |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2807 // Remove inverted smi-tag. | 2920 // Remove inverted smi-tag. |
| 2808 __ bic(result, result, ShifterOperand(kSmiTagMask)); | 2921 __ bic(result, result, ShifterOperand(kSmiTagMask)); |
| 2809 break; | 2922 break; |
| 2810 default: | 2923 default: |
| 2811 UNREACHABLE(); | 2924 UNREACHABLE(); |
| 2812 } | 2925 } |
| 2813 } | 2926 } |
| 2814 | 2927 |
| 2815 | 2928 |
| 2816 LocationSummary* SmiToDoubleInstr::MakeLocationSummary() const { | 2929 LocationSummary* SmiToDoubleInstr::MakeLocationSummary() const { |
| 2817 UNIMPLEMENTED(); | 2930 const intptr_t kNumInputs = 1; |
| 2818 return NULL; | 2931 const intptr_t kNumTemps = 0; |
| 2932 LocationSummary* result = |
| 2933 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2934 result->set_in(0, Location::WritableRegister()); |
| 2935 result->set_out(Location::RequiresFpuRegister()); |
| 2936 return result; |
| 2819 } | 2937 } |
| 2820 | 2938 |
| 2821 | 2939 |
| 2822 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2940 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2823 UNIMPLEMENTED(); | 2941 Register value = locs()->in(0).reg(); |
| 2942 FpuRegister result = locs()->out().fpu_reg(); |
| 2943 __ SmiUntag(value); |
| 2944 __ vmovsr(S0, value); |
| 2945 __ vcvtdi(result, S0); |
| 2824 } | 2946 } |
| 2825 | 2947 |
| 2826 | 2948 |
| 2827 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary() const { | 2949 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary() const { |
| 2828 UNIMPLEMENTED(); | 2950 const intptr_t kNumInputs = 1; |
| 2829 return NULL; | 2951 const intptr_t kNumTemps = 0; |
| 2952 LocationSummary* result = |
| 2953 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2954 result->set_in(0, Location::RegisterLocation(R1)); |
| 2955 result->set_out(Location::RegisterLocation(R0)); |
| 2956 return result; |
| 2830 } | 2957 } |
| 2831 | 2958 |
| 2832 | 2959 |
| 2833 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2960 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2834 UNIMPLEMENTED(); | 2961 Register result = locs()->out().reg(); |
| 2962 Register value_obj = locs()->in(0).reg(); |
| 2963 ASSERT(result == R0); |
| 2964 ASSERT(result != value_obj); |
| 2965 __ LoadDFromOffset(D0, value_obj, Double::value_offset() - kHeapObjectTag); |
| 2966 __ vcvtid(S0, D0); |
| 2967 __ vmovrs(result, S0); |
| 2968 // Overflow is signaled with minint. |
| 2969 Label do_call, done; |
| 2970 // Check for overflow and that it fits into Smi. |
| 2971 __ CompareImmediate(result, 0xC0000000); |
| 2972 __ b(&do_call, MI); |
| 2973 __ SmiTag(result); |
| 2974 __ b(&done); |
| 2975 __ Bind(&do_call); |
| 2976 __ Push(value_obj); |
| 2977 ASSERT(instance_call()->HasICData()); |
| 2978 const ICData& ic_data = *instance_call()->ic_data(); |
| 2979 ASSERT((ic_data.NumberOfChecks() == 1)); |
| 2980 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
| 2981 |
| 2982 const intptr_t kNumberOfArguments = 1; |
| 2983 compiler->GenerateStaticCall(deopt_id(), |
| 2984 instance_call()->token_pos(), |
| 2985 target, |
| 2986 kNumberOfArguments, |
| 2987 Array::Handle(), // No argument names., |
| 2988 locs()); |
| 2989 __ Bind(&done); |
| 2835 } | 2990 } |
| 2836 | 2991 |
| 2837 | 2992 |
| 2838 LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const { | 2993 LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const { |
| 2839 UNIMPLEMENTED(); | 2994 const intptr_t kNumInputs = 1; |
| 2840 return NULL; | 2995 const intptr_t kNumTemps = 0; |
| 2996 LocationSummary* result = new LocationSummary( |
| 2997 kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2998 result->set_in(0, Location::RequiresFpuRegister()); |
| 2999 result->set_out(Location::RequiresRegister()); |
| 3000 return result; |
| 2841 } | 3001 } |
| 2842 | 3002 |
| 2843 | 3003 |
| 2844 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3004 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2845 UNIMPLEMENTED(); | 3005 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi); |
| 3006 Register result = locs()->out().reg(); |
| 3007 DRegister value = locs()->in(0).fpu_reg(); |
| 3008 __ vcvtid(S0, value); |
| 3009 __ vmovrs(result, S0); |
| 3010 // Check for overflow and that it fits into Smi. |
| 3011 __ CompareImmediate(result, 0xC0000000); |
| 3012 __ b(deopt, MI); |
| 3013 __ SmiTag(result); |
| 2846 } | 3014 } |
| 2847 | 3015 |
| 2848 | 3016 |
| 2849 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const { | 3017 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const { |
| 2850 UNIMPLEMENTED(); | 3018 const intptr_t kNumInputs = 1; |
| 2851 return NULL; | 3019 const intptr_t kNumTemps = 0; |
| 3020 LocationSummary* result = |
| 3021 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3022 result->set_in(0, Location::RequiresFpuRegister()); |
| 3023 result->set_out(Location::RequiresFpuRegister()); |
| 3024 return result; |
| 2852 } | 3025 } |
| 2853 | 3026 |
| 2854 | 3027 |
| 2855 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3028 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2856 UNIMPLEMENTED(); | 3029 // DRegister value = locs()->in(0).fpu_reg(); |
| 3030 // DRegister result = locs()->out().fpu_reg(); |
| 3031 switch (recognized_kind()) { |
| 3032 case MethodRecognizer::kDoubleTruncate: |
| 3033 UNIMPLEMENTED(); |
| 3034 // __ roundsd(result, value, Assembler::kRoundToZero); |
| 3035 break; |
| 3036 case MethodRecognizer::kDoubleFloor: |
| 3037 UNIMPLEMENTED(); |
| 3038 // __ roundsd(result, value, Assembler::kRoundDown); |
| 3039 break; |
| 3040 case MethodRecognizer::kDoubleCeil: |
| 3041 UNIMPLEMENTED(); |
| 3042 // __ roundsd(result, value, Assembler::kRoundUp); |
| 3043 break; |
| 3044 default: |
| 3045 UNREACHABLE(); |
| 3046 } |
| 2857 } | 3047 } |
| 2858 | 3048 |
| 2859 | 3049 |
| 2860 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const { | 3050 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const { |
| 2861 UNIMPLEMENTED(); | 3051 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
| 2862 return NULL; | 3052 const intptr_t kNumTemps = 0; |
| 3053 LocationSummary* result = |
| 3054 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); |
| 3055 result->set_in(0, Location::FpuRegisterLocation(D1)); |
| 3056 if (InputCount() == 2) { |
| 3057 result->set_in(1, Location::FpuRegisterLocation(D2)); |
| 3058 } |
| 3059 result->set_out(Location::FpuRegisterLocation(D1)); |
| 3060 return result; |
| 2863 } | 3061 } |
| 2864 | 3062 |
| 2865 | 3063 |
| 2866 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3064 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2867 UNIMPLEMENTED(); | 3065 // For pow-function return NAN if exponent is NAN. |
| 3066 Label do_call, skip_call; |
| 3067 if (recognized_kind() == MethodRecognizer::kDoublePow) { |
| 3068 DRegister exp = locs()->in(1).fpu_reg(); |
| 3069 __ vcmpd(exp, exp); |
| 3070 __ vmstat(); |
| 3071 __ b(&do_call, VC); // NaN -> false; |
| 3072 // Exponent is NaN, return NaN. |
| 3073 __ vmovd(locs()->out().fpu_reg(), exp); |
| 3074 __ b(&skip_call); |
| 3075 } |
| 3076 __ Bind(&do_call); |
| 3077 // TODO(regis): Using D0 as the reserved scratch value is not a good idea. |
| 3078 __ vmovd(D0, locs()->in(0).fpu_reg()); |
| 3079 if (InputCount() == 2) { |
| 3080 __ vmovd(D1, locs()->in(1).fpu_reg()); |
| 3081 } |
| 3082 UNIMPLEMENTED(); // TODO(regis): We need to support double type leaf calls. |
| 3083 __ CallRuntime(TargetFunction()); |
| 3084 __ vmovd(locs()->out().fpu_reg(), D0); |
| 3085 __ Bind(&skip_call); |
| 2868 } | 3086 } |
| 2869 | 3087 |
| 2870 | 3088 |
| 2871 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { | 3089 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { |
| 2872 return MakeCallSummary(); | 3090 return MakeCallSummary(); |
| 2873 } | 3091 } |
| 2874 | 3092 |
| 2875 | 3093 |
| 2876 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3094 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2877 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 3095 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3367 compiler->GenerateCall(token_pos(), | 3585 compiler->GenerateCall(token_pos(), |
| 3368 &label, | 3586 &label, |
| 3369 PcDescriptors::kOther, | 3587 PcDescriptors::kOther, |
| 3370 locs()); | 3588 locs()); |
| 3371 __ Drop(2); // Discard type arguments and receiver. | 3589 __ Drop(2); // Discard type arguments and receiver. |
| 3372 } | 3590 } |
| 3373 | 3591 |
| 3374 } // namespace dart | 3592 } // namespace dart |
| 3375 | 3593 |
| 3376 #endif // defined TARGET_ARCH_ARM | 3594 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |