| 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 4650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4661 | 4661 |
| 4662 | 4662 |
| 4663 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4663 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4664 // Save RSP. | 4664 // Save RSP. |
| 4665 __ movq(locs()->temp(kSavedSpTempIndex).reg(), RSP); | 4665 __ movq(locs()->temp(kSavedSpTempIndex).reg(), RSP); |
| 4666 __ ReserveAlignedFrameSpace(0); | 4666 __ ReserveAlignedFrameSpace(0); |
| 4667 __ movaps(XMM0, locs()->in(0).fpu_reg()); | 4667 __ movaps(XMM0, locs()->in(0).fpu_reg()); |
| 4668 if (InputCount() == 2) { | 4668 if (InputCount() == 2) { |
| 4669 ASSERT(locs()->in(1).fpu_reg() == XMM1); | 4669 ASSERT(locs()->in(1).fpu_reg() == XMM1); |
| 4670 } | 4670 } |
| 4671 // For pow-function return NaN if exponent is NaN. | 4671 |
| 4672 Label do_call, skip_call; | 4672 Label skip_call; |
| 4673 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 4673 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 4674 // Pseudo code: | 4674 // Pseudo code: |
| 4675 // if (exponent == 0.0) return 0.0; | 4675 // if (exponent == 0.0) return 1.0; |
| 4676 // if (base == 1.0) return 1.0; | 4676 // if (base == 1.0) return 1.0; |
| 4677 // if (base.isNaN || exponent.isNaN) { | 4677 // if (base.isNaN || exponent.isNaN) { |
| 4678 // return double.NAN; | 4678 // return double.NAN; |
| 4679 // } | 4679 // } |
| 4680 // if (base != -Infinity && exponent == 0.5) { |
| 4681 // if (base == 0.0) return 0.0; |
| 4682 // return sqrt(value); |
| 4683 // } |
| 4680 XmmRegister base = locs()->in(0).fpu_reg(); | 4684 XmmRegister base = locs()->in(0).fpu_reg(); |
| 4681 XmmRegister exp = locs()->in(1).fpu_reg(); | 4685 XmmRegister exp = locs()->in(1).fpu_reg(); |
| 4682 XmmRegister result = locs()->out(0).fpu_reg(); | 4686 XmmRegister result = locs()->out(0).fpu_reg(); |
| 4683 Register temp = locs()->temp(kObjectTempIndex).reg(); | 4687 Register temp = locs()->temp(kObjectTempIndex).reg(); |
| 4684 XmmRegister zero_temp = locs()->temp(kDoubleTempIndex).fpu_reg(); | 4688 XmmRegister zero_temp = locs()->temp(kDoubleTempIndex).fpu_reg(); |
| 4685 | 4689 |
| 4686 // Check if exponent is 0.0 -> return 1.0; | 4690 Label do_call, check_base, return_nan; |
| 4687 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0)), PP); | 4691 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0)), PP); |
| 4688 __ movsd(zero_temp, FieldAddress(temp, Double::value_offset())); | 4692 __ movsd(zero_temp, FieldAddress(temp, Double::value_offset())); |
| 4689 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1)), PP); | 4693 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1)), PP); |
| 4690 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 4694 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 4691 // 'result' contains 1.0. | 4695 |
| 4692 Label exp_is_nan; | 4696 // exponent == 0.0 -> return 1.0; |
| 4693 __ comisd(exp, zero_temp); | 4697 __ comisd(exp, zero_temp); |
| 4694 __ j(PARITY_EVEN, &exp_is_nan, Assembler::kNearJump); // NaN. | 4698 __ j(PARITY_EVEN, &check_base, Assembler::kNearJump); |
| 4695 __ j(EQUAL, &skip_call, Assembler::kNearJump); // exp is 0, result is 1.0. | 4699 __ j(EQUAL, &skip_call, Assembler::kNearJump); // 'result' is 1.0. |
| 4696 | 4700 |
| 4697 Label base_is_nan; | 4701 __ Bind(&check_base); |
| 4698 // Checks if base == 1.0. | 4702 // Note: 'exp' could be NaN. |
| 4703 |
| 4704 // base == 1.0 -> return 1.0; |
| 4699 __ comisd(base, result); | 4705 __ comisd(base, result); |
| 4700 __ j(PARITY_EVEN, &base_is_nan, Assembler::kNearJump); | 4706 __ j(PARITY_EVEN, &return_nan, Assembler::kNearJump); |
| 4701 __ j(EQUAL, &skip_call, Assembler::kNearJump); // base and result are 1.0 | 4707 __ j(EQUAL, &skip_call, Assembler::kNearJump); |
| 4702 __ jmp(&do_call, Assembler::kNearJump); | 4708 // Note: 'base' could be NaN. |
| 4709 __ comisd(exp, base); |
| 4710 // Neither 'exp' nor 'base' is NaN. |
| 4711 __ j(PARITY_ODD, &do_call, Assembler::kNearJump); |
| 4712 // Return NaN. |
| 4713 __ Bind(&return_nan); |
| 4714 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN)), PP); |
| 4715 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 4716 __ jmp(&skip_call); |
| 4703 | 4717 |
| 4704 __ Bind(&base_is_nan); | 4718 Label do_pow, return_zero; |
| 4705 // Returns NaN. | 4719 __ Bind(&do_call); |
| 4706 __ movsd(result, base); | 4720 // Before calling check if we could use sqrt instead of pow. |
| 4721 __ LoadObject(temp, |
| 4722 Double::ZoneHandle(Double::NewCanonical(-INFINITY)), PP); |
| 4723 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 4724 // base == -Infinity -> call pow; |
| 4725 __ comisd(base, result); |
| 4726 __ j(EQUAL, &do_pow, Assembler::kNearJump); |
| 4727 |
| 4728 // exponent == 0.5 ? |
| 4729 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5)), PP); |
| 4730 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 4731 __ comisd(exp, result); |
| 4732 __ j(NOT_EQUAL, &do_pow, Assembler::kNearJump); |
| 4733 |
| 4734 // base == 0 -> return 0; |
| 4735 __ comisd(base, zero_temp); |
| 4736 __ j(EQUAL, &return_zero, Assembler::kNearJump); |
| 4737 |
| 4738 __ sqrtsd(result, base); |
| 4707 __ jmp(&skip_call, Assembler::kNearJump); | 4739 __ jmp(&skip_call, Assembler::kNearJump); |
| 4708 | 4740 |
| 4709 __ Bind(&exp_is_nan); | 4741 __ Bind(&return_zero); |
| 4710 // Checks if base == 1.0. | 4742 __ movsd(result, zero_temp); |
| 4711 __ comisd(base, result); | 4743 __ jmp(&skip_call); |
| 4712 __ j(PARITY_EVEN, &base_is_nan, Assembler::kNearJump); | 4744 |
| 4713 __ j(EQUAL, &skip_call, Assembler::kNearJump); // base and result are 1.0 | 4745 __ Bind(&do_pow); |
| 4714 __ movsd(result, exp); // result is NaN | |
| 4715 __ jmp(&skip_call, Assembler::kNearJump); | |
| 4716 } | 4746 } |
| 4717 __ Bind(&do_call); | |
| 4718 __ CallRuntime(TargetFunction(), InputCount()); | 4747 __ CallRuntime(TargetFunction(), InputCount()); |
| 4719 __ movaps(locs()->out(0).fpu_reg(), XMM0); | 4748 __ movaps(locs()->out(0).fpu_reg(), XMM0); |
| 4720 __ Bind(&skip_call); | 4749 __ Bind(&skip_call); |
| 4721 // Restore RSP. | 4750 // Restore RSP. |
| 4722 __ movq(RSP, locs()->temp(kSavedSpTempIndex).reg()); | 4751 __ movq(RSP, locs()->temp(kSavedSpTempIndex).reg()); |
| 4723 } | 4752 } |
| 4724 | 4753 |
| 4725 | 4754 |
| 4726 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { | 4755 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { |
| 4727 if (kind() == MergedMathInstr::kTruncDivMod) { | 4756 if (kind() == MergedMathInstr::kTruncDivMod) { |
| (...skipping 672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5400 PcDescriptors::kOther, | 5429 PcDescriptors::kOther, |
| 5401 locs()); | 5430 locs()); |
| 5402 __ Drop(ArgumentCount()); // Discard arguments. | 5431 __ Drop(ArgumentCount()); // Discard arguments. |
| 5403 } | 5432 } |
| 5404 | 5433 |
| 5405 } // namespace dart | 5434 } // namespace dart |
| 5406 | 5435 |
| 5407 #undef __ | 5436 #undef __ |
| 5408 | 5437 |
| 5409 #endif // defined TARGET_ARCH_X64 | 5438 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |