| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 2222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2233 __ ucomisd(xmm_scratch, value); | 2233 __ ucomisd(xmm_scratch, value); |
| 2234 EmitFalseBranch(instr, not_equal); | 2234 EmitFalseBranch(instr, not_equal); |
| 2235 __ movmskpd(kScratchRegister, value); | 2235 __ movmskpd(kScratchRegister, value); |
| 2236 __ testl(kScratchRegister, Immediate(1)); | 2236 __ testl(kScratchRegister, Immediate(1)); |
| 2237 EmitBranch(instr, not_zero); | 2237 EmitBranch(instr, not_zero); |
| 2238 } else { | 2238 } else { |
| 2239 Register value = ToRegister(instr->value()); | 2239 Register value = ToRegister(instr->value()); |
| 2240 Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); | 2240 Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); |
| 2241 __ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK); | 2241 __ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK); |
| 2242 __ cmpl(FieldOperand(value, HeapNumber::kExponentOffset), | 2242 __ cmpl(FieldOperand(value, HeapNumber::kExponentOffset), |
| 2243 Immediate(0x80000000)); | 2243 Immediate(0x1)); |
| 2244 EmitFalseBranch(instr, not_equal); | 2244 EmitFalseBranch(instr, no_overflow); |
| 2245 __ cmpl(FieldOperand(value, HeapNumber::kMantissaOffset), | 2245 __ cmpl(FieldOperand(value, HeapNumber::kMantissaOffset), |
| 2246 Immediate(0x00000000)); | 2246 Immediate(0x00000000)); |
| 2247 EmitBranch(instr, equal); | 2247 EmitBranch(instr, equal); |
| 2248 } | 2248 } |
| 2249 } | 2249 } |
| 2250 | 2250 |
| 2251 | 2251 |
| 2252 Condition LCodeGen::EmitIsObject(Register input, | 2252 Condition LCodeGen::EmitIsObject(Register input, |
| 2253 Label* is_not_object, | 2253 Label* is_not_object, |
| 2254 Label* is_object) { | 2254 Label* is_object) { |
| (...skipping 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3549 if (CpuFeatures::IsSupported(SSE4_1)) { | 3549 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 3550 CpuFeatureScope scope(masm(), SSE4_1); | 3550 CpuFeatureScope scope(masm(), SSE4_1); |
| 3551 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3551 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3552 // Deoptimize if minus zero. | 3552 // Deoptimize if minus zero. |
| 3553 __ movq(output_reg, input_reg); | 3553 __ movq(output_reg, input_reg); |
| 3554 __ subq(output_reg, Immediate(1)); | 3554 __ subq(output_reg, Immediate(1)); |
| 3555 DeoptimizeIf(overflow, instr->environment()); | 3555 DeoptimizeIf(overflow, instr->environment()); |
| 3556 } | 3556 } |
| 3557 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); | 3557 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); |
| 3558 __ cvttsd2si(output_reg, xmm_scratch); | 3558 __ cvttsd2si(output_reg, xmm_scratch); |
| 3559 __ cmpl(output_reg, Immediate(0x80000000)); | 3559 __ cmpl(output_reg, Immediate(0x1)); |
| 3560 DeoptimizeIf(equal, instr->environment()); | 3560 DeoptimizeIf(overflow, instr->environment()); |
| 3561 } else { | 3561 } else { |
| 3562 Label negative_sign, done; | 3562 Label negative_sign, done; |
| 3563 // Deoptimize on unordered. | 3563 // Deoptimize on unordered. |
| 3564 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. | 3564 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. |
| 3565 __ ucomisd(input_reg, xmm_scratch); | 3565 __ ucomisd(input_reg, xmm_scratch); |
| 3566 DeoptimizeIf(parity_even, instr->environment()); | 3566 DeoptimizeIf(parity_even, instr->environment()); |
| 3567 __ j(below, &negative_sign, Label::kNear); | 3567 __ j(below, &negative_sign, Label::kNear); |
| 3568 | 3568 |
| 3569 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3569 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3570 // Check for negative zero. | 3570 // Check for negative zero. |
| 3571 Label positive_sign; | 3571 Label positive_sign; |
| 3572 __ j(above, &positive_sign, Label::kNear); | 3572 __ j(above, &positive_sign, Label::kNear); |
| 3573 __ movmskpd(output_reg, input_reg); | 3573 __ movmskpd(output_reg, input_reg); |
| 3574 __ testq(output_reg, Immediate(1)); | 3574 __ testq(output_reg, Immediate(1)); |
| 3575 DeoptimizeIf(not_zero, instr->environment()); | 3575 DeoptimizeIf(not_zero, instr->environment()); |
| 3576 __ Set(output_reg, 0); | 3576 __ Set(output_reg, 0); |
| 3577 __ jmp(&done, Label::kNear); | 3577 __ jmp(&done, Label::kNear); |
| 3578 __ bind(&positive_sign); | 3578 __ bind(&positive_sign); |
| 3579 } | 3579 } |
| 3580 | 3580 |
| 3581 // Use truncating instruction (OK because input is positive). | 3581 // Use truncating instruction (OK because input is positive). |
| 3582 __ cvttsd2si(output_reg, input_reg); | 3582 __ cvttsd2si(output_reg, input_reg); |
| 3583 // Overflow is signalled with minint. | 3583 // Overflow is signalled with minint. |
| 3584 __ cmpl(output_reg, Immediate(0x80000000)); | 3584 __ cmpl(output_reg, Immediate(0x1)); |
| 3585 DeoptimizeIf(equal, instr->environment()); | 3585 DeoptimizeIf(overflow, instr->environment()); |
| 3586 __ jmp(&done, Label::kNear); | 3586 __ jmp(&done, Label::kNear); |
| 3587 | 3587 |
| 3588 // Non-zero negative reaches here. | 3588 // Non-zero negative reaches here. |
| 3589 __ bind(&negative_sign); | 3589 __ bind(&negative_sign); |
| 3590 // Truncate, then compare and compensate. | 3590 // Truncate, then compare and compensate. |
| 3591 __ cvttsd2si(output_reg, input_reg); | 3591 __ cvttsd2si(output_reg, input_reg); |
| 3592 __ Cvtlsi2sd(xmm_scratch, output_reg); | 3592 __ Cvtlsi2sd(xmm_scratch, output_reg); |
| 3593 __ ucomisd(input_reg, xmm_scratch); | 3593 __ ucomisd(input_reg, xmm_scratch); |
| 3594 __ j(equal, &done, Label::kNear); | 3594 __ j(equal, &done, Label::kNear); |
| 3595 __ subl(output_reg, Immediate(1)); | 3595 __ subl(output_reg, Immediate(1)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3612 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; | 3612 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
| 3613 __ movq(kScratchRegister, one_half); | 3613 __ movq(kScratchRegister, one_half); |
| 3614 __ movq(xmm_scratch, kScratchRegister); | 3614 __ movq(xmm_scratch, kScratchRegister); |
| 3615 __ ucomisd(xmm_scratch, input_reg); | 3615 __ ucomisd(xmm_scratch, input_reg); |
| 3616 __ j(above, &below_one_half, Label::kNear); | 3616 __ j(above, &below_one_half, Label::kNear); |
| 3617 | 3617 |
| 3618 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). | 3618 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). |
| 3619 __ addsd(xmm_scratch, input_reg); | 3619 __ addsd(xmm_scratch, input_reg); |
| 3620 __ cvttsd2si(output_reg, xmm_scratch); | 3620 __ cvttsd2si(output_reg, xmm_scratch); |
| 3621 // Overflow is signalled with minint. | 3621 // Overflow is signalled with minint. |
| 3622 __ cmpl(output_reg, Immediate(0x80000000)); | 3622 __ cmpl(output_reg, Immediate(0x1)); |
| 3623 __ RecordComment("D2I conversion overflow"); | 3623 __ RecordComment("D2I conversion overflow"); |
| 3624 DeoptimizeIf(equal, instr->environment()); | 3624 DeoptimizeIf(overflow, instr->environment()); |
| 3625 __ jmp(&done, dist); | 3625 __ jmp(&done, dist); |
| 3626 | 3626 |
| 3627 __ bind(&below_one_half); | 3627 __ bind(&below_one_half); |
| 3628 __ movq(kScratchRegister, minus_one_half); | 3628 __ movq(kScratchRegister, minus_one_half); |
| 3629 __ movq(xmm_scratch, kScratchRegister); | 3629 __ movq(xmm_scratch, kScratchRegister); |
| 3630 __ ucomisd(xmm_scratch, input_reg); | 3630 __ ucomisd(xmm_scratch, input_reg); |
| 3631 __ j(below_equal, &round_to_zero, Label::kNear); | 3631 __ j(below_equal, &round_to_zero, Label::kNear); |
| 3632 | 3632 |
| 3633 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then | 3633 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then |
| 3634 // compare and compensate. | 3634 // compare and compensate. |
| 3635 __ movq(input_temp, input_reg); // Do not alter input_reg. | 3635 __ movq(input_temp, input_reg); // Do not alter input_reg. |
| 3636 __ subsd(input_temp, xmm_scratch); | 3636 __ subsd(input_temp, xmm_scratch); |
| 3637 __ cvttsd2si(output_reg, input_temp); | 3637 __ cvttsd2si(output_reg, input_temp); |
| 3638 // Catch minint due to overflow, and to prevent overflow when compensating. | 3638 // Catch minint due to overflow, and to prevent overflow when compensating. |
| 3639 __ cmpl(output_reg, Immediate(0x80000000)); | 3639 __ cmpl(output_reg, Immediate(0x1)); |
| 3640 __ RecordComment("D2I conversion overflow"); | 3640 __ RecordComment("D2I conversion overflow"); |
| 3641 DeoptimizeIf(equal, instr->environment()); | 3641 DeoptimizeIf(overflow, instr->environment()); |
| 3642 | 3642 |
| 3643 __ Cvtlsi2sd(xmm_scratch, output_reg); | 3643 __ Cvtlsi2sd(xmm_scratch, output_reg); |
| 3644 __ ucomisd(xmm_scratch, input_temp); | 3644 __ ucomisd(xmm_scratch, input_temp); |
| 3645 __ j(equal, &done, dist); | 3645 __ j(equal, &done, dist); |
| 3646 __ subl(output_reg, Immediate(1)); | 3646 __ subl(output_reg, Immediate(1)); |
| 3647 // No overflow because we already ruled out minint. | 3647 // No overflow because we already ruled out minint. |
| 3648 __ jmp(&done, dist); | 3648 __ jmp(&done, dist); |
| 3649 | 3649 |
| 3650 __ bind(&round_to_zero); | 3650 __ bind(&round_to_zero); |
| 3651 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if | 3651 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if |
| (...skipping 1012 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4664 __ movp(reg, kScratchRegister); | 4664 __ movp(reg, kScratchRegister); |
| 4665 } | 4665 } |
| 4666 | 4666 |
| 4667 | 4667 |
| 4668 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4668 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 4669 HChange* hchange = instr->hydrogen(); | 4669 HChange* hchange = instr->hydrogen(); |
| 4670 Register input = ToRegister(instr->value()); | 4670 Register input = ToRegister(instr->value()); |
| 4671 Register output = ToRegister(instr->result()); | 4671 Register output = ToRegister(instr->result()); |
| 4672 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4672 if (hchange->CheckFlag(HValue::kCanOverflow) && |
| 4673 hchange->value()->CheckFlag(HValue::kUint32)) { | 4673 hchange->value()->CheckFlag(HValue::kUint32)) { |
| 4674 __ testl(input, Immediate(0x80000000)); | 4674 __ testl(input, input); |
| 4675 DeoptimizeIf(not_zero, instr->environment()); | 4675 DeoptimizeIf(sign, instr->environment()); |
| 4676 } | 4676 } |
| 4677 __ Integer32ToSmi(output, input); | 4677 __ Integer32ToSmi(output, input); |
| 4678 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4678 if (hchange->CheckFlag(HValue::kCanOverflow) && |
| 4679 !hchange->value()->CheckFlag(HValue::kUint32)) { | 4679 !hchange->value()->CheckFlag(HValue::kUint32)) { |
| 4680 DeoptimizeIf(overflow, instr->environment()); | 4680 DeoptimizeIf(overflow, instr->environment()); |
| 4681 } | 4681 } |
| 4682 } | 4682 } |
| 4683 | 4683 |
| 4684 | 4684 |
| 4685 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 4685 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5060 | 5060 |
| 5061 // Check for heap number | 5061 // Check for heap number |
| 5062 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 5062 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 5063 factory()->heap_number_map()); | 5063 factory()->heap_number_map()); |
| 5064 __ j(equal, &heap_number, Label::kNear); | 5064 __ j(equal, &heap_number, Label::kNear); |
| 5065 | 5065 |
| 5066 // Check for undefined. Undefined is converted to zero for clamping | 5066 // Check for undefined. Undefined is converted to zero for clamping |
| 5067 // conversions. | 5067 // conversions. |
| 5068 __ Cmp(input_reg, factory()->undefined_value()); | 5068 __ Cmp(input_reg, factory()->undefined_value()); |
| 5069 DeoptimizeIf(not_equal, instr->environment()); | 5069 DeoptimizeIf(not_equal, instr->environment()); |
| 5070 __ movp(input_reg, Immediate(0)); | 5070 __ xorl(input_reg, input_reg); |
| 5071 __ jmp(&done, Label::kNear); | 5071 __ jmp(&done, Label::kNear); |
| 5072 | 5072 |
| 5073 // Heap number | 5073 // Heap number |
| 5074 __ bind(&heap_number); | 5074 __ bind(&heap_number); |
| 5075 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 5075 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 5076 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); | 5076 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); |
| 5077 __ jmp(&done, Label::kNear); | 5077 __ jmp(&done, Label::kNear); |
| 5078 | 5078 |
| 5079 // smi | 5079 // smi |
| 5080 __ bind(&is_smi); | 5080 __ bind(&is_smi); |
| (...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5642 FixedArray::kHeaderSize - kPointerSize)); | 5642 FixedArray::kHeaderSize - kPointerSize)); |
| 5643 __ bind(&done); | 5643 __ bind(&done); |
| 5644 } | 5644 } |
| 5645 | 5645 |
| 5646 | 5646 |
| 5647 #undef __ | 5647 #undef __ |
| 5648 | 5648 |
| 5649 } } // namespace v8::internal | 5649 } } // namespace v8::internal |
| 5650 | 5650 |
| 5651 #endif // V8_TARGET_ARCH_X64 | 5651 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |