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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 4734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4745 __ Bind(&do_pow); | 4745 __ Bind(&do_pow); |
4746 } | 4746 } |
4747 __ CallRuntime(TargetFunction(), InputCount()); | 4747 __ CallRuntime(TargetFunction(), InputCount()); |
4748 __ movaps(locs()->out(0).fpu_reg(), XMM0); | 4748 __ movaps(locs()->out(0).fpu_reg(), XMM0); |
4749 __ Bind(&skip_call); | 4749 __ Bind(&skip_call); |
4750 // Restore RSP. | 4750 // Restore RSP. |
4751 __ movq(RSP, locs()->temp(kSavedSpTempIndex).reg()); | 4751 __ movq(RSP, locs()->temp(kSavedSpTempIndex).reg()); |
4752 } | 4752 } |
4753 | 4753 |
4754 | 4754 |
| 4755 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const { |
| 4756 // Only use this instruction in optimized code. |
| 4757 ASSERT(opt); |
| 4758 const intptr_t kNumInputs = 1; |
| 4759 LocationSummary* summary = |
| 4760 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); |
| 4761 if (representation() == kUnboxedDouble) { |
| 4762 if (index() == 0) { |
| 4763 summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(), |
| 4764 Location::Any())); |
| 4765 } else { |
| 4766 ASSERT(index() == 1); |
| 4767 summary->set_in(0, Location::Pair(Location::Any(), |
| 4768 Location::RequiresFpuRegister())); |
| 4769 } |
| 4770 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4771 } else { |
| 4772 ASSERT(representation() == kTagged); |
| 4773 if (index() == 0) { |
| 4774 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 4775 Location::Any())); |
| 4776 } else { |
| 4777 ASSERT(index() == 1); |
| 4778 summary->set_in(0, Location::Pair(Location::Any(), |
| 4779 Location::RequiresRegister())); |
| 4780 } |
| 4781 summary->set_out(0, Location::RequiresRegister()); |
| 4782 } |
| 4783 return summary; |
| 4784 } |
| 4785 |
| 4786 |
| 4787 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4788 ASSERT(locs()->in(0).IsPairLocation()); |
| 4789 PairLocation* pair = locs()->in(0).AsPairLocation(); |
| 4790 Location in_loc = pair->At(index()); |
| 4791 if (representation() == kUnboxedDouble) { |
| 4792 XmmRegister out = locs()->out(0).fpu_reg(); |
| 4793 XmmRegister in = in_loc.fpu_reg(); |
| 4794 __ movaps(out, in); |
| 4795 } else { |
| 4796 ASSERT(representation() == kTagged); |
| 4797 Register out = locs()->out(0).reg(); |
| 4798 Register in = in_loc.reg(); |
| 4799 __ movq(out, in); |
| 4800 } |
| 4801 } |
| 4802 |
| 4803 |
4755 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { | 4804 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { |
4756 if (kind() == MergedMathInstr::kTruncDivMod) { | 4805 if (kind() == MergedMathInstr::kTruncDivMod) { |
4757 const intptr_t kNumInputs = 2; | 4806 const intptr_t kNumInputs = 2; |
4758 const intptr_t kNumTemps = 1; | 4807 const intptr_t kNumTemps = 0; |
4759 LocationSummary* summary = | 4808 LocationSummary* summary = |
4760 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4809 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4761 // Both inputs must be writable because they will be untagged. | 4810 // Both inputs must be writable because they will be untagged. |
4762 summary->set_in(0, Location::RegisterLocation(RAX)); | 4811 summary->set_in(0, Location::RegisterLocation(RAX)); |
4763 summary->set_in(1, Location::WritableRegister()); | 4812 summary->set_in(1, Location::WritableRegister()); |
4764 summary->set_out(0, Location::RequiresRegister()); | 4813 summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX), |
4765 // Will be used for sign extension and division. | 4814 Location::RegisterLocation(RDX))); |
4766 summary->set_temp(0, Location::RegisterLocation(RDX)); | |
4767 return summary; | 4815 return summary; |
4768 } | 4816 } |
4769 if (kind() == MergedMathInstr::kSinCos) { | 4817 if (kind() == MergedMathInstr::kSinCos) { |
4770 const intptr_t kNumInputs = 1; | 4818 const intptr_t kNumInputs = 1; |
4771 const intptr_t kNumTemps = 1; | 4819 const intptr_t kNumTemps = 1; |
4772 LocationSummary* summary = | 4820 LocationSummary* summary = |
4773 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 4821 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 4822 // Because we always call into the runtime (LocationSummary::kCall) we |
| 4823 // must specify each input, temp, and output register explicitly. |
4774 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); | 4824 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); |
4775 // R13 is chosen because it is callee saved so we do not need to back it | 4825 // R13 is chosen because it is callee saved so we do not need to back it |
4776 // up before calling into the runtime. | 4826 // up before calling into the runtime. |
4777 summary->set_temp(0, Location::RegisterLocation(R13)); | 4827 summary->set_temp(0, Location::RegisterLocation(R13)); |
4778 summary->set_out(0, Location::RegisterLocation(RAX)); | 4828 summary->set_out(0, Location::Pair(Location::FpuRegisterLocation(XMM2), |
| 4829 Location::FpuRegisterLocation(XMM3))); |
4779 return summary; | 4830 return summary; |
4780 } | 4831 } |
4781 UNIMPLEMENTED(); | 4832 UNIMPLEMENTED(); |
4782 return NULL; | 4833 return NULL; |
4783 } | 4834 } |
4784 | 4835 |
4785 | 4836 |
4786 | 4837 |
4787 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); | 4838 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); |
4788 | 4839 |
4789 extern const RuntimeEntry kSinCosRuntimeEntry( | 4840 extern const RuntimeEntry kSinCosRuntimeEntry( |
4790 "libc_sincos", reinterpret_cast<RuntimeFunction>( | 4841 "libc_sincos", reinterpret_cast<RuntimeFunction>( |
4791 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); | 4842 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); |
4792 | 4843 |
4793 | 4844 |
4794 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4845 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4795 Label* deopt = NULL; | 4846 Label* deopt = NULL; |
4796 if (CanDeoptimize()) { | 4847 if (CanDeoptimize()) { |
4797 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); | 4848 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
4798 } | 4849 } |
4799 if (kind() == MergedMathInstr::kTruncDivMod) { | 4850 if (kind() == MergedMathInstr::kTruncDivMod) { |
4800 Register left = locs()->in(0).reg(); | 4851 Register left = locs()->in(0).reg(); |
4801 Register right = locs()->in(1).reg(); | 4852 Register right = locs()->in(1).reg(); |
4802 Register result = locs()->out(0).reg(); | 4853 ASSERT(locs()->out(0).IsPairLocation()); |
| 4854 PairLocation* pair = locs()->out(0).AsPairLocation(); |
| 4855 Register result1 = pair->At(0).reg(); |
| 4856 Register result2 = pair->At(1).reg(); |
4803 Label not_32bit, done; | 4857 Label not_32bit, done; |
4804 Register temp = locs()->temp(0).reg(); | 4858 Register temp = RDX; |
4805 ASSERT(left == RAX); | 4859 ASSERT(left == RAX); |
4806 ASSERT((right != RDX) && (right != RAX)); | 4860 ASSERT((right != RDX) && (right != RAX)); |
4807 ASSERT(temp == RDX); | 4861 ASSERT(result1 == RAX); |
4808 ASSERT((result != RDX) && (result != RAX)); | 4862 ASSERT(result2 == RDX); |
4809 | |
4810 Range* right_range = InputAt(1)->definition()->range(); | 4863 Range* right_range = InputAt(1)->definition()->range(); |
4811 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 4864 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
4812 // Handle divide by zero in runtime. | 4865 // Handle divide by zero in runtime. |
4813 __ testq(right, right); | 4866 __ testq(right, right); |
4814 __ j(ZERO, deopt); | 4867 __ j(ZERO, deopt); |
4815 } | 4868 } |
4816 // Check if both operands fit into 32bits as idiv with 64bit operands | 4869 // Check if both operands fit into 32bits as idiv with 64bit operands |
4817 // requires twice as many cycles and has much higher latency. | 4870 // requires twice as many cycles and has much higher latency. |
4818 // We are checking this before untagging them to avoid corner case | 4871 // We are checking this before untagging them to avoid corner case |
4819 // dividing INT_MAX by -1 that raises exception because quotient is | 4872 // dividing INT_MAX by -1 that raises exception because quotient is |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4868 __ Bind(&subtract); | 4921 __ Bind(&subtract); |
4869 __ subq(RDX, right); | 4922 __ subq(RDX, right); |
4870 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) { | 4923 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) { |
4871 // Right is positive. | 4924 // Right is positive. |
4872 __ addq(RDX, right); | 4925 __ addq(RDX, right); |
4873 } else { | 4926 } else { |
4874 // Right is negative. | 4927 // Right is negative. |
4875 __ subq(RDX, right); | 4928 __ subq(RDX, right); |
4876 } | 4929 } |
4877 __ Bind(&all_done); | 4930 __ Bind(&all_done); |
4878 __ SmiTag(result); | |
4879 | 4931 |
4880 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld)), PP); | |
4881 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid); | |
4882 Address trunc_div_address( | |
4883 FlowGraphCompiler::ElementAddressForIntIndex( | |
4884 kArrayCid, index_scale, result, | |
4885 MergedMathInstr::ResultIndexOf(Token::kTRUNCDIV))); | |
4886 Address mod_address( | |
4887 FlowGraphCompiler::ElementAddressForIntIndex( | |
4888 kArrayCid, index_scale, result, | |
4889 MergedMathInstr::ResultIndexOf(Token::kMOD))); | |
4890 __ SmiTag(RAX); | 4932 __ SmiTag(RAX); |
4891 __ SmiTag(RDX); | 4933 __ SmiTag(RDX); |
4892 __ StoreIntoObjectNoBarrier(result, trunc_div_address, RAX); | |
4893 __ StoreIntoObjectNoBarrier(result, mod_address, RDX); | |
4894 // FLAG_throw_on_javascript_int_overflow: not needed. | 4934 // FLAG_throw_on_javascript_int_overflow: not needed. |
4895 // Note that the result of an integer division/modulo of two | 4935 // Note that the result of an integer division/modulo of two |
4896 // in-range arguments, cannot create out-of-range result. | 4936 // in-range arguments, cannot create out-of-range result. |
4897 return; | 4937 return; |
4898 } | 4938 } |
4899 if (kind() == MergedMathInstr::kSinCos) { | 4939 if (kind() == MergedMathInstr::kSinCos) { |
| 4940 ASSERT(locs()->out(0).IsPairLocation()); |
| 4941 PairLocation* pair = locs()->out(0).AsPairLocation(); |
| 4942 XmmRegister out1 = pair->At(0).fpu_reg(); |
| 4943 XmmRegister out2 = pair->At(1).fpu_reg(); |
| 4944 |
4900 // Save RSP. | 4945 // Save RSP. |
4901 __ movq(locs()->temp(0).reg(), RSP); | 4946 __ movq(locs()->temp(0).reg(), RSP); |
4902 // +-------------------------------+ | 4947 // +-------------------------------+ |
4903 // | double-argument | <- TOS | 4948 // | double-argument | <- TOS |
4904 // +-------------------------------+ | 4949 // +-------------------------------+ |
4905 // | address-cos-result | +8 | 4950 // | address-cos-result | +8 |
4906 // +-------------------------------+ | 4951 // +-------------------------------+ |
4907 // | address-sin-result | +16 | 4952 // | address-sin-result | +16 |
4908 // +-------------------------------+ | 4953 // +-------------------------------+ |
4909 // | double-storage-for-cos-result | +24 | 4954 // | double-storage-for-cos-result | +24 |
4910 // +-------------------------------+ | 4955 // +-------------------------------+ |
4911 // | double-storage-for-sin-result | +32 | 4956 // | double-storage-for-sin-result | +32 |
4912 // +-------------------------------+ | 4957 // +-------------------------------+ |
4913 // .... | 4958 // .... |
4914 __ ReserveAlignedFrameSpace(kDoubleSize * 3 + kWordSize * 2); | 4959 __ ReserveAlignedFrameSpace(kDoubleSize * 3 + kWordSize * 2); |
4915 __ movsd(Address(RSP, 0), locs()->in(0).fpu_reg()); | 4960 __ movsd(Address(RSP, 0), locs()->in(0).fpu_reg()); |
4916 | 4961 |
4917 __ leaq(RDI, Address(RSP, 2 * kWordSize + kDoubleSize)); | 4962 __ leaq(RDI, Address(RSP, 2 * kWordSize + kDoubleSize)); |
4918 __ leaq(RSI, Address(RSP, 2 * kWordSize + 2 * kDoubleSize)); | 4963 __ leaq(RSI, Address(RSP, 2 * kWordSize + 2 * kDoubleSize)); |
4919 __ movaps(XMM0, locs()->in(0).fpu_reg()); | 4964 __ movaps(XMM0, locs()->in(0).fpu_reg()); |
4920 | 4965 |
4921 __ CallRuntime(kSinCosRuntimeEntry, InputCount()); | 4966 __ CallRuntime(kSinCosRuntimeEntry, InputCount()); |
4922 __ movsd(XMM0, Address(RSP, 2 * kWordSize + kDoubleSize * 2)); // sin. | 4967 __ movsd(out2, Address(RSP, 2 * kWordSize + kDoubleSize * 2)); // sin. |
4923 __ movsd(XMM1, Address(RSP, 2 * kWordSize + kDoubleSize)); // cos. | 4968 __ movsd(out1, Address(RSP, 2 * kWordSize + kDoubleSize)); // cos. |
4924 // Restore RSP. | 4969 // Restore RSP. |
4925 __ movq(RSP, locs()->temp(0).reg()); | 4970 __ movq(RSP, locs()->temp(0).reg()); |
4926 | 4971 |
4927 Register result = locs()->out(0).reg(); | |
4928 const TypedData& res_array = TypedData::ZoneHandle( | |
4929 TypedData::New(kTypedDataFloat64ArrayCid, 2, Heap::kOld)); | |
4930 __ LoadObject(result, res_array, PP); | |
4931 const intptr_t index_scale = | |
4932 FlowGraphCompiler::ElementSizeFor(kTypedDataFloat64ArrayCid); | |
4933 Address sin_address( | |
4934 FlowGraphCompiler::ElementAddressForIntIndex( | |
4935 kTypedDataFloat64ArrayCid, index_scale, result, | |
4936 MergedMathInstr::ResultIndexOf(MethodRecognizer::kMathSin))); | |
4937 Address cos_address( | |
4938 FlowGraphCompiler::ElementAddressForIntIndex( | |
4939 kTypedDataFloat64ArrayCid, index_scale, result, | |
4940 MergedMathInstr::ResultIndexOf(MethodRecognizer::kMathCos))); | |
4941 __ movsd(sin_address, XMM0); | |
4942 __ movsd(cos_address, XMM1); | |
4943 return; | 4972 return; |
4944 } | 4973 } |
4945 UNIMPLEMENTED(); | 4974 UNIMPLEMENTED(); |
4946 } | 4975 } |
4947 | 4976 |
4948 | 4977 |
4949 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 4978 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
4950 bool opt) const { | 4979 bool opt) const { |
4951 return MakeCallSummary(); | 4980 return MakeCallSummary(); |
4952 } | 4981 } |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5429 PcDescriptors::kOther, | 5458 PcDescriptors::kOther, |
5430 locs()); | 5459 locs()); |
5431 __ Drop(ArgumentCount()); // Discard arguments. | 5460 __ Drop(ArgumentCount()); // Discard arguments. |
5432 } | 5461 } |
5433 | 5462 |
5434 } // namespace dart | 5463 } // namespace dart |
5435 | 5464 |
5436 #undef __ | 5465 #undef __ |
5437 | 5466 |
5438 #endif // defined TARGET_ARCH_X64 | 5467 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |