| 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 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 3780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3791 __ movq(kScratchRegister, one_half); | 3791 __ movq(kScratchRegister, one_half); |
| 3792 __ movq(xmm_scratch, kScratchRegister); | 3792 __ movq(xmm_scratch, kScratchRegister); |
| 3793 __ ucomisd(xmm_scratch, input_reg); | 3793 __ ucomisd(xmm_scratch, input_reg); |
| 3794 __ j(above, &below_one_half, Label::kNear); | 3794 __ j(above, &below_one_half, Label::kNear); |
| 3795 | 3795 |
| 3796 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). | 3796 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). |
| 3797 __ addsd(xmm_scratch, input_reg); | 3797 __ addsd(xmm_scratch, input_reg); |
| 3798 __ cvttsd2si(output_reg, xmm_scratch); | 3798 __ cvttsd2si(output_reg, xmm_scratch); |
| 3799 // Overflow is signalled with minint. | 3799 // Overflow is signalled with minint. |
| 3800 __ cmpl(output_reg, Immediate(0x1)); | 3800 __ cmpl(output_reg, Immediate(0x1)); |
| 3801 __ RecordComment("D2I conversion overflow"); | 3801 DeoptimizeIf(overflow, instr, "conversion overflow"); |
| 3802 DeoptimizeIf(overflow, instr); | |
| 3803 __ jmp(&done, dist); | 3802 __ jmp(&done, dist); |
| 3804 | 3803 |
| 3805 __ bind(&below_one_half); | 3804 __ bind(&below_one_half); |
| 3806 __ movq(kScratchRegister, minus_one_half); | 3805 __ movq(kScratchRegister, minus_one_half); |
| 3807 __ movq(xmm_scratch, kScratchRegister); | 3806 __ movq(xmm_scratch, kScratchRegister); |
| 3808 __ ucomisd(xmm_scratch, input_reg); | 3807 __ ucomisd(xmm_scratch, input_reg); |
| 3809 __ j(below_equal, &round_to_zero, Label::kNear); | 3808 __ j(below_equal, &round_to_zero, Label::kNear); |
| 3810 | 3809 |
| 3811 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then | 3810 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then |
| 3812 // compare and compensate. | 3811 // compare and compensate. |
| 3813 __ movq(input_temp, input_reg); // Do not alter input_reg. | 3812 __ movq(input_temp, input_reg); // Do not alter input_reg. |
| 3814 __ subsd(input_temp, xmm_scratch); | 3813 __ subsd(input_temp, xmm_scratch); |
| 3815 __ cvttsd2si(output_reg, input_temp); | 3814 __ cvttsd2si(output_reg, input_temp); |
| 3816 // Catch minint due to overflow, and to prevent overflow when compensating. | 3815 // Catch minint due to overflow, and to prevent overflow when compensating. |
| 3817 __ cmpl(output_reg, Immediate(0x1)); | 3816 __ cmpl(output_reg, Immediate(0x1)); |
| 3818 __ RecordComment("D2I conversion overflow"); | 3817 DeoptimizeIf(overflow, instr, "conversion overflow"); |
| 3819 DeoptimizeIf(overflow, instr); | |
| 3820 | 3818 |
| 3821 __ Cvtlsi2sd(xmm_scratch, output_reg); | 3819 __ Cvtlsi2sd(xmm_scratch, output_reg); |
| 3822 __ ucomisd(xmm_scratch, input_temp); | 3820 __ ucomisd(xmm_scratch, input_temp); |
| 3823 __ j(equal, &done, dist); | 3821 __ j(equal, &done, dist); |
| 3824 __ subl(output_reg, Immediate(1)); | 3822 __ subl(output_reg, Immediate(1)); |
| 3825 // No overflow because we already ruled out minint. | 3823 // No overflow because we already ruled out minint. |
| 3826 __ jmp(&done, dist); | 3824 __ jmp(&done, dist); |
| 3827 | 3825 |
| 3828 __ bind(&round_to_zero); | 3826 __ bind(&round_to_zero); |
| 3829 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if | 3827 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if |
| 3830 // we can ignore the difference between a result of -0 and +0. | 3828 // we can ignore the difference between a result of -0 and +0. |
| 3831 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3829 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3832 __ movq(output_reg, input_reg); | 3830 __ movq(output_reg, input_reg); |
| 3833 __ testq(output_reg, output_reg); | 3831 __ testq(output_reg, output_reg); |
| 3834 __ RecordComment("Minus zero"); | 3832 DeoptimizeIf(negative, instr, "minus zero"); |
| 3835 DeoptimizeIf(negative, instr); | |
| 3836 } | 3833 } |
| 3837 __ Set(output_reg, 0); | 3834 __ Set(output_reg, 0); |
| 3838 __ bind(&done); | 3835 __ bind(&done); |
| 3839 } | 3836 } |
| 3840 | 3837 |
| 3841 | 3838 |
| 3842 void LCodeGen::DoMathFround(LMathFround* instr) { | 3839 void LCodeGen::DoMathFround(LMathFround* instr) { |
| 3843 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3840 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3844 XMMRegister output_reg = ToDoubleRegister(instr->result()); | 3841 XMMRegister output_reg = ToDoubleRegister(instr->result()); |
| 3845 __ cvtsd2ss(output_reg, input_reg); | 3842 __ cvtsd2ss(output_reg, input_reg); |
| (...skipping 1109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4955 __ jmp(done); | 4952 __ jmp(done); |
| 4956 | 4953 |
| 4957 __ bind(&check_bools); | 4954 __ bind(&check_bools); |
| 4958 __ CompareRoot(input_reg, Heap::kTrueValueRootIndex); | 4955 __ CompareRoot(input_reg, Heap::kTrueValueRootIndex); |
| 4959 __ j(not_equal, &check_false, Label::kNear); | 4956 __ j(not_equal, &check_false, Label::kNear); |
| 4960 __ Set(input_reg, 1); | 4957 __ Set(input_reg, 1); |
| 4961 __ jmp(done); | 4958 __ jmp(done); |
| 4962 | 4959 |
| 4963 __ bind(&check_false); | 4960 __ bind(&check_false); |
| 4964 __ CompareRoot(input_reg, Heap::kFalseValueRootIndex); | 4961 __ CompareRoot(input_reg, Heap::kFalseValueRootIndex); |
| 4965 __ RecordComment("Deferred TaggedToI: cannot truncate"); | 4962 DeoptimizeIf(not_equal, instr, "cannot truncate"); |
| 4966 DeoptimizeIf(not_equal, instr); | |
| 4967 __ Set(input_reg, 0); | 4963 __ Set(input_reg, 0); |
| 4968 } else { | 4964 } else { |
| 4969 XMMRegister scratch = ToDoubleRegister(instr->temp()); | 4965 XMMRegister scratch = ToDoubleRegister(instr->temp()); |
| 4970 DCHECK(!scratch.is(xmm0)); | 4966 DCHECK(!scratch.is(xmm0)); |
| 4971 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 4967 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 4972 Heap::kHeapNumberMapRootIndex); | 4968 Heap::kHeapNumberMapRootIndex); |
| 4973 __ RecordComment("Deferred TaggedToI: not a heap number"); | 4969 DeoptimizeIf(not_equal, instr, "not a heap number"); |
| 4974 DeoptimizeIf(not_equal, instr); | |
| 4975 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 4970 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 4976 __ cvttsd2si(input_reg, xmm0); | 4971 __ cvttsd2si(input_reg, xmm0); |
| 4977 __ Cvtlsi2sd(scratch, input_reg); | 4972 __ Cvtlsi2sd(scratch, input_reg); |
| 4978 __ ucomisd(xmm0, scratch); | 4973 __ ucomisd(xmm0, scratch); |
| 4979 __ RecordComment("Deferred TaggedToI: lost precision"); | 4974 DeoptimizeIf(not_equal, instr, "lost precision"); |
| 4980 DeoptimizeIf(not_equal, instr); | 4975 DeoptimizeIf(parity_even, instr, "NaN"); |
| 4981 __ RecordComment("Deferred TaggedToI: NaN"); | |
| 4982 DeoptimizeIf(parity_even, instr); | |
| 4983 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { | 4976 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { |
| 4984 __ testl(input_reg, input_reg); | 4977 __ testl(input_reg, input_reg); |
| 4985 __ j(not_zero, done); | 4978 __ j(not_zero, done); |
| 4986 __ movmskpd(input_reg, xmm0); | 4979 __ movmskpd(input_reg, xmm0); |
| 4987 __ andl(input_reg, Immediate(1)); | 4980 __ andl(input_reg, Immediate(1)); |
| 4988 __ RecordComment("Deferred TaggedToI: minus zero"); | 4981 DeoptimizeIf(not_zero, instr, "minus zero"); |
| 4989 DeoptimizeIf(not_zero, instr); | |
| 4990 } | 4982 } |
| 4991 } | 4983 } |
| 4992 } | 4984 } |
| 4993 | 4985 |
| 4994 | 4986 |
| 4995 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 4987 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 4996 class DeferredTaggedToI FINAL : public LDeferredCode { | 4988 class DeferredTaggedToI FINAL : public LDeferredCode { |
| 4997 public: | 4989 public: |
| 4998 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 4990 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 4999 : LDeferredCode(codegen), instr_(instr) { } | 4991 : LDeferredCode(codegen), instr_(instr) { } |
| (...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5885 CallRuntime(Runtime::kPushBlockContext, 2, instr); | 5877 CallRuntime(Runtime::kPushBlockContext, 2, instr); |
| 5886 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5878 RecordSafepoint(Safepoint::kNoLazyDeopt); |
| 5887 } | 5879 } |
| 5888 | 5880 |
| 5889 | 5881 |
| 5890 #undef __ | 5882 #undef __ |
| 5891 | 5883 |
| 5892 } } // namespace v8::internal | 5884 } } // namespace v8::internal |
| 5893 | 5885 |
| 5894 #endif // V8_TARGET_ARCH_X64 | 5886 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |