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_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 3962 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3973 | 3973 |
| 3974 | 3974 |
| 3975 LocationSummary* MathUnaryInstr::MakeLocationSummary(bool opt) const { | 3975 LocationSummary* MathUnaryInstr::MakeLocationSummary(bool opt) const { |
| 3976 if ((kind() == MethodRecognizer::kMathSin) || | 3976 if ((kind() == MethodRecognizer::kMathSin) || |
| 3977 (kind() == MethodRecognizer::kMathCos)) { | 3977 (kind() == MethodRecognizer::kMathCos)) { |
| 3978 // Calling convention on x64 uses XMM0 and XMM1 to pass the first two | 3978 // Calling convention on x64 uses XMM0 and XMM1 to pass the first two |
| 3979 // double arguments and XMM0 to return the result. Unfortunately | 3979 // double arguments and XMM0 to return the result. Unfortunately |
| 3980 // currently we can't specify these registers because ParallelMoveResolver | 3980 // currently we can't specify these registers because ParallelMoveResolver |
| 3981 // assumes that XMM0 is free at all times. | 3981 // assumes that XMM0 is free at all times. |
| 3982 // TODO(vegorov): allow XMM0 to be used. | 3982 // TODO(vegorov): allow XMM0 to be used. |
| 3983 const intptr_t kNumTemps = 0; | 3983 const intptr_t kNumTemps = 1; |
| 3984 LocationSummary* summary = | 3984 LocationSummary* summary = |
| 3985 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); | 3985 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); |
| 3986 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); | 3986 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); |
| 3987 summary->set_temp(0, Location::RegisterLocation(CALLEE_SAVED)); | |
|
regis
2014/02/26 23:53:12
ditto
Cutch
2014/02/27 15:52:37
Done.
| |
| 3987 summary->set_out(Location::FpuRegisterLocation(XMM1)); | 3988 summary->set_out(Location::FpuRegisterLocation(XMM1)); |
| 3988 return summary; | 3989 return summary; |
| 3989 } | 3990 } |
| 3991 ASSERT(kind() == MethodRecognizer::kMathSqrt); | |
| 3990 const intptr_t kNumInputs = 1; | 3992 const intptr_t kNumInputs = 1; |
| 3991 const intptr_t kNumTemps = 0; | 3993 const intptr_t kNumTemps = 0; |
| 3992 LocationSummary* summary = | 3994 LocationSummary* summary = |
| 3993 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3995 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3994 summary->set_in(0, Location::RequiresFpuRegister()); | 3996 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3995 summary->set_out(Location::RequiresFpuRegister()); | 3997 summary->set_out(Location::RequiresFpuRegister()); |
| 3996 return summary; | 3998 return summary; |
| 3997 } | 3999 } |
| 3998 | 4000 |
| 3999 | 4001 |
| 4000 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4002 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4001 if (kind() == MethodRecognizer::kMathSqrt) { | 4003 if (kind() == MethodRecognizer::kMathSqrt) { |
| 4002 __ sqrtsd(locs()->out().fpu_reg(), locs()->in(0).fpu_reg()); | 4004 __ sqrtsd(locs()->out().fpu_reg(), locs()->in(0).fpu_reg()); |
| 4003 } else { | 4005 } else { |
| 4004 __ EnterFrame(0); | 4006 ASSERT((kind() == MethodRecognizer::kMathSin) || |
| 4007 (kind() == MethodRecognizer::kMathCos)); | |
| 4008 // Save RSP. | |
| 4009 __ movq(locs()->temp(0).reg(), RSP); | |
| 4005 __ ReserveAlignedFrameSpace(0); | 4010 __ ReserveAlignedFrameSpace(0); |
| 4006 __ movaps(XMM0, locs()->in(0).fpu_reg()); | 4011 __ movaps(XMM0, locs()->in(0).fpu_reg()); |
| 4007 __ CallRuntime(TargetFunction(), InputCount()); | 4012 __ CallRuntime(TargetFunction(), InputCount()); |
| 4008 __ movaps(locs()->out().fpu_reg(), XMM0); | 4013 __ movaps(locs()->out().fpu_reg(), XMM0); |
| 4009 __ leave(); | 4014 // Restore RSP. |
| 4015 __ movq(RSP, locs()->temp(0).reg()); | |
| 4010 } | 4016 } |
| 4011 } | 4017 } |
| 4012 | 4018 |
| 4013 | 4019 |
| 4014 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const { | 4020 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const { |
| 4015 const intptr_t kNumInputs = 1; | 4021 const intptr_t kNumInputs = 1; |
| 4016 return LocationSummary::Make(kNumInputs, | 4022 return LocationSummary::Make(kNumInputs, |
| 4017 Location::SameAsFirstInput(), | 4023 Location::SameAsFirstInput(), |
| 4018 LocationSummary::kNoCall); | 4024 LocationSummary::kNoCall); |
| 4019 } | 4025 } |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4315 } | 4321 } |
| 4316 | 4322 |
| 4317 | 4323 |
| 4318 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const { | 4324 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const { |
| 4319 // Calling convention on x64 uses XMM0 and XMM1 to pass the first two | 4325 // Calling convention on x64 uses XMM0 and XMM1 to pass the first two |
| 4320 // double arguments and XMM0 to return the result. Unfortunately | 4326 // double arguments and XMM0 to return the result. Unfortunately |
| 4321 // currently we can't specify these registers because ParallelMoveResolver | 4327 // currently we can't specify these registers because ParallelMoveResolver |
| 4322 // assumes that XMM0 is free at all times. | 4328 // assumes that XMM0 is free at all times. |
| 4323 // TODO(vegorov): allow XMM0 to be used. | 4329 // TODO(vegorov): allow XMM0 to be used. |
| 4324 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 4330 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
| 4325 const intptr_t kNumTemps = 0; | 4331 const intptr_t kNumTemps = 1; |
| 4326 LocationSummary* result = | 4332 LocationSummary* result = |
| 4327 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); | 4333 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); |
| 4334 result->set_temp(0, Location::RegisterLocation(CALLEE_SAVED)); | |
| 4328 result->set_in(0, Location::FpuRegisterLocation(XMM2)); | 4335 result->set_in(0, Location::FpuRegisterLocation(XMM2)); |
| 4329 if (InputCount() == 2) { | 4336 if (InputCount() == 2) { |
| 4330 result->set_in(1, Location::FpuRegisterLocation(XMM1)); | 4337 result->set_in(1, Location::FpuRegisterLocation(XMM1)); |
| 4331 } | 4338 } |
| 4332 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 4339 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 4333 result->AddTemp(Location::RegisterLocation(RAX)); | 4340 result->AddTemp(Location::RegisterLocation(RAX)); |
| 4334 result->AddTemp(Location::FpuRegisterLocation(XMM4)); | 4341 result->AddTemp(Location::FpuRegisterLocation(XMM4)); |
| 4335 } | 4342 } |
| 4336 result->set_out(Location::FpuRegisterLocation(XMM3)); | 4343 result->set_out(Location::FpuRegisterLocation(XMM3)); |
| 4337 return result; | 4344 return result; |
| 4338 } | 4345 } |
| 4339 | 4346 |
| 4340 | 4347 |
| 4341 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4348 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4342 __ EnterFrame(0); | 4349 // Save RSP. |
| 4350 __ movq(locs()->temp(0).reg(), RSP); | |
| 4343 __ ReserveAlignedFrameSpace(0); | 4351 __ ReserveAlignedFrameSpace(0); |
| 4344 __ movaps(XMM0, locs()->in(0).fpu_reg()); | 4352 __ movaps(XMM0, locs()->in(0).fpu_reg()); |
| 4345 if (InputCount() == 2) { | 4353 if (InputCount() == 2) { |
| 4346 ASSERT(locs()->in(1).fpu_reg() == XMM1); | 4354 ASSERT(locs()->in(1).fpu_reg() == XMM1); |
| 4347 } | 4355 } |
| 4348 // For pow-function return NaN if exponent is NaN. | 4356 // For pow-function return NaN if exponent is NaN. |
| 4349 Label do_call, skip_call; | 4357 Label do_call, skip_call; |
| 4350 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 4358 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 4351 // Pseudo code: | 4359 // Pseudo code: |
| 4352 // if (exponent == 0.0) return 0.0; | 4360 // if (exponent == 0.0) return 0.0; |
| 4353 // if (base == 1.0) return 1.0; | 4361 // if (base == 1.0) return 1.0; |
| 4354 // if (base.isNaN || exponent.isNaN) { | 4362 // if (base.isNaN || exponent.isNaN) { |
| 4355 // return double.NAN; | 4363 // return double.NAN; |
| 4356 // } | 4364 // } |
| 4357 XmmRegister base = locs()->in(0).fpu_reg(); | 4365 XmmRegister base = locs()->in(0).fpu_reg(); |
| 4358 XmmRegister exp = locs()->in(1).fpu_reg(); | 4366 XmmRegister exp = locs()->in(1).fpu_reg(); |
| 4359 XmmRegister result = locs()->out().fpu_reg(); | 4367 XmmRegister result = locs()->out().fpu_reg(); |
| 4360 Register temp = locs()->temp(0).reg(); | 4368 Register temp = locs()->temp(0).reg(); |
|
siva
2014/02/27 00:00:26
Ditto comment about the temp index.
I am wondering
Cutch
2014/02/27 15:52:37
Added index constants to instruction.
| |
| 4361 XmmRegister zero_temp = locs()->temp(1).fpu_reg(); | 4369 XmmRegister zero_temp = locs()->temp(1).fpu_reg(); |
| 4362 | 4370 |
| 4363 // Check if exponent is 0.0 -> return 1.0; | 4371 // Check if exponent is 0.0 -> return 1.0; |
| 4364 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0)), PP); | 4372 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0)), PP); |
| 4365 __ movsd(zero_temp, FieldAddress(temp, Double::value_offset())); | 4373 __ movsd(zero_temp, FieldAddress(temp, Double::value_offset())); |
| 4366 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1)), PP); | 4374 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1)), PP); |
| 4367 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 4375 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 4368 // 'result' contains 1.0. | 4376 // 'result' contains 1.0. |
| 4369 Label exp_is_nan; | 4377 Label exp_is_nan; |
| 4370 __ comisd(exp, zero_temp); | 4378 __ comisd(exp, zero_temp); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 4388 __ comisd(base, result); | 4396 __ comisd(base, result); |
| 4389 __ j(PARITY_EVEN, &base_is_nan, Assembler::kNearJump); | 4397 __ j(PARITY_EVEN, &base_is_nan, Assembler::kNearJump); |
| 4390 __ j(EQUAL, &skip_call, Assembler::kNearJump); // base and result are 1.0 | 4398 __ j(EQUAL, &skip_call, Assembler::kNearJump); // base and result are 1.0 |
| 4391 __ movsd(result, exp); // result is NaN | 4399 __ movsd(result, exp); // result is NaN |
| 4392 __ jmp(&skip_call, Assembler::kNearJump); | 4400 __ jmp(&skip_call, Assembler::kNearJump); |
| 4393 } | 4401 } |
| 4394 __ Bind(&do_call); | 4402 __ Bind(&do_call); |
| 4395 __ CallRuntime(TargetFunction(), InputCount()); | 4403 __ CallRuntime(TargetFunction(), InputCount()); |
| 4396 __ movaps(locs()->out().fpu_reg(), XMM0); | 4404 __ movaps(locs()->out().fpu_reg(), XMM0); |
| 4397 __ Bind(&skip_call); | 4405 __ Bind(&skip_call); |
| 4398 __ leave(); | 4406 // Restore RSP. |
| 4407 __ movq(RSP, locs()->temp(0).reg()); | |
| 4399 } | 4408 } |
| 4400 | 4409 |
| 4401 | 4410 |
| 4402 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { | 4411 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { |
| 4403 if (kind() == MergedMathInstr::kTruncDivMod) { | 4412 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 4404 const intptr_t kNumInputs = 2; | 4413 const intptr_t kNumInputs = 2; |
| 4405 const intptr_t kNumTemps = 1; | 4414 const intptr_t kNumTemps = 1; |
| 4406 LocationSummary* summary = | 4415 LocationSummary* summary = |
| 4407 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4416 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4408 // Both inputs must be writable because they will be untagged. | 4417 // Both inputs must be writable because they will be untagged. |
| 4409 summary->set_in(0, Location::RegisterLocation(RAX)); | 4418 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 4410 summary->set_in(1, Location::WritableRegister()); | 4419 summary->set_in(1, Location::WritableRegister()); |
| 4411 summary->set_out(Location::RequiresRegister()); | 4420 summary->set_out(Location::RequiresRegister()); |
| 4412 // Will be used for sign extension and division. | 4421 // Will be used for sign extension and division. |
| 4413 summary->set_temp(0, Location::RegisterLocation(RDX)); | 4422 summary->set_temp(0, Location::RegisterLocation(RDX)); |
| 4414 return summary; | 4423 return summary; |
| 4415 } | 4424 } |
| 4416 if (kind() == MergedMathInstr::kSinCos) { | 4425 if (kind() == MergedMathInstr::kSinCos) { |
| 4417 const intptr_t kNumInputs = 1; | 4426 const intptr_t kNumInputs = 1; |
| 4418 const intptr_t kNumTemps = 0; | 4427 const intptr_t kNumTemps = 1; |
| 4419 LocationSummary* summary = | 4428 LocationSummary* summary = |
| 4420 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 4429 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 4421 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); | 4430 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); |
| 4431 summary->set_temp(0, Location::RegisterLocation(CALLEE_SAVED)); | |
| 4422 summary->set_out(Location::RegisterLocation(RAX)); | 4432 summary->set_out(Location::RegisterLocation(RAX)); |
| 4423 return summary; | 4433 return summary; |
| 4424 } | 4434 } |
| 4425 UNIMPLEMENTED(); | 4435 UNIMPLEMENTED(); |
| 4426 return NULL; | 4436 return NULL; |
| 4427 } | 4437 } |
| 4428 | 4438 |
| 4429 | 4439 |
| 4430 | 4440 |
| 4431 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); | 4441 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4534 __ SmiTag(RAX); | 4544 __ SmiTag(RAX); |
| 4535 __ SmiTag(RDX); | 4545 __ SmiTag(RDX); |
| 4536 __ StoreIntoObjectNoBarrier(result, trunc_div_address, RAX); | 4546 __ StoreIntoObjectNoBarrier(result, trunc_div_address, RAX); |
| 4537 __ StoreIntoObjectNoBarrier(result, mod_address, RDX); | 4547 __ StoreIntoObjectNoBarrier(result, mod_address, RDX); |
| 4538 // FLAG_throw_on_javascript_int_overflow: not needed. | 4548 // FLAG_throw_on_javascript_int_overflow: not needed. |
| 4539 // Note that the result of an integer division/modulo of two | 4549 // Note that the result of an integer division/modulo of two |
| 4540 // in-range arguments, cannot create out-of-range result. | 4550 // in-range arguments, cannot create out-of-range result. |
| 4541 return; | 4551 return; |
| 4542 } | 4552 } |
| 4543 if (kind() == MergedMathInstr::kSinCos) { | 4553 if (kind() == MergedMathInstr::kSinCos) { |
| 4544 __ EnterFrame(0); | 4554 // Save RSP. |
| 4555 __ movq(locs()->temp(0).reg(), RSP); | |
| 4545 // +-------------------------------+ | 4556 // +-------------------------------+ |
| 4546 // | double-argument | <- TOS | 4557 // | double-argument | <- TOS |
| 4547 // +-------------------------------+ | 4558 // +-------------------------------+ |
| 4548 // | address-cos-result | +8 | 4559 // | address-cos-result | +8 |
| 4549 // +-------------------------------+ | 4560 // +-------------------------------+ |
| 4550 // | address-sin-result | +16 | 4561 // | address-sin-result | +16 |
| 4551 // +-------------------------------+ | 4562 // +-------------------------------+ |
| 4552 // | double-storage-for-cos-result | +24 | 4563 // | double-storage-for-cos-result | +24 |
| 4553 // +-------------------------------+ | 4564 // +-------------------------------+ |
| 4554 // | double-storage-for-sin-result | +32 | 4565 // | double-storage-for-sin-result | +32 |
| 4555 // +-------------------------------+ | 4566 // +-------------------------------+ |
| 4556 // .... | 4567 // .... |
| 4557 __ ReserveAlignedFrameSpace(kDoubleSize * 3 + kWordSize * 2); | 4568 __ ReserveAlignedFrameSpace(kDoubleSize * 3 + kWordSize * 2); |
| 4558 __ movsd(Address(RSP, 0), locs()->in(0).fpu_reg()); | 4569 __ movsd(Address(RSP, 0), locs()->in(0).fpu_reg()); |
| 4559 | 4570 |
| 4560 __ leaq(RDI, Address(RSP, 2 * kWordSize + kDoubleSize)); | 4571 __ leaq(RDI, Address(RSP, 2 * kWordSize + kDoubleSize)); |
| 4561 __ leaq(RSI, Address(RSP, 2 * kWordSize + 2 * kDoubleSize)); | 4572 __ leaq(RSI, Address(RSP, 2 * kWordSize + 2 * kDoubleSize)); |
| 4562 __ movaps(XMM0, locs()->in(0).fpu_reg()); | 4573 __ movaps(XMM0, locs()->in(0).fpu_reg()); |
| 4563 | 4574 |
| 4564 __ CallRuntime(kSinCosRuntimeEntry, InputCount()); | 4575 __ CallRuntime(kSinCosRuntimeEntry, InputCount()); |
| 4565 __ movsd(XMM0, Address(RSP, 2 * kWordSize + kDoubleSize * 2)); // sin. | 4576 __ movsd(XMM0, Address(RSP, 2 * kWordSize + kDoubleSize * 2)); // sin. |
| 4566 __ movsd(XMM1, Address(RSP, 2 * kWordSize + kDoubleSize)); // cos. | 4577 __ movsd(XMM1, Address(RSP, 2 * kWordSize + kDoubleSize)); // cos. |
| 4567 __ leave(); | 4578 // Restore RSP. |
| 4579 __ movq(RSP, locs()->temp(0).reg()); | |
| 4568 | 4580 |
| 4569 Register result = locs()->out().reg(); | 4581 Register result = locs()->out().reg(); |
| 4570 const TypedData& res_array = TypedData::ZoneHandle( | 4582 const TypedData& res_array = TypedData::ZoneHandle( |
| 4571 TypedData::New(kTypedDataFloat64ArrayCid, 2, Heap::kOld)); | 4583 TypedData::New(kTypedDataFloat64ArrayCid, 2, Heap::kOld)); |
| 4572 __ LoadObject(result, res_array, PP); | 4584 __ LoadObject(result, res_array, PP); |
| 4573 const intptr_t index_scale = | 4585 const intptr_t index_scale = |
| 4574 FlowGraphCompiler::ElementSizeFor(kTypedDataFloat64ArrayCid); | 4586 FlowGraphCompiler::ElementSizeFor(kTypedDataFloat64ArrayCid); |
| 4575 Address sin_address( | 4587 Address sin_address( |
| 4576 FlowGraphCompiler::ElementAddressForIntIndex( | 4588 FlowGraphCompiler::ElementAddressForIntIndex( |
| 4577 kTypedDataFloat64ArrayCid, index_scale, result, | 4589 kTypedDataFloat64ArrayCid, index_scale, result, |
| (...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5090 PcDescriptors::kOther, | 5102 PcDescriptors::kOther, |
| 5091 locs()); | 5103 locs()); |
| 5092 __ Drop(2); // Discard type arguments and receiver. | 5104 __ Drop(2); // Discard type arguments and receiver. |
| 5093 } | 5105 } |
| 5094 | 5106 |
| 5095 } // namespace dart | 5107 } // namespace dart |
| 5096 | 5108 |
| 5097 #undef __ | 5109 #undef __ |
| 5098 | 5110 |
| 5099 #endif // defined TARGET_ARCH_X64 | 5111 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |