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 |