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 |