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