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 1949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1960 __ j(condition, &return_left, Label::kNear); | 1960 __ j(condition, &return_left, Label::kNear); |
1961 __ movp(left_reg, right_op); | 1961 __ movp(left_reg, right_op); |
1962 } | 1962 } |
1963 __ bind(&return_left); | 1963 __ bind(&return_left); |
1964 } else { | 1964 } else { |
1965 DCHECK(instr->hydrogen()->representation().IsDouble()); | 1965 DCHECK(instr->hydrogen()->representation().IsDouble()); |
1966 Label check_nan_left, check_zero, return_left, return_right; | 1966 Label check_nan_left, check_zero, return_left, return_right; |
1967 Condition condition = (operation == HMathMinMax::kMathMin) ? below : above; | 1967 Condition condition = (operation == HMathMinMax::kMathMin) ? below : above; |
1968 XMMRegister left_reg = ToDoubleRegister(left); | 1968 XMMRegister left_reg = ToDoubleRegister(left); |
1969 XMMRegister right_reg = ToDoubleRegister(right); | 1969 XMMRegister right_reg = ToDoubleRegister(right); |
1970 __ ucomisd(left_reg, right_reg); | 1970 __ Ucomisd(left_reg, right_reg); |
1971 __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN. | 1971 __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN. |
1972 __ j(equal, &check_zero, Label::kNear); // left == right. | 1972 __ j(equal, &check_zero, Label::kNear); // left == right. |
1973 __ j(condition, &return_left, Label::kNear); | 1973 __ j(condition, &return_left, Label::kNear); |
1974 __ jmp(&return_right, Label::kNear); | 1974 __ jmp(&return_right, Label::kNear); |
1975 | 1975 |
1976 __ bind(&check_zero); | 1976 __ bind(&check_zero); |
1977 XMMRegister xmm_scratch = double_scratch0(); | 1977 XMMRegister xmm_scratch = double_scratch0(); |
1978 __ Xorpd(xmm_scratch, xmm_scratch); | 1978 __ Xorpd(xmm_scratch, xmm_scratch); |
1979 __ ucomisd(left_reg, xmm_scratch); | 1979 __ Ucomisd(left_reg, xmm_scratch); |
1980 __ j(not_equal, &return_left, Label::kNear); // left == right != 0. | 1980 __ j(not_equal, &return_left, Label::kNear); // left == right != 0. |
1981 // At this point, both left and right are either 0 or -0. | 1981 // At this point, both left and right are either 0 or -0. |
1982 if (operation == HMathMinMax::kMathMin) { | 1982 if (operation == HMathMinMax::kMathMin) { |
1983 __ orps(left_reg, right_reg); | 1983 __ orps(left_reg, right_reg); |
1984 } else { | 1984 } else { |
1985 // Since we operate on +0 and/or -0, addsd and andsd have the same effect. | 1985 // Since we operate on +0 and/or -0, addsd and andsd have the same effect. |
1986 __ addsd(left_reg, right_reg); | 1986 __ addsd(left_reg, right_reg); |
1987 } | 1987 } |
1988 __ jmp(&return_left, Label::kNear); | 1988 __ jmp(&return_left, Label::kNear); |
1989 | 1989 |
1990 __ bind(&check_nan_left); | 1990 __ bind(&check_nan_left); |
1991 __ ucomisd(left_reg, left_reg); // NaN check. | 1991 __ Ucomisd(left_reg, left_reg); // NaN check. |
1992 __ j(parity_even, &return_left, Label::kNear); | 1992 __ j(parity_even, &return_left, Label::kNear); |
1993 __ bind(&return_right); | 1993 __ bind(&return_right); |
1994 __ Movapd(left_reg, right_reg); | 1994 __ Movapd(left_reg, right_reg); |
1995 | 1995 |
1996 __ bind(&return_left); | 1996 __ bind(&return_left); |
1997 } | 1997 } |
1998 } | 1998 } |
1999 | 1999 |
2000 | 2000 |
2001 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 2001 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2122 } else if (r.IsSmi()) { | 2122 } else if (r.IsSmi()) { |
2123 DCHECK(!info()->IsStub()); | 2123 DCHECK(!info()->IsStub()); |
2124 Register reg = ToRegister(instr->value()); | 2124 Register reg = ToRegister(instr->value()); |
2125 __ testp(reg, reg); | 2125 __ testp(reg, reg); |
2126 EmitBranch(instr, not_zero); | 2126 EmitBranch(instr, not_zero); |
2127 } else if (r.IsDouble()) { | 2127 } else if (r.IsDouble()) { |
2128 DCHECK(!info()->IsStub()); | 2128 DCHECK(!info()->IsStub()); |
2129 XMMRegister reg = ToDoubleRegister(instr->value()); | 2129 XMMRegister reg = ToDoubleRegister(instr->value()); |
2130 XMMRegister xmm_scratch = double_scratch0(); | 2130 XMMRegister xmm_scratch = double_scratch0(); |
2131 __ Xorpd(xmm_scratch, xmm_scratch); | 2131 __ Xorpd(xmm_scratch, xmm_scratch); |
2132 __ ucomisd(reg, xmm_scratch); | 2132 __ Ucomisd(reg, xmm_scratch); |
2133 EmitBranch(instr, not_equal); | 2133 EmitBranch(instr, not_equal); |
2134 } else { | 2134 } else { |
2135 DCHECK(r.IsTagged()); | 2135 DCHECK(r.IsTagged()); |
2136 Register reg = ToRegister(instr->value()); | 2136 Register reg = ToRegister(instr->value()); |
2137 HType type = instr->hydrogen()->value()->type(); | 2137 HType type = instr->hydrogen()->value()->type(); |
2138 if (type.IsBoolean()) { | 2138 if (type.IsBoolean()) { |
2139 DCHECK(!info()->IsStub()); | 2139 DCHECK(!info()->IsStub()); |
2140 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 2140 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
2141 EmitBranch(instr, equal); | 2141 EmitBranch(instr, equal); |
2142 } else if (type.IsSmi()) { | 2142 } else if (type.IsSmi()) { |
2143 DCHECK(!info()->IsStub()); | 2143 DCHECK(!info()->IsStub()); |
2144 __ SmiCompare(reg, Smi::FromInt(0)); | 2144 __ SmiCompare(reg, Smi::FromInt(0)); |
2145 EmitBranch(instr, not_equal); | 2145 EmitBranch(instr, not_equal); |
2146 } else if (type.IsJSArray()) { | 2146 } else if (type.IsJSArray()) { |
2147 DCHECK(!info()->IsStub()); | 2147 DCHECK(!info()->IsStub()); |
2148 EmitBranch(instr, no_condition); | 2148 EmitBranch(instr, no_condition); |
2149 } else if (type.IsHeapNumber()) { | 2149 } else if (type.IsHeapNumber()) { |
2150 DCHECK(!info()->IsStub()); | 2150 DCHECK(!info()->IsStub()); |
2151 XMMRegister xmm_scratch = double_scratch0(); | 2151 XMMRegister xmm_scratch = double_scratch0(); |
2152 __ Xorpd(xmm_scratch, xmm_scratch); | 2152 __ Xorpd(xmm_scratch, xmm_scratch); |
2153 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); | 2153 __ Ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); |
2154 EmitBranch(instr, not_equal); | 2154 EmitBranch(instr, not_equal); |
2155 } else if (type.IsString()) { | 2155 } else if (type.IsString()) { |
2156 DCHECK(!info()->IsStub()); | 2156 DCHECK(!info()->IsStub()); |
2157 __ cmpp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 2157 __ cmpp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
2158 EmitBranch(instr, not_equal); | 2158 EmitBranch(instr, not_equal); |
2159 } else { | 2159 } else { |
2160 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 2160 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
2161 // Avoid deopts in the case where we've never executed this path before. | 2161 // Avoid deopts in the case where we've never executed this path before. |
2162 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); | 2162 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); |
2163 | 2163 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2232 __ j(equal, instr->TrueLabel(chunk_)); | 2232 __ j(equal, instr->TrueLabel(chunk_)); |
2233 } | 2233 } |
2234 | 2234 |
2235 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 2235 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
2236 // heap number -> false iff +0, -0, or NaN. | 2236 // heap number -> false iff +0, -0, or NaN. |
2237 Label not_heap_number; | 2237 Label not_heap_number; |
2238 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 2238 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
2239 __ j(not_equal, ¬_heap_number, Label::kNear); | 2239 __ j(not_equal, ¬_heap_number, Label::kNear); |
2240 XMMRegister xmm_scratch = double_scratch0(); | 2240 XMMRegister xmm_scratch = double_scratch0(); |
2241 __ Xorpd(xmm_scratch, xmm_scratch); | 2241 __ Xorpd(xmm_scratch, xmm_scratch); |
2242 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); | 2242 __ Ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); |
2243 __ j(zero, instr->FalseLabel(chunk_)); | 2243 __ j(zero, instr->FalseLabel(chunk_)); |
2244 __ jmp(instr->TrueLabel(chunk_)); | 2244 __ jmp(instr->TrueLabel(chunk_)); |
2245 __ bind(¬_heap_number); | 2245 __ bind(¬_heap_number); |
2246 } | 2246 } |
2247 | 2247 |
2248 if (!expected.IsGeneric()) { | 2248 if (!expected.IsGeneric()) { |
2249 // We've seen something for the first time -> deopt. | 2249 // We've seen something for the first time -> deopt. |
2250 // This can only happen if we are not generic already. | 2250 // This can only happen if we are not generic already. |
2251 DeoptimizeIf(no_condition, instr, Deoptimizer::kUnexpectedObject); | 2251 DeoptimizeIf(no_condition, instr, Deoptimizer::kUnexpectedObject); |
2252 } | 2252 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2312 // We can statically evaluate the comparison. | 2312 // We can statically evaluate the comparison. |
2313 double left_val = ToDouble(LConstantOperand::cast(left)); | 2313 double left_val = ToDouble(LConstantOperand::cast(left)); |
2314 double right_val = ToDouble(LConstantOperand::cast(right)); | 2314 double right_val = ToDouble(LConstantOperand::cast(right)); |
2315 int next_block = EvalComparison(instr->op(), left_val, right_val) ? | 2315 int next_block = EvalComparison(instr->op(), left_val, right_val) ? |
2316 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); | 2316 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); |
2317 EmitGoto(next_block); | 2317 EmitGoto(next_block); |
2318 } else { | 2318 } else { |
2319 if (instr->is_double()) { | 2319 if (instr->is_double()) { |
2320 // Don't base result on EFLAGS when a NaN is involved. Instead | 2320 // Don't base result on EFLAGS when a NaN is involved. Instead |
2321 // jump to the false block. | 2321 // jump to the false block. |
2322 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 2322 __ Ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
2323 __ j(parity_even, instr->FalseLabel(chunk_)); | 2323 __ j(parity_even, instr->FalseLabel(chunk_)); |
2324 } else { | 2324 } else { |
2325 int32_t value; | 2325 int32_t value; |
2326 if (right->IsConstantOperand()) { | 2326 if (right->IsConstantOperand()) { |
2327 value = ToInteger32(LConstantOperand::cast(right)); | 2327 value = ToInteger32(LConstantOperand::cast(right)); |
2328 if (instr->hydrogen_value()->representation().IsSmi()) { | 2328 if (instr->hydrogen_value()->representation().IsSmi()) { |
2329 __ Cmp(ToRegister(left), Smi::FromInt(value)); | 2329 __ Cmp(ToRegister(left), Smi::FromInt(value)); |
2330 } else { | 2330 } else { |
2331 __ cmpl(ToRegister(left), Immediate(value)); | 2331 __ cmpl(ToRegister(left), Immediate(value)); |
2332 } | 2332 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2380 | 2380 |
2381 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { | 2381 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { |
2382 if (instr->hydrogen()->representation().IsTagged()) { | 2382 if (instr->hydrogen()->representation().IsTagged()) { |
2383 Register input_reg = ToRegister(instr->object()); | 2383 Register input_reg = ToRegister(instr->object()); |
2384 __ Cmp(input_reg, factory()->the_hole_value()); | 2384 __ Cmp(input_reg, factory()->the_hole_value()); |
2385 EmitBranch(instr, equal); | 2385 EmitBranch(instr, equal); |
2386 return; | 2386 return; |
2387 } | 2387 } |
2388 | 2388 |
2389 XMMRegister input_reg = ToDoubleRegister(instr->object()); | 2389 XMMRegister input_reg = ToDoubleRegister(instr->object()); |
2390 __ ucomisd(input_reg, input_reg); | 2390 __ Ucomisd(input_reg, input_reg); |
2391 EmitFalseBranch(instr, parity_odd); | 2391 EmitFalseBranch(instr, parity_odd); |
2392 | 2392 |
2393 __ subp(rsp, Immediate(kDoubleSize)); | 2393 __ subp(rsp, Immediate(kDoubleSize)); |
2394 __ Movsd(MemOperand(rsp, 0), input_reg); | 2394 __ Movsd(MemOperand(rsp, 0), input_reg); |
2395 __ addp(rsp, Immediate(kDoubleSize)); | 2395 __ addp(rsp, Immediate(kDoubleSize)); |
2396 | 2396 |
2397 int offset = sizeof(kHoleNanUpper32); | 2397 int offset = sizeof(kHoleNanUpper32); |
2398 __ cmpl(MemOperand(rsp, -offset), Immediate(kHoleNanUpper32)); | 2398 __ cmpl(MemOperand(rsp, -offset), Immediate(kHoleNanUpper32)); |
2399 EmitBranch(instr, equal); | 2399 EmitBranch(instr, equal); |
2400 } | 2400 } |
2401 | 2401 |
2402 | 2402 |
2403 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { | 2403 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { |
2404 Representation rep = instr->hydrogen()->value()->representation(); | 2404 Representation rep = instr->hydrogen()->value()->representation(); |
2405 DCHECK(!rep.IsInteger32()); | 2405 DCHECK(!rep.IsInteger32()); |
2406 | 2406 |
2407 if (rep.IsDouble()) { | 2407 if (rep.IsDouble()) { |
2408 XMMRegister value = ToDoubleRegister(instr->value()); | 2408 XMMRegister value = ToDoubleRegister(instr->value()); |
2409 XMMRegister xmm_scratch = double_scratch0(); | 2409 XMMRegister xmm_scratch = double_scratch0(); |
2410 __ Xorpd(xmm_scratch, xmm_scratch); | 2410 __ Xorpd(xmm_scratch, xmm_scratch); |
2411 __ ucomisd(xmm_scratch, value); | 2411 __ Ucomisd(xmm_scratch, value); |
2412 EmitFalseBranch(instr, not_equal); | 2412 EmitFalseBranch(instr, not_equal); |
2413 __ Movmskpd(kScratchRegister, value); | 2413 __ Movmskpd(kScratchRegister, value); |
2414 __ testl(kScratchRegister, Immediate(1)); | 2414 __ testl(kScratchRegister, Immediate(1)); |
2415 EmitBranch(instr, not_zero); | 2415 EmitBranch(instr, not_zero); |
2416 } else { | 2416 } else { |
2417 Register value = ToRegister(instr->value()); | 2417 Register value = ToRegister(instr->value()); |
2418 Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); | 2418 Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); |
2419 __ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK); | 2419 __ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK); |
2420 __ cmpl(FieldOperand(value, HeapNumber::kExponentOffset), | 2420 __ cmpl(FieldOperand(value, HeapNumber::kExponentOffset), |
2421 Immediate(0x1)); | 2421 Immediate(0x1)); |
(...skipping 1186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3608 DeoptimizeIf(overflow, instr, Deoptimizer::kMinusZero); | 3608 DeoptimizeIf(overflow, instr, Deoptimizer::kMinusZero); |
3609 } | 3609 } |
3610 __ roundsd(xmm_scratch, input_reg, kRoundDown); | 3610 __ roundsd(xmm_scratch, input_reg, kRoundDown); |
3611 __ Cvttsd2si(output_reg, xmm_scratch); | 3611 __ Cvttsd2si(output_reg, xmm_scratch); |
3612 __ cmpl(output_reg, Immediate(0x1)); | 3612 __ cmpl(output_reg, Immediate(0x1)); |
3613 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 3613 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); |
3614 } else { | 3614 } else { |
3615 Label negative_sign, done; | 3615 Label negative_sign, done; |
3616 // Deoptimize on unordered. | 3616 // Deoptimize on unordered. |
3617 __ Xorpd(xmm_scratch, xmm_scratch); // Zero the register. | 3617 __ Xorpd(xmm_scratch, xmm_scratch); // Zero the register. |
3618 __ ucomisd(input_reg, xmm_scratch); | 3618 __ Ucomisd(input_reg, xmm_scratch); |
3619 DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN); | 3619 DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN); |
3620 __ j(below, &negative_sign, Label::kNear); | 3620 __ j(below, &negative_sign, Label::kNear); |
3621 | 3621 |
3622 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3622 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3623 // Check for negative zero. | 3623 // Check for negative zero. |
3624 Label positive_sign; | 3624 Label positive_sign; |
3625 __ j(above, &positive_sign, Label::kNear); | 3625 __ j(above, &positive_sign, Label::kNear); |
3626 __ Movmskpd(output_reg, input_reg); | 3626 __ Movmskpd(output_reg, input_reg); |
3627 __ testl(output_reg, Immediate(1)); | 3627 __ testl(output_reg, Immediate(1)); |
3628 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); | 3628 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); |
3629 __ Set(output_reg, 0); | 3629 __ Set(output_reg, 0); |
3630 __ jmp(&done); | 3630 __ jmp(&done); |
3631 __ bind(&positive_sign); | 3631 __ bind(&positive_sign); |
3632 } | 3632 } |
3633 | 3633 |
3634 // Use truncating instruction (OK because input is positive). | 3634 // Use truncating instruction (OK because input is positive). |
3635 __ Cvttsd2si(output_reg, input_reg); | 3635 __ Cvttsd2si(output_reg, input_reg); |
3636 // Overflow is signalled with minint. | 3636 // Overflow is signalled with minint. |
3637 __ cmpl(output_reg, Immediate(0x1)); | 3637 __ cmpl(output_reg, Immediate(0x1)); |
3638 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 3638 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); |
3639 __ jmp(&done, Label::kNear); | 3639 __ jmp(&done, Label::kNear); |
3640 | 3640 |
3641 // Non-zero negative reaches here. | 3641 // Non-zero negative reaches here. |
3642 __ bind(&negative_sign); | 3642 __ bind(&negative_sign); |
3643 // Truncate, then compare and compensate. | 3643 // Truncate, then compare and compensate. |
3644 __ Cvttsd2si(output_reg, input_reg); | 3644 __ Cvttsd2si(output_reg, input_reg); |
3645 __ Cvtlsi2sd(xmm_scratch, output_reg); | 3645 __ Cvtlsi2sd(xmm_scratch, output_reg); |
3646 __ ucomisd(input_reg, xmm_scratch); | 3646 __ Ucomisd(input_reg, xmm_scratch); |
3647 __ j(equal, &done, Label::kNear); | 3647 __ j(equal, &done, Label::kNear); |
3648 __ subl(output_reg, Immediate(1)); | 3648 __ subl(output_reg, Immediate(1)); |
3649 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 3649 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); |
3650 | 3650 |
3651 __ bind(&done); | 3651 __ bind(&done); |
3652 } | 3652 } |
3653 } | 3653 } |
3654 | 3654 |
3655 | 3655 |
3656 void LCodeGen::DoMathRound(LMathRound* instr) { | 3656 void LCodeGen::DoMathRound(LMathRound* instr) { |
3657 const XMMRegister xmm_scratch = double_scratch0(); | 3657 const XMMRegister xmm_scratch = double_scratch0(); |
3658 Register output_reg = ToRegister(instr->result()); | 3658 Register output_reg = ToRegister(instr->result()); |
3659 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3659 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3660 XMMRegister input_temp = ToDoubleRegister(instr->temp()); | 3660 XMMRegister input_temp = ToDoubleRegister(instr->temp()); |
3661 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 | 3661 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 |
3662 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 | 3662 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 |
3663 | 3663 |
3664 Label done, round_to_zero, below_one_half; | 3664 Label done, round_to_zero, below_one_half; |
3665 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; | 3665 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
3666 __ movq(kScratchRegister, one_half); | 3666 __ movq(kScratchRegister, one_half); |
3667 __ Movq(xmm_scratch, kScratchRegister); | 3667 __ Movq(xmm_scratch, kScratchRegister); |
3668 __ ucomisd(xmm_scratch, input_reg); | 3668 __ Ucomisd(xmm_scratch, input_reg); |
3669 __ j(above, &below_one_half, Label::kNear); | 3669 __ j(above, &below_one_half, Label::kNear); |
3670 | 3670 |
3671 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). | 3671 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). |
3672 __ addsd(xmm_scratch, input_reg); | 3672 __ addsd(xmm_scratch, input_reg); |
3673 __ Cvttsd2si(output_reg, xmm_scratch); | 3673 __ Cvttsd2si(output_reg, xmm_scratch); |
3674 // Overflow is signalled with minint. | 3674 // Overflow is signalled with minint. |
3675 __ cmpl(output_reg, Immediate(0x1)); | 3675 __ cmpl(output_reg, Immediate(0x1)); |
3676 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 3676 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); |
3677 __ jmp(&done, dist); | 3677 __ jmp(&done, dist); |
3678 | 3678 |
3679 __ bind(&below_one_half); | 3679 __ bind(&below_one_half); |
3680 __ movq(kScratchRegister, minus_one_half); | 3680 __ movq(kScratchRegister, minus_one_half); |
3681 __ Movq(xmm_scratch, kScratchRegister); | 3681 __ Movq(xmm_scratch, kScratchRegister); |
3682 __ ucomisd(xmm_scratch, input_reg); | 3682 __ Ucomisd(xmm_scratch, input_reg); |
3683 __ j(below_equal, &round_to_zero, Label::kNear); | 3683 __ j(below_equal, &round_to_zero, Label::kNear); |
3684 | 3684 |
3685 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then | 3685 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then |
3686 // compare and compensate. | 3686 // compare and compensate. |
3687 __ Movapd(input_temp, input_reg); // Do not alter input_reg. | 3687 __ Movapd(input_temp, input_reg); // Do not alter input_reg. |
3688 __ subsd(input_temp, xmm_scratch); | 3688 __ subsd(input_temp, xmm_scratch); |
3689 __ Cvttsd2si(output_reg, input_temp); | 3689 __ Cvttsd2si(output_reg, input_temp); |
3690 // Catch minint due to overflow, and to prevent overflow when compensating. | 3690 // Catch minint due to overflow, and to prevent overflow when compensating. |
3691 __ cmpl(output_reg, Immediate(0x1)); | 3691 __ cmpl(output_reg, Immediate(0x1)); |
3692 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 3692 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); |
3693 | 3693 |
3694 __ Cvtlsi2sd(xmm_scratch, output_reg); | 3694 __ Cvtlsi2sd(xmm_scratch, output_reg); |
3695 __ ucomisd(xmm_scratch, input_temp); | 3695 __ Ucomisd(xmm_scratch, input_temp); |
3696 __ j(equal, &done, dist); | 3696 __ j(equal, &done, dist); |
3697 __ subl(output_reg, Immediate(1)); | 3697 __ subl(output_reg, Immediate(1)); |
3698 // No overflow because we already ruled out minint. | 3698 // No overflow because we already ruled out minint. |
3699 __ jmp(&done, dist); | 3699 __ jmp(&done, dist); |
3700 | 3700 |
3701 __ bind(&round_to_zero); | 3701 __ bind(&round_to_zero); |
3702 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if | 3702 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if |
3703 // we can ignore the difference between a result of -0 and +0. | 3703 // we can ignore the difference between a result of -0 and +0. |
3704 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3704 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3705 __ Movq(output_reg, input_reg); | 3705 __ Movq(output_reg, input_reg); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3737 DCHECK(ToDoubleRegister(instr->result()).is(input_reg)); | 3737 DCHECK(ToDoubleRegister(instr->result()).is(input_reg)); |
3738 | 3738 |
3739 // Note that according to ECMA-262 15.8.2.13: | 3739 // Note that according to ECMA-262 15.8.2.13: |
3740 // Math.pow(-Infinity, 0.5) == Infinity | 3740 // Math.pow(-Infinity, 0.5) == Infinity |
3741 // Math.sqrt(-Infinity) == NaN | 3741 // Math.sqrt(-Infinity) == NaN |
3742 Label done, sqrt; | 3742 Label done, sqrt; |
3743 // Check base for -Infinity. According to IEEE-754, double-precision | 3743 // Check base for -Infinity. According to IEEE-754, double-precision |
3744 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. | 3744 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. |
3745 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000)); | 3745 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000)); |
3746 __ Movq(xmm_scratch, kScratchRegister); | 3746 __ Movq(xmm_scratch, kScratchRegister); |
3747 __ ucomisd(xmm_scratch, input_reg); | 3747 __ Ucomisd(xmm_scratch, input_reg); |
3748 // Comparing -Infinity with NaN results in "unordered", which sets the | 3748 // Comparing -Infinity with NaN results in "unordered", which sets the |
3749 // zero flag as if both were equal. However, it also sets the carry flag. | 3749 // zero flag as if both were equal. However, it also sets the carry flag. |
3750 __ j(not_equal, &sqrt, Label::kNear); | 3750 __ j(not_equal, &sqrt, Label::kNear); |
3751 __ j(carry, &sqrt, Label::kNear); | 3751 __ j(carry, &sqrt, Label::kNear); |
3752 // If input is -Infinity, return Infinity. | 3752 // If input is -Infinity, return Infinity. |
3753 __ Xorpd(input_reg, input_reg); | 3753 __ Xorpd(input_reg, input_reg); |
3754 __ subsd(input_reg, xmm_scratch); | 3754 __ subsd(input_reg, xmm_scratch); |
3755 __ jmp(&done, Label::kNear); | 3755 __ jmp(&done, Label::kNear); |
3756 | 3756 |
3757 // Square root. | 3757 // Square root. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3808 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); | 3808 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); |
3809 } | 3809 } |
3810 | 3810 |
3811 | 3811 |
3812 void LCodeGen::DoMathLog(LMathLog* instr) { | 3812 void LCodeGen::DoMathLog(LMathLog* instr) { |
3813 DCHECK(instr->value()->Equals(instr->result())); | 3813 DCHECK(instr->value()->Equals(instr->result())); |
3814 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3814 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3815 XMMRegister xmm_scratch = double_scratch0(); | 3815 XMMRegister xmm_scratch = double_scratch0(); |
3816 Label positive, done, zero; | 3816 Label positive, done, zero; |
3817 __ Xorpd(xmm_scratch, xmm_scratch); | 3817 __ Xorpd(xmm_scratch, xmm_scratch); |
3818 __ ucomisd(input_reg, xmm_scratch); | 3818 __ Ucomisd(input_reg, xmm_scratch); |
3819 __ j(above, &positive, Label::kNear); | 3819 __ j(above, &positive, Label::kNear); |
3820 __ j(not_carry, &zero, Label::kNear); | 3820 __ j(not_carry, &zero, Label::kNear); |
3821 __ pcmpeqd(input_reg, input_reg); | 3821 __ pcmpeqd(input_reg, input_reg); |
3822 __ jmp(&done, Label::kNear); | 3822 __ jmp(&done, Label::kNear); |
3823 __ bind(&zero); | 3823 __ bind(&zero); |
3824 ExternalReference ninf = | 3824 ExternalReference ninf = |
3825 ExternalReference::address_of_negative_infinity(); | 3825 ExternalReference::address_of_negative_infinity(); |
3826 Operand ninf_operand = masm()->ExternalOperand(ninf); | 3826 Operand ninf_operand = masm()->ExternalOperand(ninf); |
3827 __ Movsd(input_reg, ninf_operand); | 3827 __ Movsd(input_reg, ninf_operand); |
3828 __ jmp(&done, Label::kNear); | 3828 __ jmp(&done, Label::kNear); |
(...skipping 1088 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4917 | 4917 |
4918 if (can_convert_undefined_to_nan) { | 4918 if (can_convert_undefined_to_nan) { |
4919 __ j(not_equal, &convert, Label::kNear); | 4919 __ j(not_equal, &convert, Label::kNear); |
4920 } else { | 4920 } else { |
4921 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber); | 4921 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber); |
4922 } | 4922 } |
4923 | 4923 |
4924 if (deoptimize_on_minus_zero) { | 4924 if (deoptimize_on_minus_zero) { |
4925 XMMRegister xmm_scratch = double_scratch0(); | 4925 XMMRegister xmm_scratch = double_scratch0(); |
4926 __ Xorpd(xmm_scratch, xmm_scratch); | 4926 __ Xorpd(xmm_scratch, xmm_scratch); |
4927 __ ucomisd(xmm_scratch, result_reg); | 4927 __ Ucomisd(xmm_scratch, result_reg); |
4928 __ j(not_equal, &done, Label::kNear); | 4928 __ j(not_equal, &done, Label::kNear); |
4929 __ Movmskpd(kScratchRegister, result_reg); | 4929 __ Movmskpd(kScratchRegister, result_reg); |
4930 __ testl(kScratchRegister, Immediate(1)); | 4930 __ testl(kScratchRegister, Immediate(1)); |
4931 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); | 4931 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); |
4932 } | 4932 } |
4933 __ jmp(&done, Label::kNear); | 4933 __ jmp(&done, Label::kNear); |
4934 | 4934 |
4935 if (can_convert_undefined_to_nan) { | 4935 if (can_convert_undefined_to_nan) { |
4936 __ bind(&convert); | 4936 __ bind(&convert); |
4937 | 4937 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4988 __ Set(input_reg, 0); | 4988 __ Set(input_reg, 0); |
4989 } else { | 4989 } else { |
4990 XMMRegister scratch = ToDoubleRegister(instr->temp()); | 4990 XMMRegister scratch = ToDoubleRegister(instr->temp()); |
4991 DCHECK(!scratch.is(xmm0)); | 4991 DCHECK(!scratch.is(xmm0)); |
4992 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 4992 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
4993 Heap::kHeapNumberMapRootIndex); | 4993 Heap::kHeapNumberMapRootIndex); |
4994 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber); | 4994 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber); |
4995 __ Movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 4995 __ Movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
4996 __ Cvttsd2si(input_reg, xmm0); | 4996 __ Cvttsd2si(input_reg, xmm0); |
4997 __ Cvtlsi2sd(scratch, input_reg); | 4997 __ Cvtlsi2sd(scratch, input_reg); |
4998 __ ucomisd(xmm0, scratch); | 4998 __ Ucomisd(xmm0, scratch); |
4999 DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision); | 4999 DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision); |
5000 DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN); | 5000 DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN); |
5001 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { | 5001 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { |
5002 __ testl(input_reg, input_reg); | 5002 __ testl(input_reg, input_reg); |
5003 __ j(not_zero, done); | 5003 __ j(not_zero, done); |
5004 __ Movmskpd(input_reg, xmm0); | 5004 __ Movmskpd(input_reg, xmm0); |
5005 __ andl(input_reg, Immediate(1)); | 5005 __ andl(input_reg, Immediate(1)); |
5006 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); | 5006 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); |
5007 } | 5007 } |
5008 } | 5008 } |
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5904 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5904 RecordSafepoint(Safepoint::kNoLazyDeopt); |
5905 } | 5905 } |
5906 | 5906 |
5907 | 5907 |
5908 #undef __ | 5908 #undef __ |
5909 | 5909 |
5910 } // namespace internal | 5910 } // namespace internal |
5911 } // namespace v8 | 5911 } // namespace v8 |
5912 | 5912 |
5913 #endif // V8_TARGET_ARCH_X64 | 5913 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |