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 = 1; |
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::RequiresRegister(), |
Florian Schneider
2014/04/08 09:48:45
Same here: It should be possible to have the outpu
Cutch
2014/04/08 15:56:16
Done.
| |
4814 Location::RequiresRegister())); | |
4765 // Will be used for sign extension and division. | 4815 // Will be used for sign extension and division. |
4766 summary->set_temp(0, Location::RegisterLocation(RDX)); | 4816 summary->set_temp(0, Location::RegisterLocation(RDX)); |
4767 return summary; | 4817 return summary; |
4768 } | 4818 } |
4769 if (kind() == MergedMathInstr::kSinCos) { | 4819 if (kind() == MergedMathInstr::kSinCos) { |
4770 const intptr_t kNumInputs = 1; | 4820 const intptr_t kNumInputs = 1; |
4771 const intptr_t kNumTemps = 1; | 4821 const intptr_t kNumTemps = 1; |
4772 LocationSummary* summary = | 4822 LocationSummary* summary = |
4773 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 4823 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
4824 // Because we always call into the runtime (LocationSummary::kCall) we | |
4825 // must specify each input, temp, and output register explicitly. | |
4774 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); | 4826 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); |
4775 // R13 is chosen because it is callee saved so we do not need to back it | 4827 // R13 is chosen because it is callee saved so we do not need to back it |
4776 // up before calling into the runtime. | 4828 // up before calling into the runtime. |
4777 summary->set_temp(0, Location::RegisterLocation(R13)); | 4829 summary->set_temp(0, Location::RegisterLocation(R13)); |
4778 summary->set_out(0, Location::RegisterLocation(RAX)); | 4830 summary->set_out(0, Location::Pair(Location::FpuRegisterLocation(XMM2), |
4831 Location::FpuRegisterLocation(XMM3))); | |
4779 return summary; | 4832 return summary; |
4780 } | 4833 } |
4781 UNIMPLEMENTED(); | 4834 UNIMPLEMENTED(); |
4782 return NULL; | 4835 return NULL; |
4783 } | 4836 } |
4784 | 4837 |
4785 | 4838 |
4786 | 4839 |
4787 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); | 4840 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); |
4788 | 4841 |
4789 extern const RuntimeEntry kSinCosRuntimeEntry( | 4842 extern const RuntimeEntry kSinCosRuntimeEntry( |
4790 "libc_sincos", reinterpret_cast<RuntimeFunction>( | 4843 "libc_sincos", reinterpret_cast<RuntimeFunction>( |
4791 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); | 4844 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); |
4792 | 4845 |
4793 | 4846 |
4794 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4847 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4795 Label* deopt = NULL; | 4848 Label* deopt = NULL; |
4796 if (CanDeoptimize()) { | 4849 if (CanDeoptimize()) { |
4797 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); | 4850 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
4798 } | 4851 } |
4799 if (kind() == MergedMathInstr::kTruncDivMod) { | 4852 if (kind() == MergedMathInstr::kTruncDivMod) { |
4800 Register left = locs()->in(0).reg(); | 4853 Register left = locs()->in(0).reg(); |
4801 Register right = locs()->in(1).reg(); | 4854 Register right = locs()->in(1).reg(); |
4802 Register result = locs()->out(0).reg(); | 4855 ASSERT(locs()->out(0).IsPairLocation()); |
4856 PairLocation* pair = locs()->out(0).AsPairLocation(); | |
4857 Register result1 = pair->At(0).reg(); | |
4858 Register result2 = pair->At(1).reg(); | |
4803 Label not_32bit, done; | 4859 Label not_32bit, done; |
4804 Register temp = locs()->temp(0).reg(); | 4860 Register temp = locs()->temp(0).reg(); |
4805 ASSERT(left == RAX); | 4861 ASSERT(left == RAX); |
4806 ASSERT((right != RDX) && (right != RAX)); | 4862 ASSERT((right != RDX) && (right != RAX)); |
4807 ASSERT(temp == RDX); | 4863 ASSERT(temp == RDX); |
4808 ASSERT((result != RDX) && (result != RAX)); | 4864 ASSERT((result1 != RDX) && (result1 != RAX)); |
4865 ASSERT((result2 != RDX) && (result2 != RAX)); | |
4809 | 4866 |
4810 Range* right_range = InputAt(1)->definition()->range(); | 4867 Range* right_range = InputAt(1)->definition()->range(); |
4811 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 4868 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
4812 // Handle divide by zero in runtime. | 4869 // Handle divide by zero in runtime. |
4813 __ testq(right, right); | 4870 __ testq(right, right); |
4814 __ j(ZERO, deopt); | 4871 __ j(ZERO, deopt); |
4815 } | 4872 } |
4816 // Check if both operands fit into 32bits as idiv with 64bit operands | 4873 // Check if both operands fit into 32bits as idiv with 64bit operands |
4817 // requires twice as many cycles and has much higher latency. | 4874 // requires twice as many cycles and has much higher latency. |
4818 // We are checking this before untagging them to avoid corner case | 4875 // We are checking this before untagging them to avoid corner case |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4868 __ Bind(&subtract); | 4925 __ Bind(&subtract); |
4869 __ subq(RDX, right); | 4926 __ subq(RDX, right); |
4870 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) { | 4927 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) { |
4871 // Right is positive. | 4928 // Right is positive. |
4872 __ addq(RDX, right); | 4929 __ addq(RDX, right); |
4873 } else { | 4930 } else { |
4874 // Right is negative. | 4931 // Right is negative. |
4875 __ subq(RDX, right); | 4932 __ subq(RDX, right); |
4876 } | 4933 } |
4877 __ Bind(&all_done); | 4934 __ Bind(&all_done); |
4878 __ SmiTag(result); | |
4879 | 4935 |
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); | 4936 __ SmiTag(RAX); |
4891 __ SmiTag(RDX); | 4937 __ SmiTag(RDX); |
4892 __ StoreIntoObjectNoBarrier(result, trunc_div_address, RAX); | 4938 |
4893 __ StoreIntoObjectNoBarrier(result, mod_address, RDX); | 4939 __ movq(result1, RAX); |
4940 __ movq(result2, RDX); | |
4894 // FLAG_throw_on_javascript_int_overflow: not needed. | 4941 // FLAG_throw_on_javascript_int_overflow: not needed. |
4895 // Note that the result of an integer division/modulo of two | 4942 // Note that the result of an integer division/modulo of two |
4896 // in-range arguments, cannot create out-of-range result. | 4943 // in-range arguments, cannot create out-of-range result. |
4897 return; | 4944 return; |
4898 } | 4945 } |
4899 if (kind() == MergedMathInstr::kSinCos) { | 4946 if (kind() == MergedMathInstr::kSinCos) { |
4947 ASSERT(locs()->out(0).IsPairLocation()); | |
4948 PairLocation* pair = locs()->out(0).AsPairLocation(); | |
4949 XmmRegister out1 = pair->At(0).fpu_reg(); | |
4950 XmmRegister out2 = pair->At(1).fpu_reg(); | |
4951 | |
4900 // Save RSP. | 4952 // Save RSP. |
4901 __ movq(locs()->temp(0).reg(), RSP); | 4953 __ movq(locs()->temp(0).reg(), RSP); |
4902 // +-------------------------------+ | 4954 // +-------------------------------+ |
4903 // | double-argument | <- TOS | 4955 // | double-argument | <- TOS |
4904 // +-------------------------------+ | 4956 // +-------------------------------+ |
4905 // | address-cos-result | +8 | 4957 // | address-cos-result | +8 |
4906 // +-------------------------------+ | 4958 // +-------------------------------+ |
4907 // | address-sin-result | +16 | 4959 // | address-sin-result | +16 |
4908 // +-------------------------------+ | 4960 // +-------------------------------+ |
4909 // | double-storage-for-cos-result | +24 | 4961 // | double-storage-for-cos-result | +24 |
4910 // +-------------------------------+ | 4962 // +-------------------------------+ |
4911 // | double-storage-for-sin-result | +32 | 4963 // | double-storage-for-sin-result | +32 |
4912 // +-------------------------------+ | 4964 // +-------------------------------+ |
4913 // .... | 4965 // .... |
4914 __ ReserveAlignedFrameSpace(kDoubleSize * 3 + kWordSize * 2); | 4966 __ ReserveAlignedFrameSpace(kDoubleSize * 3 + kWordSize * 2); |
4915 __ movsd(Address(RSP, 0), locs()->in(0).fpu_reg()); | 4967 __ movsd(Address(RSP, 0), locs()->in(0).fpu_reg()); |
4916 | 4968 |
4917 __ leaq(RDI, Address(RSP, 2 * kWordSize + kDoubleSize)); | 4969 __ leaq(RDI, Address(RSP, 2 * kWordSize + kDoubleSize)); |
4918 __ leaq(RSI, Address(RSP, 2 * kWordSize + 2 * kDoubleSize)); | 4970 __ leaq(RSI, Address(RSP, 2 * kWordSize + 2 * kDoubleSize)); |
4919 __ movaps(XMM0, locs()->in(0).fpu_reg()); | 4971 __ movaps(XMM0, locs()->in(0).fpu_reg()); |
4920 | 4972 |
4921 __ CallRuntime(kSinCosRuntimeEntry, InputCount()); | 4973 __ CallRuntime(kSinCosRuntimeEntry, InputCount()); |
4922 __ movsd(XMM0, Address(RSP, 2 * kWordSize + kDoubleSize * 2)); // sin. | 4974 __ movsd(out2, Address(RSP, 2 * kWordSize + kDoubleSize * 2)); // sin. |
4923 __ movsd(XMM1, Address(RSP, 2 * kWordSize + kDoubleSize)); // cos. | 4975 __ movsd(out1, Address(RSP, 2 * kWordSize + kDoubleSize)); // cos. |
4924 // Restore RSP. | 4976 // Restore RSP. |
4925 __ movq(RSP, locs()->temp(0).reg()); | 4977 __ movq(RSP, locs()->temp(0).reg()); |
4926 | 4978 |
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; | 4979 return; |
4944 } | 4980 } |
4945 UNIMPLEMENTED(); | 4981 UNIMPLEMENTED(); |
4946 } | 4982 } |
4947 | 4983 |
4948 | 4984 |
4949 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 4985 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
4950 bool opt) const { | 4986 bool opt) const { |
4951 return MakeCallSummary(); | 4987 return MakeCallSummary(); |
4952 } | 4988 } |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5429 PcDescriptors::kOther, | 5465 PcDescriptors::kOther, |
5430 locs()); | 5466 locs()); |
5431 __ Drop(ArgumentCount()); // Discard arguments. | 5467 __ Drop(ArgumentCount()); // Discard arguments. |
5432 } | 5468 } |
5433 | 5469 |
5434 } // namespace dart | 5470 } // namespace dart |
5435 | 5471 |
5436 #undef __ | 5472 #undef __ |
5437 | 5473 |
5438 #endif // defined TARGET_ARCH_X64 | 5474 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |