Chromium Code Reviews| 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 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 4826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4837 | 4837 |
| 4838 __ CallRuntime(TargetFunction(), InputCount()); | 4838 __ CallRuntime(TargetFunction(), InputCount()); |
| 4839 __ fstpl(Address(ESP, 0)); | 4839 __ fstpl(Address(ESP, 0)); |
| 4840 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0)); | 4840 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0)); |
| 4841 __ Bind(&skip_call); | 4841 __ Bind(&skip_call); |
| 4842 // Restore ESP. | 4842 // Restore ESP. |
| 4843 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); | 4843 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); |
| 4844 } | 4844 } |
| 4845 | 4845 |
| 4846 | 4846 |
| 4847 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const { | |
| 4848 // Only use this instruction in optimized code. | |
| 4849 ASSERT(opt); | |
| 4850 const intptr_t kNumInputs = 1; | |
| 4851 LocationSummary* summary = | |
| 4852 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); | |
| 4853 if (representation() == kUnboxedDouble) { | |
| 4854 if (index() == 0) { | |
| 4855 summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(), | |
| 4856 Location::Any())); | |
| 4857 } else { | |
| 4858 ASSERT(index() == 1); | |
| 4859 summary->set_in(0, Location::Pair(Location::Any(), | |
| 4860 Location::RequiresFpuRegister())); | |
| 4861 } | |
| 4862 summary->set_out(0, Location::RequiresFpuRegister()); | |
| 4863 } else { | |
| 4864 ASSERT(representation() == kTagged); | |
| 4865 if (index() == 0) { | |
| 4866 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | |
| 4867 Location::Any())); | |
| 4868 } else { | |
| 4869 ASSERT(index() == 1); | |
| 4870 summary->set_in(0, Location::Pair(Location::Any(), | |
| 4871 Location::RequiresRegister())); | |
| 4872 } | |
| 4873 summary->set_out(0, Location::RequiresRegister()); | |
| 4874 } | |
| 4875 return summary; | |
| 4876 } | |
| 4877 | |
| 4878 | |
| 4879 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 4880 ASSERT(locs()->in(0).IsPairLocation()); | |
| 4881 PairLocation* pair = locs()->in(0).AsPairLocation(); | |
| 4882 Location in_loc = pair->At(index()); | |
| 4883 if (representation() == kUnboxedDouble) { | |
| 4884 XmmRegister out = locs()->out(0).fpu_reg(); | |
| 4885 XmmRegister in = in_loc.fpu_reg(); | |
| 4886 __ movaps(out, in); | |
| 4887 } else { | |
| 4888 ASSERT(representation() == kTagged); | |
| 4889 Register out = locs()->out(0).reg(); | |
| 4890 Register in = in_loc.reg(); | |
| 4891 __ movl(out, in); | |
| 4892 } | |
| 4893 } | |
| 4894 | |
| 4895 | |
| 4847 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { | 4896 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { |
| 4848 if (kind() == MergedMathInstr::kTruncDivMod) { | 4897 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 4849 const intptr_t kNumInputs = 2; | 4898 const intptr_t kNumInputs = 2; |
| 4850 const intptr_t kNumTemps = 1; | 4899 const intptr_t kNumTemps = 1; |
| 4851 LocationSummary* summary = | 4900 LocationSummary* summary = |
| 4852 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4901 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4853 // Both inputs must be writable because they will be untagged. | 4902 // Both inputs must be writable because they will be untagged. |
| 4854 summary->set_in(0, Location::RegisterLocation(EAX)); | 4903 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 4855 summary->set_in(1, Location::WritableRegister()); | 4904 summary->set_in(1, Location::WritableRegister()); |
| 4856 summary->set_out(0, Location::RequiresRegister()); | 4905 // Output is a pair of registers. |
| 4906 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | |
|
Florian Schneider
2014/04/08 09:48:45
How about making the output a pair EDX:EAX instead
Cutch
2014/04/08 15:56:16
Done.
| |
| 4907 Location::RequiresRegister())); | |
| 4857 // Will be used for sign extension and division. | 4908 // Will be used for sign extension and division. |
| 4858 summary->set_temp(0, Location::RegisterLocation(EDX)); | 4909 summary->set_temp(0, Location::RegisterLocation(EDX)); |
| 4859 return summary; | 4910 return summary; |
| 4860 } | 4911 } |
| 4861 if (kind() == MergedMathInstr::kSinCos) { | 4912 if (kind() == MergedMathInstr::kSinCos) { |
| 4862 const intptr_t kNumInputs = 1; | 4913 const intptr_t kNumInputs = 1; |
| 4863 const intptr_t kNumTemps = 0; | 4914 const intptr_t kNumTemps = 0; |
| 4864 LocationSummary* summary = | 4915 LocationSummary* summary = |
| 4865 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 4916 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4866 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); | 4917 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4867 summary->set_out(0, Location::RegisterLocation(EAX)); | 4918 summary->set_out(0, Location::Pair(Location::RequiresFpuRegister(), |
| 4919 Location::RequiresFpuRegister())); | |
| 4868 return summary; | 4920 return summary; |
| 4869 } | 4921 } |
| 4870 UNIMPLEMENTED(); | 4922 UNIMPLEMENTED(); |
| 4871 return NULL; | 4923 return NULL; |
| 4872 } | 4924 } |
| 4873 | 4925 |
| 4874 | 4926 |
| 4875 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); | 4927 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); |
| 4876 | 4928 |
| 4877 extern const RuntimeEntry kSinCosRuntimeEntry( | 4929 extern const RuntimeEntry kSinCosRuntimeEntry( |
| 4878 "libc_sincos", reinterpret_cast<RuntimeFunction>( | 4930 "libc_sincos", reinterpret_cast<RuntimeFunction>( |
| 4879 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); | 4931 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); |
| 4880 | 4932 |
| 4881 | 4933 |
| 4882 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4934 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4883 Label* deopt = NULL; | 4935 Label* deopt = NULL; |
| 4884 if (CanDeoptimize()) { | 4936 if (CanDeoptimize()) { |
| 4885 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); | 4937 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
| 4886 } | 4938 } |
| 4887 | 4939 |
| 4888 if (kind() == MergedMathInstr::kTruncDivMod) { | 4940 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 4889 Register left = locs()->in(0).reg(); | 4941 Register left = locs()->in(0).reg(); |
| 4890 Register right = locs()->in(1).reg(); | 4942 Register right = locs()->in(1).reg(); |
| 4891 Register result = locs()->out(0).reg(); | 4943 ASSERT(locs()->out(0).IsPairLocation()); |
| 4944 PairLocation* pair = locs()->out(0).AsPairLocation(); | |
| 4945 Register result1 = pair->At(0).reg(); | |
| 4946 Register result2 = pair->At(1).reg(); | |
| 4892 Range* right_range = InputAt(1)->definition()->range(); | 4947 Range* right_range = InputAt(1)->definition()->range(); |
| 4893 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 4948 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 4894 // Handle divide by zero in runtime. | 4949 // Handle divide by zero in runtime. |
| 4895 __ testl(right, right); | 4950 __ testl(right, right); |
| 4896 __ j(ZERO, deopt); | 4951 __ j(ZERO, deopt); |
| 4897 } | 4952 } |
| 4898 ASSERT(left == EAX); | 4953 ASSERT(left == EAX); |
| 4899 ASSERT((right != EDX) && (right != EAX)); | 4954 ASSERT((right != EDX) && (right != EAX)); |
| 4900 ASSERT(locs()->temp(0).reg() == EDX); | 4955 ASSERT(locs()->temp(0).reg() == EDX); |
| 4901 ASSERT((result != EDX) && (result != EAX)); | 4956 ASSERT((result1 != EDX) && (result1 != EAX)); |
| 4957 ASSERT((result2 != EDX) && (result2 != EAX)); | |
| 4902 __ SmiUntag(left); | 4958 __ SmiUntag(left); |
| 4903 __ SmiUntag(right); | 4959 __ SmiUntag(right); |
| 4904 __ cdq(); // Sign extend EAX -> EDX:EAX. | 4960 __ cdq(); // Sign extend EAX -> EDX:EAX. |
| 4905 __ idivl(right); // EAX: quotient, EDX: remainder. | 4961 __ idivl(right); // EAX: quotient, EDX: remainder. |
| 4906 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 4962 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 4907 // case we cannot tag the result. | 4963 // case we cannot tag the result. |
| 4908 // TODO(srdjan): We could store instead untagged intermediate results in a | 4964 // TODO(srdjan): We could store instead untagged intermediate results in a |
| 4909 // typed array, but then the load indexed instructions would need to be | 4965 // typed array, but then the load indexed instructions would need to be |
| 4910 // able to deoptimize. | 4966 // able to deoptimize. |
| 4911 __ cmpl(EAX, Immediate(0x40000000)); | 4967 __ cmpl(EAX, Immediate(0x40000000)); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 4933 __ subl(EDX, right); | 4989 __ subl(EDX, right); |
| 4934 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) { | 4990 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) { |
| 4935 // Right is positive. | 4991 // Right is positive. |
| 4936 __ addl(EDX, right); | 4992 __ addl(EDX, right); |
| 4937 } else { | 4993 } else { |
| 4938 // Right is negative. | 4994 // Right is negative. |
| 4939 __ subl(EDX, right); | 4995 __ subl(EDX, right); |
| 4940 } | 4996 } |
| 4941 __ Bind(&done); | 4997 __ Bind(&done); |
| 4942 | 4998 |
| 4943 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld))); | |
| 4944 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid); | |
| 4945 Address trunc_div_address( | |
| 4946 FlowGraphCompiler::ElementAddressForIntIndex( | |
| 4947 kArrayCid, index_scale, result, | |
| 4948 MergedMathInstr::ResultIndexOf(Token::kTRUNCDIV))); | |
| 4949 Address mod_address( | |
| 4950 FlowGraphCompiler::ElementAddressForIntIndex( | |
| 4951 kArrayCid, index_scale, result, | |
| 4952 MergedMathInstr::ResultIndexOf(Token::kMOD))); | |
| 4953 __ SmiTag(EAX); | 4999 __ SmiTag(EAX); |
| 4954 __ SmiTag(EDX); | 5000 __ SmiTag(EDX); |
| 4955 __ StoreIntoObjectNoBarrier(result, trunc_div_address, EAX); | 5001 __ movl(result1, EAX); |
| 4956 __ StoreIntoObjectNoBarrier(result, mod_address, EDX); | 5002 __ movl(result2, EDX); |
| 4957 return; | 5003 return; |
| 4958 } | 5004 } |
| 4959 | 5005 |
| 4960 if (kind() == MergedMathInstr::kSinCos) { | 5006 if (kind() == MergedMathInstr::kSinCos) { |
| 5007 XmmRegister in = locs()->in(0).fpu_reg(); | |
| 5008 ASSERT(locs()->out(0).IsPairLocation()); | |
| 5009 PairLocation* pair = locs()->out(0).AsPairLocation(); | |
| 5010 XmmRegister out1 = pair->At(0).fpu_reg(); | |
| 5011 XmmRegister out2 = pair->At(1).fpu_reg(); | |
| 5012 | |
| 4961 // Do x87 sincos, since the ia32 compilers may not fuse sin/cos into | 5013 // Do x87 sincos, since the ia32 compilers may not fuse sin/cos into |
| 4962 // sincos. | 5014 // sincos. |
| 4963 __ pushl(EAX); | 5015 __ pushl(EAX); |
| 4964 __ pushl(EAX); | 5016 __ pushl(EAX); |
| 4965 __ movsd(Address(ESP, 0), locs()->in(0).fpu_reg()); | 5017 __ movsd(Address(ESP, 0), in); |
| 4966 __ fldl(Address(ESP, 0)); | 5018 __ fldl(Address(ESP, 0)); |
| 4967 __ fsincos(); | 5019 __ fsincos(); |
| 4968 __ fstpl(Address(ESP, 0)); | 5020 __ fstpl(Address(ESP, 0)); |
| 4969 __ movsd(XMM1, Address(ESP, 0)); | 5021 __ movsd(out1, Address(ESP, 0)); |
| 4970 __ fstpl(Address(ESP, 0)); | 5022 __ fstpl(Address(ESP, 0)); |
| 4971 __ movsd(XMM0, Address(ESP, 0)); | 5023 __ movsd(out2, Address(ESP, 0)); |
| 4972 __ addl(ESP, Immediate(2 * kWordSize)); | 5024 __ addl(ESP, Immediate(2 * kWordSize)); |
| 4973 | |
| 4974 Register result = locs()->out(0).reg(); | |
| 4975 const TypedData& res_array = TypedData::ZoneHandle( | |
| 4976 TypedData::New(kTypedDataFloat64ArrayCid, 2, Heap::kOld)); | |
| 4977 __ LoadObject(result, res_array); | |
| 4978 const intptr_t index_scale = | |
| 4979 FlowGraphCompiler::ElementSizeFor(kTypedDataFloat64ArrayCid); | |
| 4980 Address sin_address( | |
| 4981 FlowGraphCompiler::ElementAddressForIntIndex( | |
| 4982 kTypedDataFloat64ArrayCid, index_scale, result, | |
| 4983 MergedMathInstr::ResultIndexOf(MethodRecognizer::kMathSin))); | |
| 4984 Address cos_address( | |
| 4985 FlowGraphCompiler::ElementAddressForIntIndex( | |
| 4986 kTypedDataFloat64ArrayCid, index_scale, result, | |
| 4987 MergedMathInstr::ResultIndexOf(MethodRecognizer::kMathCos))); | |
| 4988 __ movsd(sin_address, XMM0); | |
| 4989 __ movsd(cos_address, XMM1); | |
| 4990 return; | 5025 return; |
| 4991 } | 5026 } |
| 4992 | 5027 |
| 4993 UNIMPLEMENTED(); | 5028 UNIMPLEMENTED(); |
| 4994 } | 5029 } |
| 4995 | 5030 |
| 4996 | 5031 |
| 4997 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 5032 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
| 4998 bool opt) const { | 5033 bool opt) const { |
| 4999 return MakeCallSummary(); | 5034 return MakeCallSummary(); |
| (...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5839 PcDescriptors::kOther, | 5874 PcDescriptors::kOther, |
| 5840 locs()); | 5875 locs()); |
| 5841 __ Drop(ArgumentCount()); // Discard arguments. | 5876 __ Drop(ArgumentCount()); // Discard arguments. |
| 5842 } | 5877 } |
| 5843 | 5878 |
| 5844 } // namespace dart | 5879 } // namespace dart |
| 5845 | 5880 |
| 5846 #undef __ | 5881 #undef __ |
| 5847 | 5882 |
| 5848 #endif // defined TARGET_ARCH_IA32 | 5883 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |