| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/hydrogen-osr.h" | 10 #include "src/hydrogen-osr.h" |
| (...skipping 3586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3597 | 3597 |
| 3598 void LCodeGen::DoMathFloor(LMathFloor* instr) { | 3598 void LCodeGen::DoMathFloor(LMathFloor* instr) { |
| 3599 XMMRegister xmm_scratch = double_scratch0(); | 3599 XMMRegister xmm_scratch = double_scratch0(); |
| 3600 Register output_reg = ToRegister(instr->result()); | 3600 Register output_reg = ToRegister(instr->result()); |
| 3601 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3601 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3602 | 3602 |
| 3603 if (CpuFeatures::IsSupported(SSE4_1)) { | 3603 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 3604 CpuFeatureScope scope(masm(), SSE4_1); | 3604 CpuFeatureScope scope(masm(), SSE4_1); |
| 3605 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3605 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3606 // Deoptimize if minus zero. | 3606 // Deoptimize if minus zero. |
| 3607 __ movq(output_reg, input_reg); | 3607 __ Movq(output_reg, input_reg); |
| 3608 __ subq(output_reg, Immediate(1)); | 3608 __ subq(output_reg, Immediate(1)); |
| 3609 DeoptimizeIf(overflow, instr, Deoptimizer::kMinusZero); | 3609 DeoptimizeIf(overflow, instr, Deoptimizer::kMinusZero); |
| 3610 } | 3610 } |
| 3611 __ roundsd(xmm_scratch, input_reg, kRoundDown); | 3611 __ roundsd(xmm_scratch, input_reg, kRoundDown); |
| 3612 __ cvttsd2si(output_reg, xmm_scratch); | 3612 __ cvttsd2si(output_reg, xmm_scratch); |
| 3613 __ cmpl(output_reg, Immediate(0x1)); | 3613 __ cmpl(output_reg, Immediate(0x1)); |
| 3614 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 3614 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); |
| 3615 } else { | 3615 } else { |
| 3616 Label negative_sign, done; | 3616 Label negative_sign, done; |
| 3617 // Deoptimize on unordered. | 3617 // Deoptimize on unordered. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3658 const XMMRegister xmm_scratch = double_scratch0(); | 3658 const XMMRegister xmm_scratch = double_scratch0(); |
| 3659 Register output_reg = ToRegister(instr->result()); | 3659 Register output_reg = ToRegister(instr->result()); |
| 3660 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3660 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3661 XMMRegister input_temp = ToDoubleRegister(instr->temp()); | 3661 XMMRegister input_temp = ToDoubleRegister(instr->temp()); |
| 3662 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 | 3662 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 |
| 3663 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 | 3663 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 |
| 3664 | 3664 |
| 3665 Label done, round_to_zero, below_one_half; | 3665 Label done, round_to_zero, below_one_half; |
| 3666 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; | 3666 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
| 3667 __ movq(kScratchRegister, one_half); | 3667 __ movq(kScratchRegister, one_half); |
| 3668 __ movq(xmm_scratch, kScratchRegister); | 3668 __ Movq(xmm_scratch, kScratchRegister); |
| 3669 __ ucomisd(xmm_scratch, input_reg); | 3669 __ ucomisd(xmm_scratch, input_reg); |
| 3670 __ j(above, &below_one_half, Label::kNear); | 3670 __ j(above, &below_one_half, Label::kNear); |
| 3671 | 3671 |
| 3672 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). | 3672 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). |
| 3673 __ addsd(xmm_scratch, input_reg); | 3673 __ addsd(xmm_scratch, input_reg); |
| 3674 __ cvttsd2si(output_reg, xmm_scratch); | 3674 __ cvttsd2si(output_reg, xmm_scratch); |
| 3675 // Overflow is signalled with minint. | 3675 // Overflow is signalled with minint. |
| 3676 __ cmpl(output_reg, Immediate(0x1)); | 3676 __ cmpl(output_reg, Immediate(0x1)); |
| 3677 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 3677 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); |
| 3678 __ jmp(&done, dist); | 3678 __ jmp(&done, dist); |
| 3679 | 3679 |
| 3680 __ bind(&below_one_half); | 3680 __ bind(&below_one_half); |
| 3681 __ movq(kScratchRegister, minus_one_half); | 3681 __ movq(kScratchRegister, minus_one_half); |
| 3682 __ movq(xmm_scratch, kScratchRegister); | 3682 __ Movq(xmm_scratch, kScratchRegister); |
| 3683 __ ucomisd(xmm_scratch, input_reg); | 3683 __ ucomisd(xmm_scratch, input_reg); |
| 3684 __ j(below_equal, &round_to_zero, Label::kNear); | 3684 __ j(below_equal, &round_to_zero, Label::kNear); |
| 3685 | 3685 |
| 3686 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then | 3686 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then |
| 3687 // compare and compensate. | 3687 // compare and compensate. |
| 3688 __ movq(input_temp, input_reg); // Do not alter input_reg. | 3688 __ Movapd(input_temp, input_reg); // Do not alter input_reg. |
| 3689 __ subsd(input_temp, xmm_scratch); | 3689 __ subsd(input_temp, xmm_scratch); |
| 3690 __ cvttsd2si(output_reg, input_temp); | 3690 __ cvttsd2si(output_reg, input_temp); |
| 3691 // Catch minint due to overflow, and to prevent overflow when compensating. | 3691 // Catch minint due to overflow, and to prevent overflow when compensating. |
| 3692 __ cmpl(output_reg, Immediate(0x1)); | 3692 __ cmpl(output_reg, Immediate(0x1)); |
| 3693 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 3693 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); |
| 3694 | 3694 |
| 3695 __ Cvtlsi2sd(xmm_scratch, output_reg); | 3695 __ Cvtlsi2sd(xmm_scratch, output_reg); |
| 3696 __ ucomisd(xmm_scratch, input_temp); | 3696 __ ucomisd(xmm_scratch, input_temp); |
| 3697 __ j(equal, &done, dist); | 3697 __ j(equal, &done, dist); |
| 3698 __ subl(output_reg, Immediate(1)); | 3698 __ subl(output_reg, Immediate(1)); |
| 3699 // No overflow because we already ruled out minint. | 3699 // No overflow because we already ruled out minint. |
| 3700 __ jmp(&done, dist); | 3700 __ jmp(&done, dist); |
| 3701 | 3701 |
| 3702 __ bind(&round_to_zero); | 3702 __ bind(&round_to_zero); |
| 3703 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if | 3703 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if |
| 3704 // we can ignore the difference between a result of -0 and +0. | 3704 // we can ignore the difference between a result of -0 and +0. |
| 3705 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3705 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3706 __ movq(output_reg, input_reg); | 3706 __ Movq(output_reg, input_reg); |
| 3707 __ testq(output_reg, output_reg); | 3707 __ testq(output_reg, output_reg); |
| 3708 DeoptimizeIf(negative, instr, Deoptimizer::kMinusZero); | 3708 DeoptimizeIf(negative, instr, Deoptimizer::kMinusZero); |
| 3709 } | 3709 } |
| 3710 __ Set(output_reg, 0); | 3710 __ Set(output_reg, 0); |
| 3711 __ bind(&done); | 3711 __ bind(&done); |
| 3712 } | 3712 } |
| 3713 | 3713 |
| 3714 | 3714 |
| 3715 void LCodeGen::DoMathFround(LMathFround* instr) { | 3715 void LCodeGen::DoMathFround(LMathFround* instr) { |
| 3716 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3716 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3737 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3737 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3738 DCHECK(ToDoubleRegister(instr->result()).is(input_reg)); | 3738 DCHECK(ToDoubleRegister(instr->result()).is(input_reg)); |
| 3739 | 3739 |
| 3740 // Note that according to ECMA-262 15.8.2.13: | 3740 // Note that according to ECMA-262 15.8.2.13: |
| 3741 // Math.pow(-Infinity, 0.5) == Infinity | 3741 // Math.pow(-Infinity, 0.5) == Infinity |
| 3742 // Math.sqrt(-Infinity) == NaN | 3742 // Math.sqrt(-Infinity) == NaN |
| 3743 Label done, sqrt; | 3743 Label done, sqrt; |
| 3744 // Check base for -Infinity. According to IEEE-754, double-precision | 3744 // Check base for -Infinity. According to IEEE-754, double-precision |
| 3745 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. | 3745 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. |
| 3746 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000)); | 3746 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000)); |
| 3747 __ movq(xmm_scratch, kScratchRegister); | 3747 __ Movq(xmm_scratch, kScratchRegister); |
| 3748 __ ucomisd(xmm_scratch, input_reg); | 3748 __ ucomisd(xmm_scratch, input_reg); |
| 3749 // Comparing -Infinity with NaN results in "unordered", which sets the | 3749 // Comparing -Infinity with NaN results in "unordered", which sets the |
| 3750 // zero flag as if both were equal. However, it also sets the carry flag. | 3750 // zero flag as if both were equal. However, it also sets the carry flag. |
| 3751 __ j(not_equal, &sqrt, Label::kNear); | 3751 __ j(not_equal, &sqrt, Label::kNear); |
| 3752 __ j(carry, &sqrt, Label::kNear); | 3752 __ j(carry, &sqrt, Label::kNear); |
| 3753 // If input is -Infinity, return Infinity. | 3753 // If input is -Infinity, return Infinity. |
| 3754 __ xorps(input_reg, input_reg); | 3754 __ xorps(input_reg, input_reg); |
| 3755 __ subsd(input_reg, xmm_scratch); | 3755 __ subsd(input_reg, xmm_scratch); |
| 3756 __ jmp(&done, Label::kNear); | 3756 __ jmp(&done, Label::kNear); |
| 3757 | 3757 |
| (...skipping 1557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5315 __ ClampUint8(input_reg); | 5315 __ ClampUint8(input_reg); |
| 5316 | 5316 |
| 5317 __ bind(&done); | 5317 __ bind(&done); |
| 5318 } | 5318 } |
| 5319 | 5319 |
| 5320 | 5320 |
| 5321 void LCodeGen::DoDoubleBits(LDoubleBits* instr) { | 5321 void LCodeGen::DoDoubleBits(LDoubleBits* instr) { |
| 5322 XMMRegister value_reg = ToDoubleRegister(instr->value()); | 5322 XMMRegister value_reg = ToDoubleRegister(instr->value()); |
| 5323 Register result_reg = ToRegister(instr->result()); | 5323 Register result_reg = ToRegister(instr->result()); |
| 5324 if (instr->hydrogen()->bits() == HDoubleBits::HIGH) { | 5324 if (instr->hydrogen()->bits() == HDoubleBits::HIGH) { |
| 5325 __ movq(result_reg, value_reg); | 5325 __ Movq(result_reg, value_reg); |
| 5326 __ shrq(result_reg, Immediate(32)); | 5326 __ shrq(result_reg, Immediate(32)); |
| 5327 } else { | 5327 } else { |
| 5328 __ movd(result_reg, value_reg); | 5328 __ Movd(result_reg, value_reg); |
| 5329 } | 5329 } |
| 5330 } | 5330 } |
| 5331 | 5331 |
| 5332 | 5332 |
| 5333 void LCodeGen::DoConstructDouble(LConstructDouble* instr) { | 5333 void LCodeGen::DoConstructDouble(LConstructDouble* instr) { |
| 5334 Register hi_reg = ToRegister(instr->hi()); | 5334 Register hi_reg = ToRegister(instr->hi()); |
| 5335 Register lo_reg = ToRegister(instr->lo()); | 5335 Register lo_reg = ToRegister(instr->lo()); |
| 5336 XMMRegister result_reg = ToDoubleRegister(instr->result()); | 5336 XMMRegister result_reg = ToDoubleRegister(instr->result()); |
| 5337 XMMRegister xmm_scratch = double_scratch0(); | 5337 XMMRegister xmm_scratch = double_scratch0(); |
| 5338 __ movd(result_reg, hi_reg); | 5338 __ Movd(result_reg, hi_reg); |
| 5339 __ psllq(result_reg, 32); | 5339 __ psllq(result_reg, 32); |
| 5340 __ movd(xmm_scratch, lo_reg); | 5340 __ Movd(xmm_scratch, lo_reg); |
| 5341 __ orps(result_reg, xmm_scratch); | 5341 __ orps(result_reg, xmm_scratch); |
| 5342 } | 5342 } |
| 5343 | 5343 |
| 5344 | 5344 |
| 5345 void LCodeGen::DoAllocate(LAllocate* instr) { | 5345 void LCodeGen::DoAllocate(LAllocate* instr) { |
| 5346 class DeferredAllocate final : public LDeferredCode { | 5346 class DeferredAllocate final : public LDeferredCode { |
| 5347 public: | 5347 public: |
| 5348 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) | 5348 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) |
| 5349 : LDeferredCode(codegen), instr_(instr) { } | 5349 : LDeferredCode(codegen), instr_(instr) { } |
| 5350 void Generate() override { codegen()->DoDeferredAllocate(instr_); } | 5350 void Generate() override { codegen()->DoDeferredAllocate(instr_); } |
| (...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5905 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5905 RecordSafepoint(Safepoint::kNoLazyDeopt); |
| 5906 } | 5906 } |
| 5907 | 5907 |
| 5908 | 5908 |
| 5909 #undef __ | 5909 #undef __ |
| 5910 | 5910 |
| 5911 } // namespace internal | 5911 } // namespace internal |
| 5912 } // namespace v8 | 5912 } // namespace v8 |
| 5913 | 5913 |
| 5914 #endif // V8_TARGET_ARCH_X64 | 5914 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |