| 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 1868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1879 __ j(cc, chunk_->GetAssemblyLabel(left_block)); | 1879 __ j(cc, chunk_->GetAssemblyLabel(left_block)); |
| 1880 } else { | 1880 } else { |
| 1881 __ j(cc, chunk_->GetAssemblyLabel(left_block)); | 1881 __ j(cc, chunk_->GetAssemblyLabel(left_block)); |
| 1882 if (cc != always) { | 1882 if (cc != always) { |
| 1883 __ jmp(chunk_->GetAssemblyLabel(right_block)); | 1883 __ jmp(chunk_->GetAssemblyLabel(right_block)); |
| 1884 } | 1884 } |
| 1885 } | 1885 } |
| 1886 } | 1886 } |
| 1887 | 1887 |
| 1888 | 1888 |
| 1889 template<class InstrType> |
| 1890 void LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) { |
| 1891 int false_block = instr->FalseDestination(chunk_); |
| 1892 __ j(cc, chunk_->GetAssemblyLabel(false_block)); |
| 1893 } |
| 1894 |
| 1895 |
| 1889 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 1896 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
| 1890 __ int3(); | 1897 __ int3(); |
| 1891 } | 1898 } |
| 1892 | 1899 |
| 1893 | 1900 |
| 1894 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { | 1901 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { |
| 1895 Representation r = instr->hydrogen()->value()->representation(); | 1902 Representation r = instr->hydrogen()->value()->representation(); |
| 1896 if (r.IsSmiOrInteger32() || r.IsDouble()) { | 1903 if (r.IsSmiOrInteger32() || r.IsDouble()) { |
| 1897 EmitBranch(instr, no_condition); | 1904 EmitBranch(instr, no_condition); |
| 1898 } else { | 1905 } else { |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2152 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); | 2159 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); |
| 2153 __ CmpObject(left, right); | 2160 __ CmpObject(left, right); |
| 2154 } else { | 2161 } else { |
| 2155 Register right = ToRegister(instr->right()); | 2162 Register right = ToRegister(instr->right()); |
| 2156 __ cmpq(left, right); | 2163 __ cmpq(left, right); |
| 2157 } | 2164 } |
| 2158 EmitBranch(instr, equal); | 2165 EmitBranch(instr, equal); |
| 2159 } | 2166 } |
| 2160 | 2167 |
| 2161 | 2168 |
| 2169 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { |
| 2170 if (instr->hydrogen()->representation().IsTagged()) { |
| 2171 Register input_reg = ToRegister(instr->object()); |
| 2172 __ Cmp(input_reg, factory()->the_hole_value()); |
| 2173 EmitBranch(instr, equal); |
| 2174 return; |
| 2175 } |
| 2176 |
| 2177 XMMRegister input_reg = ToDoubleRegister(instr->object()); |
| 2178 __ ucomisd(input_reg, input_reg); |
| 2179 EmitFalseBranch(instr, parity_odd); |
| 2180 |
| 2181 __ subq(rsp, Immediate(kDoubleSize)); |
| 2182 __ movsd(MemOperand(rsp, 0), input_reg); |
| 2183 __ addq(rsp, Immediate(kDoubleSize)); |
| 2184 |
| 2185 int size = sizeof(kHoleNanUpper32); |
| 2186 __ cmpl(MemOperand(rsp, -size), |
| 2187 Immediate(kHoleNanUpper32)); |
| 2188 EmitBranch(instr, equal); |
| 2189 } |
| 2190 |
| 2191 |
| 2162 Condition LCodeGen::EmitIsObject(Register input, | 2192 Condition LCodeGen::EmitIsObject(Register input, |
| 2163 Label* is_not_object, | 2193 Label* is_not_object, |
| 2164 Label* is_object) { | 2194 Label* is_object) { |
| 2165 ASSERT(!input.is(kScratchRegister)); | 2195 ASSERT(!input.is(kScratchRegister)); |
| 2166 | 2196 |
| 2167 __ JumpIfSmi(input, is_not_object); | 2197 __ JumpIfSmi(input, is_not_object); |
| 2168 | 2198 |
| 2169 __ CompareRoot(input, Heap::kNullValueRootIndex); | 2199 __ CompareRoot(input, Heap::kNullValueRootIndex); |
| 2170 __ j(equal, is_object); | 2200 __ j(equal, is_object); |
| 2171 | 2201 |
| (...skipping 2430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4602 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 4632 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
| 4603 virtual LInstruction* instr() { return instr_; } | 4633 virtual LInstruction* instr() { return instr_; } |
| 4604 private: | 4634 private: |
| 4605 LNumberTagD* instr_; | 4635 LNumberTagD* instr_; |
| 4606 }; | 4636 }; |
| 4607 | 4637 |
| 4608 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 4638 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 4609 Register reg = ToRegister(instr->result()); | 4639 Register reg = ToRegister(instr->result()); |
| 4610 Register tmp = ToRegister(instr->temp()); | 4640 Register tmp = ToRegister(instr->temp()); |
| 4611 | 4641 |
| 4612 bool convert_hole = false; | |
| 4613 HValue* change_input = instr->hydrogen()->value(); | |
| 4614 if (change_input->IsLoadKeyed()) { | |
| 4615 HLoadKeyed* load = HLoadKeyed::cast(change_input); | |
| 4616 convert_hole = load->UsesMustHandleHole(); | |
| 4617 } | |
| 4618 | |
| 4619 Label no_special_nan_handling; | |
| 4620 Label done; | |
| 4621 if (convert_hole) { | |
| 4622 XMMRegister input_reg = ToDoubleRegister(instr->value()); | |
| 4623 __ ucomisd(input_reg, input_reg); | |
| 4624 __ j(parity_odd, &no_special_nan_handling); | |
| 4625 __ subq(rsp, Immediate(kDoubleSize)); | |
| 4626 __ movsd(MemOperand(rsp, 0), input_reg); | |
| 4627 __ cmpl(MemOperand(rsp, sizeof(kHoleNanLower32)), | |
| 4628 Immediate(kHoleNanUpper32)); | |
| 4629 Label canonicalize; | |
| 4630 __ j(not_equal, &canonicalize); | |
| 4631 __ addq(rsp, Immediate(kDoubleSize)); | |
| 4632 __ Move(reg, factory()->the_hole_value()); | |
| 4633 __ jmp(&done); | |
| 4634 __ bind(&canonicalize); | |
| 4635 __ addq(rsp, Immediate(kDoubleSize)); | |
| 4636 __ Set(kScratchRegister, BitCast<uint64_t>( | |
| 4637 FixedDoubleArray::canonical_not_the_hole_nan_as_double())); | |
| 4638 __ movq(input_reg, kScratchRegister); | |
| 4639 } | |
| 4640 | |
| 4641 __ bind(&no_special_nan_handling); | |
| 4642 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4642 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
| 4643 if (FLAG_inline_new) { | 4643 if (FLAG_inline_new) { |
| 4644 __ AllocateHeapNumber(reg, tmp, deferred->entry()); | 4644 __ AllocateHeapNumber(reg, tmp, deferred->entry()); |
| 4645 } else { | 4645 } else { |
| 4646 __ jmp(deferred->entry()); | 4646 __ jmp(deferred->entry()); |
| 4647 } | 4647 } |
| 4648 __ bind(deferred->exit()); | 4648 __ bind(deferred->exit()); |
| 4649 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); | 4649 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); |
| 4650 | |
| 4651 __ bind(&done); | |
| 4652 } | 4650 } |
| 4653 | 4651 |
| 4654 | 4652 |
| 4655 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4653 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 4656 // TODO(3095996): Get rid of this. For now, we need to make the | 4654 // TODO(3095996): Get rid of this. For now, we need to make the |
| 4657 // result register contain a valid pointer because it is already | 4655 // result register contain a valid pointer because it is already |
| 4658 // contained in the register pointer map. | 4656 // contained in the register pointer map. |
| 4659 Register reg = ToRegister(instr->result()); | 4657 Register reg = ToRegister(instr->result()); |
| 4660 __ Move(reg, Smi::FromInt(0)); | 4658 __ Move(reg, Smi::FromInt(0)); |
| 4661 | 4659 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 4685 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); | 4683 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); |
| 4686 } else { | 4684 } else { |
| 4687 __ AssertSmi(input); | 4685 __ AssertSmi(input); |
| 4688 } | 4686 } |
| 4689 __ SmiToInteger32(input, input); | 4687 __ SmiToInteger32(input, input); |
| 4690 } | 4688 } |
| 4691 | 4689 |
| 4692 | 4690 |
| 4693 void LCodeGen::EmitNumberUntagD(Register input_reg, | 4691 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| 4694 XMMRegister result_reg, | 4692 XMMRegister result_reg, |
| 4695 bool allow_undefined_as_nan, | 4693 bool can_convert_undefined_to_nan, |
| 4696 bool deoptimize_on_minus_zero, | 4694 bool deoptimize_on_minus_zero, |
| 4697 LEnvironment* env, | 4695 LEnvironment* env, |
| 4698 NumberUntagDMode mode) { | 4696 NumberUntagDMode mode) { |
| 4699 Label load_smi, done; | 4697 Label load_smi, done; |
| 4700 | 4698 |
| 4701 STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE > | 4699 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
| 4702 NUMBER_CANDIDATE_IS_ANY_TAGGED); | |
| 4703 if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) { | |
| 4704 // Smi check. | 4700 // Smi check. |
| 4705 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); | 4701 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); |
| 4706 | 4702 |
| 4707 // Heap number map check. | 4703 // Heap number map check. |
| 4708 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 4704 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 4709 Heap::kHeapNumberMapRootIndex); | 4705 Heap::kHeapNumberMapRootIndex); |
| 4710 if (!allow_undefined_as_nan) { | 4706 if (!can_convert_undefined_to_nan) { |
| 4711 DeoptimizeIf(not_equal, env); | 4707 DeoptimizeIf(not_equal, env); |
| 4712 } else { | 4708 } else { |
| 4713 Label heap_number, convert; | 4709 Label heap_number, convert; |
| 4714 __ j(equal, &heap_number, Label::kNear); | 4710 __ j(equal, &heap_number, Label::kNear); |
| 4715 | 4711 |
| 4716 // Convert undefined (and hole) to NaN. Compute NaN as 0/0. | 4712 // Convert undefined (and hole) to NaN. Compute NaN as 0/0. |
| 4717 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); | 4713 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
| 4718 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) { | |
| 4719 __ j(equal, &convert, Label::kNear); | |
| 4720 __ CompareRoot(input_reg, Heap::kTheHoleValueRootIndex); | |
| 4721 } | |
| 4722 DeoptimizeIf(not_equal, env); | 4714 DeoptimizeIf(not_equal, env); |
| 4723 | 4715 |
| 4724 __ bind(&convert); | 4716 __ bind(&convert); |
| 4725 __ xorps(result_reg, result_reg); | 4717 __ xorps(result_reg, result_reg); |
| 4726 __ divsd(result_reg, result_reg); | 4718 __ divsd(result_reg, result_reg); |
| 4727 __ jmp(&done, Label::kNear); | 4719 __ jmp(&done, Label::kNear); |
| 4728 | 4720 |
| 4729 __ bind(&heap_number); | 4721 __ bind(&heap_number); |
| 4730 } | 4722 } |
| 4731 // Heap number to XMM conversion. | 4723 // Heap number to XMM conversion. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4824 | 4816 |
| 4825 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 4817 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 4826 LOperand* input = instr->value(); | 4818 LOperand* input = instr->value(); |
| 4827 ASSERT(input->IsRegister()); | 4819 ASSERT(input->IsRegister()); |
| 4828 LOperand* result = instr->result(); | 4820 LOperand* result = instr->result(); |
| 4829 ASSERT(result->IsDoubleRegister()); | 4821 ASSERT(result->IsDoubleRegister()); |
| 4830 | 4822 |
| 4831 Register input_reg = ToRegister(input); | 4823 Register input_reg = ToRegister(input); |
| 4832 XMMRegister result_reg = ToDoubleRegister(result); | 4824 XMMRegister result_reg = ToDoubleRegister(result); |
| 4833 | 4825 |
| 4834 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED; | |
| 4835 HValue* value = instr->hydrogen()->value(); | 4826 HValue* value = instr->hydrogen()->value(); |
| 4836 if (value->type().IsSmi()) { | 4827 NumberUntagDMode mode = value->representation().IsSmi() |
| 4837 mode = NUMBER_CANDIDATE_IS_SMI; | 4828 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; |
| 4838 } else if (value->IsLoadKeyed()) { | |
| 4839 HLoadKeyed* load = HLoadKeyed::cast(value); | |
| 4840 if (load->UsesMustHandleHole()) { | |
| 4841 mode = NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE; | |
| 4842 } | |
| 4843 } | |
| 4844 | 4829 |
| 4845 EmitNumberUntagD(input_reg, result_reg, | 4830 EmitNumberUntagD(input_reg, result_reg, |
| 4846 instr->hydrogen()->allow_undefined_as_nan(), | 4831 instr->hydrogen()->can_convert_undefined_to_nan(), |
| 4847 instr->hydrogen()->deoptimize_on_minus_zero(), | 4832 instr->hydrogen()->deoptimize_on_minus_zero(), |
| 4848 instr->environment(), | 4833 instr->environment(), |
| 4849 mode); | 4834 mode); |
| 4850 } | 4835 } |
| 4851 | 4836 |
| 4852 | 4837 |
| 4853 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 4838 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 4854 LOperand* input = instr->value(); | 4839 LOperand* input = instr->value(); |
| 4855 ASSERT(input->IsDoubleRegister()); | 4840 ASSERT(input->IsDoubleRegister()); |
| 4856 LOperand* result = instr->result(); | 4841 LOperand* result = instr->result(); |
| (...skipping 760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5617 FixedArray::kHeaderSize - kPointerSize)); | 5602 FixedArray::kHeaderSize - kPointerSize)); |
| 5618 __ bind(&done); | 5603 __ bind(&done); |
| 5619 } | 5604 } |
| 5620 | 5605 |
| 5621 | 5606 |
| 5622 #undef __ | 5607 #undef __ |
| 5623 | 5608 |
| 5624 } } // namespace v8::internal | 5609 } } // namespace v8::internal |
| 5625 | 5610 |
| 5626 #endif // V8_TARGET_ARCH_X64 | 5611 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |