OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 dest->Split(not_equal); | 735 dest->Split(not_equal); |
736 } | 736 } |
737 | 737 |
738 | 738 |
739 class FloatingPointHelper : public AllStatic { | 739 class FloatingPointHelper : public AllStatic { |
740 public: | 740 public: |
741 // Code pattern for loading a floating point value. Input value must | 741 // Code pattern for loading a floating point value. Input value must |
742 // be either a smi or a heap number object (fp value). Requirements: | 742 // be either a smi or a heap number object (fp value). Requirements: |
743 // operand in register number. Returns operand as floating point number | 743 // operand in register number. Returns operand as floating point number |
744 // on FPU stack. | 744 // on FPU stack. |
745 static void LoadFloatOperand(MacroAssembler* masm, Register number); | 745 static void LoadFloatOperand(MacroAssembler* masm, |
| 746 Register number, |
| 747 Register scratch); |
746 // Code pattern for loading floating point values. Input values must | 748 // Code pattern for loading floating point values. Input values must |
747 // be either smi or heap number objects (fp values). Requirements: | 749 // be either smi or heap number objects (fp values). Requirements: |
748 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as | 750 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as |
749 // floating point numbers on FPU stack. | 751 // floating point numbers on FPU stack. |
750 static void LoadFloatOperands(MacroAssembler* masm, Register scratch); | 752 static void LoadFloatOperands(MacroAssembler* masm, Register scratch); |
751 // Test if operands are smi or number objects (fp). Requirements: | 753 // Test if operands are smi or number objects (fp). Requirements: |
752 // operand_1 in eax, operand_2 in edx; falls through on float | 754 // operand_1 in eax, operand_2 in edx; falls through on float |
753 // operands, jumps to the non_float label otherwise. | 755 // operands, jumps to the non_float label otherwise. |
754 static void CheckFloatOperands(MacroAssembler* masm, | 756 static void CheckFloatOperands(MacroAssembler* masm, |
755 Label* non_float, | 757 Label* non_float, |
756 Register scratch); | 758 Register scratch); |
757 // Test if operands are numbers (smi or HeapNumber objects), and load | 759 // Test if operands are numbers (smi or HeapNumber objects), and load |
758 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if | 760 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if |
759 // either operand is not a number. Operands are in edx and eax. | 761 // either operand is not a number. Operands are in edx and eax. |
760 // Leaves operands unchanged. | 762 // Leaves operands unchanged. |
761 static void LoadSse2Operands(MacroAssembler* masm, Label* not_numbers); | 763 static void LoadSse2Operands(MacroAssembler* masm, Register scratch, Label* no
t_numbers); |
762 }; | 764 }; |
763 | 765 |
764 | 766 |
765 const char* GenericBinaryOpStub::GetName() { | 767 const char* GenericBinaryOpStub::GetName() { |
| 768 bool smi = (flags_ & NO_SMI_CODE_IN_STUB) == 0; |
766 switch (op_) { | 769 switch (op_) { |
767 case Token::ADD: return "GenericBinaryOpStub_ADD"; | 770 case Token::ADD: |
768 case Token::SUB: return "GenericBinaryOpStub_SUB"; | 771 return smi ? "GenericBinaryOpStub_ADD_Smi" : "GenericBinaryOpStub_ADD"; |
769 case Token::MUL: return "GenericBinaryOpStub_MUL"; | 772 case Token::SUB: |
770 case Token::DIV: return "GenericBinaryOpStub_DIV"; | 773 return smi ? "GenericBinaryOpStub_SUB_Smi" : "GenericBinaryOpStub_SUB"; |
771 case Token::BIT_OR: return "GenericBinaryOpStub_BIT_OR"; | 774 case Token::MUL: |
772 case Token::BIT_AND: return "GenericBinaryOpStub_BIT_AND"; | 775 return smi ? "GenericBinaryOpStub_MUL_Smi" : "GenericBinaryOpStub_MUL"; |
773 case Token::BIT_XOR: return "GenericBinaryOpStub_BIT_XOR"; | 776 case Token::DIV: |
774 case Token::SAR: return "GenericBinaryOpStub_SAR"; | 777 return smi ? "GenericBinaryOpStub_DIV_Smi" : "GenericBinaryOpStub_DIV"; |
775 case Token::SHL: return "GenericBinaryOpStub_SHL"; | 778 case Token::BIT_OR: |
776 case Token::SHR: return "GenericBinaryOpStub_SHR"; | 779 return smi ? |
777 default: return "GenericBinaryOpStub"; | 780 "GenericBinaryOpStub_BIT_OR_Smi" : |
| 781 "GenericBinaryOpStub_BIT_OR"; |
| 782 case Token::BIT_AND: |
| 783 return smi ? |
| 784 "GenericBinaryOpStub_BIT_AND_Smi" : |
| 785 "GenericBinaryOpStub_BIT_AND"; |
| 786 case Token::BIT_XOR: |
| 787 return smi ? |
| 788 "GenericBinaryOpStub_BIT_XOR_Smi" : |
| 789 "GenericBinaryOpStub_BIT_XOR"; |
| 790 case Token::SAR: |
| 791 return smi ? "GenericBinaryOpStub_SAR_Smi" : "GenericBinaryOpStub_SAR"; |
| 792 case Token::SHL: |
| 793 return smi ? "GenericBinaryOpStub_SHL_Smi" : "GenericBinaryOpStub_SHL"; |
| 794 case Token::SHR: |
| 795 return smi ? "GenericBinaryOpStub_SHR_Smi" : "GenericBinaryOpStub_SHR"; |
| 796 default: |
| 797 return "GenericBinaryOpStub"; |
778 } | 798 } |
779 } | 799 } |
780 | 800 |
781 | 801 |
782 // Call the specialized stub for a binary operation. | 802 // Call the specialized stub for a binary operation. |
783 class DeferredInlineBinaryOperation: public DeferredCode { | 803 class DeferredInlineBinaryOperation: public DeferredCode { |
784 public: | 804 public: |
785 DeferredInlineBinaryOperation(Token::Value op, | 805 DeferredInlineBinaryOperation(Token::Value op, |
786 Register dst, | 806 Register dst, |
787 Register left, | 807 Register left, |
(...skipping 4359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5147 JumpTarget done; | 5167 JumpTarget done; |
5148 JumpTarget call_runtime; | 5168 JumpTarget call_runtime; |
5149 ASSERT(args->length() == 1); | 5169 ASSERT(args->length() == 1); |
5150 | 5170 |
5151 // Load number and duplicate it. | 5171 // Load number and duplicate it. |
5152 Load(args->at(0)); | 5172 Load(args->at(0)); |
5153 frame_->Dup(); | 5173 frame_->Dup(); |
5154 | 5174 |
5155 // Get the number into an unaliased register and load it onto the | 5175 // Get the number into an unaliased register and load it onto the |
5156 // floating point stack still leaving one copy on the frame. | 5176 // floating point stack still leaving one copy on the frame. |
| 5177 Result scratch = allocator_->Allocate(); |
| 5178 ASSERT(scratch.is_valid()); |
5157 Result number = frame_->Pop(); | 5179 Result number = frame_->Pop(); |
5158 number.ToRegister(); | 5180 number.ToRegister(); |
5159 frame_->Spill(number.reg()); | 5181 frame_->Spill(number.reg()); |
5160 FloatingPointHelper::LoadFloatOperand(masm_, number.reg()); | 5182 FloatingPointHelper::LoadFloatOperand(masm_, number.reg(), scratch.reg()); |
5161 number.Unuse(); | 5183 number.Unuse(); |
| 5184 scratch.Unuse(); |
5162 | 5185 |
5163 // Perform the operation on the number. | 5186 // Perform the operation on the number. |
5164 switch (op) { | 5187 switch (op) { |
5165 case SIN: | 5188 case SIN: |
5166 __ fsin(); | 5189 __ fsin(); |
5167 break; | 5190 break; |
5168 case COS: | 5191 case COS: |
5169 __ fcos(); | 5192 __ fcos(); |
5170 break; | 5193 break; |
5171 } | 5194 } |
5172 | 5195 |
5173 // Go slow case if argument to operation is out of range. | 5196 // Go slow case if argument to operation is out of range. |
5174 Result eax_reg = allocator_->Allocate(eax); | 5197 Result eax_reg = allocator_->Allocate(eax); |
5175 ASSERT(eax_reg.is_valid()); | 5198 ASSERT(eax_reg.is_valid()); |
5176 __ fnstsw_ax(); | 5199 __ fnstsw_ax(); |
5177 __ sahf(); | 5200 __ sahf(); |
5178 eax_reg.Unuse(); | 5201 eax_reg.Unuse(); |
5179 call_runtime.Branch(parity_even, not_taken); | 5202 call_runtime.Branch(parity_even, not_taken); |
5180 | 5203 |
5181 // Allocate heap number for result if possible. | 5204 // Allocate heap number for result if possible. |
5182 Result scratch1 = allocator()->Allocate(); | 5205 Result scratch1 = allocator()->Allocate(); |
5183 Result scratch2 = allocator()->Allocate(); | 5206 Result scratch2 = allocator()->Allocate(); |
5184 Result heap_number = allocator()->Allocate(); | 5207 Result heap_number = allocator()->Allocate(); |
5185 __ AllocateHeapNumber(heap_number.reg(), | 5208 __ AllocateHeapNumber(heap_number.reg(), |
5186 scratch1.reg(), | 5209 scratch1.reg(), |
5187 scratch2.reg(), | 5210 scratch2.reg(), |
5188 call_runtime.entry_label()); | 5211 call_runtime.entry_label()); |
5189 scratch1.Unuse(); | 5212 scratch1.Unuse(); |
| 5213 |
| 5214 // Store the result in the allocated heap number. |
| 5215 __ GenerateHeapNumberValueAddress(scratch2.reg(), heap_number.reg()); |
| 5216 __ fstp_d(Operand(scratch2.reg(), 0)); |
5190 scratch2.Unuse(); | 5217 scratch2.Unuse(); |
5191 | 5218 |
5192 // Store the result in the allocated heap number. | |
5193 __ fstp_d(FieldOperand(heap_number.reg(), HeapNumber::kValueOffset)); | |
5194 // Replace the extra copy of the argument with the result. | 5219 // Replace the extra copy of the argument with the result. |
5195 frame_->SetElementAt(0, &heap_number); | 5220 frame_->SetElementAt(0, &heap_number); |
5196 done.Jump(); | 5221 done.Jump(); |
5197 | 5222 |
5198 call_runtime.Bind(); | 5223 call_runtime.Bind(); |
5199 // Free ST(0) which was not popped before calling into the runtime. | 5224 // Free ST(0) which was not popped before calling into the runtime. |
5200 __ ffree(0); | 5225 __ ffree(0); |
5201 Result answer; | 5226 Result answer; |
5202 switch (op) { | 5227 switch (op) { |
5203 case SIN: | 5228 case SIN: |
(...skipping 1303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6507 __ mov(edx, FieldOperand(eax, String::kLengthOffset)); | 6532 __ mov(edx, FieldOperand(eax, String::kLengthOffset)); |
6508 __ test(edx, Operand(edx)); | 6533 __ test(edx, Operand(edx)); |
6509 __ j(zero, &false_result); | 6534 __ j(zero, &false_result); |
6510 __ jmp(&true_result); | 6535 __ jmp(&true_result); |
6511 | 6536 |
6512 __ bind(¬_string); | 6537 __ bind(¬_string); |
6513 // HeapNumber => false iff +0, -0, or NaN. | 6538 // HeapNumber => false iff +0, -0, or NaN. |
6514 __ cmp(edx, Factory::heap_number_map()); | 6539 __ cmp(edx, Factory::heap_number_map()); |
6515 __ j(not_equal, &true_result); | 6540 __ j(not_equal, &true_result); |
6516 __ fldz(); | 6541 __ fldz(); |
6517 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 6542 __ GenerateHeapNumberValueAddress(edx, eax); |
| 6543 __ fld_d(Operand(edx, 0)); |
6518 __ FCmp(); | 6544 __ FCmp(); |
6519 __ j(zero, &false_result); | 6545 __ j(zero, &false_result); |
6520 // Fall through to |true_result|. | 6546 // Fall through to |true_result|. |
6521 | 6547 |
6522 // Return 1/0 for true/false in eax. | 6548 // Return 1/0 for true/false in eax. |
6523 __ bind(&true_result); | 6549 __ bind(&true_result); |
6524 __ mov(eax, 1); | 6550 __ mov(eax, 1); |
6525 __ ret(1 * kPointerSize); | 6551 __ ret(1 * kPointerSize); |
6526 __ bind(&false_result); | 6552 __ bind(&false_result); |
6527 __ mov(eax, 0); | 6553 __ mov(eax, 0); |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6819 switch (op_) { | 6845 switch (op_) { |
6820 case Token::ADD: | 6846 case Token::ADD: |
6821 case Token::SUB: | 6847 case Token::SUB: |
6822 case Token::MUL: | 6848 case Token::MUL: |
6823 case Token::DIV: { | 6849 case Token::DIV: { |
6824 // eax: y | 6850 // eax: y |
6825 // edx: x | 6851 // edx: x |
6826 | 6852 |
6827 if (CpuFeatures::IsSupported(SSE2)) { | 6853 if (CpuFeatures::IsSupported(SSE2)) { |
6828 CpuFeatures::Scope use_sse2(SSE2); | 6854 CpuFeatures::Scope use_sse2(SSE2); |
6829 FloatingPointHelper::LoadSse2Operands(masm, &call_runtime); | 6855 FloatingPointHelper::LoadSse2Operands(masm, ecx, &call_runtime); |
6830 | 6856 |
6831 switch (op_) { | 6857 switch (op_) { |
6832 case Token::ADD: __ addsd(xmm0, xmm1); break; | 6858 case Token::ADD: __ addsd(xmm0, xmm1); break; |
6833 case Token::SUB: __ subsd(xmm0, xmm1); break; | 6859 case Token::SUB: __ subsd(xmm0, xmm1); break; |
6834 case Token::MUL: __ mulsd(xmm0, xmm1); break; | 6860 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
6835 case Token::DIV: __ divsd(xmm0, xmm1); break; | 6861 case Token::DIV: __ divsd(xmm0, xmm1); break; |
6836 default: UNREACHABLE(); | 6862 default: UNREACHABLE(); |
6837 } | 6863 } |
6838 // Allocate a heap number, if needed. | 6864 // Allocate a heap number, if needed. |
6839 Label skip_allocation; | 6865 Label skip_allocation; |
(...skipping 12 matching lines...) Expand all Loading... |
6852 // for the possible runtime call. | 6878 // for the possible runtime call. |
6853 __ AllocateHeapNumber(ebx, ecx, no_reg, &call_runtime); | 6879 __ AllocateHeapNumber(ebx, ecx, no_reg, &call_runtime); |
6854 // Now eax can be overwritten losing one of the arguments as we are | 6880 // Now eax can be overwritten losing one of the arguments as we are |
6855 // now done and will not need it any more. | 6881 // now done and will not need it any more. |
6856 __ mov(eax, ebx); | 6882 __ mov(eax, ebx); |
6857 __ bind(&skip_allocation); | 6883 __ bind(&skip_allocation); |
6858 break; | 6884 break; |
6859 } | 6885 } |
6860 default: UNREACHABLE(); | 6886 default: UNREACHABLE(); |
6861 } | 6887 } |
6862 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 6888 __ GenerateHeapNumberValueAddress(ecx, eax); |
| 6889 __ movdbl(Operand(ecx, 0), xmm0); |
6863 GenerateReturn(masm); | 6890 GenerateReturn(masm); |
6864 } else { // SSE2 not available, use FPU. | 6891 } else { // SSE2 not available, use FPU. |
6865 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx); | 6892 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx); |
6866 // Allocate a heap number, if needed. | 6893 // Allocate a heap number, if needed. |
6867 Label skip_allocation; | 6894 Label skip_allocation; |
6868 switch (mode_) { | 6895 switch (mode_) { |
6869 case OVERWRITE_LEFT: | 6896 case OVERWRITE_LEFT: |
6870 __ mov(eax, Operand(edx)); | 6897 __ mov(eax, Operand(edx)); |
6871 // Fall through! | 6898 // Fall through! |
6872 case OVERWRITE_RIGHT: | 6899 case OVERWRITE_RIGHT: |
(...skipping 15 matching lines...) Expand all Loading... |
6888 } | 6915 } |
6889 FloatingPointHelper::LoadFloatOperands(masm, ecx); | 6916 FloatingPointHelper::LoadFloatOperands(masm, ecx); |
6890 | 6917 |
6891 switch (op_) { | 6918 switch (op_) { |
6892 case Token::ADD: __ faddp(1); break; | 6919 case Token::ADD: __ faddp(1); break; |
6893 case Token::SUB: __ fsubp(1); break; | 6920 case Token::SUB: __ fsubp(1); break; |
6894 case Token::MUL: __ fmulp(1); break; | 6921 case Token::MUL: __ fmulp(1); break; |
6895 case Token::DIV: __ fdivp(1); break; | 6922 case Token::DIV: __ fdivp(1); break; |
6896 default: UNREACHABLE(); | 6923 default: UNREACHABLE(); |
6897 } | 6924 } |
6898 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 6925 __ GenerateHeapNumberValueAddress(ecx, eax); |
| 6926 __ fstp_d(Operand(ecx, 0)); |
6899 GenerateReturn(masm); | 6927 GenerateReturn(masm); |
6900 } | 6928 } |
6901 } | 6929 } |
6902 case Token::MOD: { | 6930 case Token::MOD: { |
6903 // For MOD we go directly to runtime in the non-smi case. | 6931 // For MOD we go directly to runtime in the non-smi case. |
6904 break; | 6932 break; |
6905 } | 6933 } |
6906 case Token::BIT_OR: | 6934 case Token::BIT_OR: |
6907 case Token::BIT_AND: | 6935 case Token::BIT_AND: |
6908 case Token::BIT_XOR: | 6936 case Token::BIT_XOR: |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6985 // Fall through! | 7013 // Fall through! |
6986 case NO_OVERWRITE: | 7014 case NO_OVERWRITE: |
6987 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | 7015 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
6988 __ bind(&skip_allocation); | 7016 __ bind(&skip_allocation); |
6989 break; | 7017 break; |
6990 default: UNREACHABLE(); | 7018 default: UNREACHABLE(); |
6991 } | 7019 } |
6992 // Store the result in the HeapNumber and return. | 7020 // Store the result in the HeapNumber and return. |
6993 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 7021 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
6994 __ fild_s(Operand(esp, 1 * kPointerSize)); | 7022 __ fild_s(Operand(esp, 1 * kPointerSize)); |
6995 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 7023 __ GenerateHeapNumberValueAddress(ecx, eax); |
| 7024 __ fstp_d(Operand(ecx, 0)); |
6996 GenerateReturn(masm); | 7025 GenerateReturn(masm); |
6997 } | 7026 } |
6998 | 7027 |
6999 // Clear the FPU exception flag and reset the stack before calling | 7028 // Clear the FPU exception flag and reset the stack before calling |
7000 // the runtime system. | 7029 // the runtime system. |
7001 __ bind(&operand_conversion_failure); | 7030 __ bind(&operand_conversion_failure); |
7002 __ add(Operand(esp), Immediate(2 * kPointerSize)); | 7031 __ add(Operand(esp), Immediate(2 * kPointerSize)); |
7003 if (use_sse3_) { | 7032 if (use_sse3_) { |
7004 // If we've used the SSE3 instructions for truncating the | 7033 // If we've used the SSE3 instructions for truncating the |
7005 // floating point values to integers and it failed, we have a | 7034 // floating point values to integers and it failed, we have a |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7129 // returning. | 7158 // returning. |
7130 if (!HasArgumentsInRegisters()) { | 7159 if (!HasArgumentsInRegisters()) { |
7131 __ ret(2 * kPointerSize); // Remove both operands | 7160 __ ret(2 * kPointerSize); // Remove both operands |
7132 } else { | 7161 } else { |
7133 __ ret(0); | 7162 __ ret(0); |
7134 } | 7163 } |
7135 } | 7164 } |
7136 | 7165 |
7137 | 7166 |
7138 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, | 7167 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, |
7139 Register number) { | 7168 Register number, |
| 7169 Register scratch) { |
7140 Label load_smi, done; | 7170 Label load_smi, done; |
7141 | 7171 |
7142 __ test(number, Immediate(kSmiTagMask)); | 7172 __ test(number, Immediate(kSmiTagMask)); |
7143 __ j(zero, &load_smi, not_taken); | 7173 __ j(zero, &load_smi, not_taken); |
7144 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); | 7174 __ GenerateHeapNumberValueAddress(scratch, number); |
| 7175 __ fld_d(Operand(scratch, 0)); |
7145 __ jmp(&done); | 7176 __ jmp(&done); |
7146 | 7177 |
7147 __ bind(&load_smi); | 7178 __ bind(&load_smi); |
7148 __ sar(number, kSmiTagSize); | 7179 __ sar(number, kSmiTagSize); |
7149 __ push(number); | 7180 __ push(number); |
7150 __ fild_s(Operand(esp, 0)); | 7181 __ fild_s(Operand(esp, 0)); |
7151 __ pop(number); | 7182 __ pop(number); |
7152 | 7183 |
7153 __ bind(&done); | 7184 __ bind(&done); |
7154 } | 7185 } |
7155 | 7186 |
7156 | 7187 |
7157 void FloatingPointHelper::LoadSse2Operands(MacroAssembler* masm, | 7188 void FloatingPointHelper::LoadSse2Operands(MacroAssembler* masm, |
| 7189 Register scratch, |
7158 Label* not_numbers) { | 7190 Label* not_numbers) { |
7159 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; | 7191 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; |
7160 // Load operand in edx into xmm0, or branch to not_numbers. | 7192 // Load operand in edx into xmm0, or branch to not_numbers. |
7161 __ test(edx, Immediate(kSmiTagMask)); | 7193 __ test(edx, Immediate(kSmiTagMask)); |
7162 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi. | 7194 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi. |
7163 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), Factory::heap_number_map()); | 7195 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), Factory::heap_number_map()); |
7164 __ j(not_equal, not_numbers); // Argument in edx is not a number. | 7196 __ j(not_equal, not_numbers); // Argument in edx is not a number. |
7165 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 7197 __ GenerateHeapNumberValueAddress(scratch, edx); |
| 7198 __ movdbl(xmm0, Operand(scratch, 0)); |
7166 __ bind(&load_eax); | 7199 __ bind(&load_eax); |
7167 // Load operand in eax into xmm1, or branch to not_numbers. | 7200 // Load operand in eax into xmm1, or branch to not_numbers. |
7168 __ test(eax, Immediate(kSmiTagMask)); | 7201 __ test(eax, Immediate(kSmiTagMask)); |
7169 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. | 7202 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. |
7170 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::heap_number_map()); | 7203 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::heap_number_map()); |
7171 __ j(equal, &load_float_eax); | 7204 __ j(equal, &load_float_eax); |
7172 __ jmp(not_numbers); // Argument in eax is not a number. | 7205 __ jmp(not_numbers); // Argument in eax is not a number. |
7173 __ bind(&load_smi_edx); | 7206 __ bind(&load_smi_edx); |
7174 __ sar(edx, 1); // Untag smi before converting to float. | 7207 __ sar(edx, 1); // Untag smi before converting to float. |
7175 __ cvtsi2sd(xmm0, Operand(edx)); | 7208 __ cvtsi2sd(xmm0, Operand(edx)); |
7176 __ shl(edx, 1); // Retag smi for heap number overwriting test. | 7209 __ shl(edx, 1); // Retag smi for heap number overwriting test. |
7177 __ jmp(&load_eax); | 7210 __ jmp(&load_eax); |
7178 __ bind(&load_smi_eax); | 7211 __ bind(&load_smi_eax); |
7179 __ sar(eax, 1); // Untag smi before converting to float. | 7212 __ sar(eax, 1); // Untag smi before converting to float. |
7180 __ cvtsi2sd(xmm1, Operand(eax)); | 7213 __ cvtsi2sd(xmm1, Operand(eax)); |
7181 __ shl(eax, 1); // Retag smi for heap number overwriting test. | 7214 __ shl(eax, 1); // Retag smi for heap number overwriting test. |
7182 __ jmp(&done); | 7215 __ jmp(&done); |
7183 __ bind(&load_float_eax); | 7216 __ bind(&load_float_eax); |
7184 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 7217 __ GenerateHeapNumberValueAddress(scratch, eax); |
| 7218 __ movdbl(xmm1, Operand(scratch, 0)); |
7185 __ bind(&done); | 7219 __ bind(&done); |
7186 } | 7220 } |
7187 | 7221 |
7188 | 7222 |
7189 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, | 7223 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, |
7190 Register scratch) { | 7224 Register scratch) { |
7191 Label load_smi_1, load_smi_2, done_load_1, done; | 7225 Label load_smi_1, load_smi_2, done_load_1, done; |
7192 __ mov(scratch, Operand(esp, 2 * kPointerSize)); | 7226 __ mov(scratch, Operand(esp, 2 * kPointerSize)); |
7193 __ test(scratch, Immediate(kSmiTagMask)); | 7227 __ test(scratch, Immediate(kSmiTagMask)); |
7194 __ j(zero, &load_smi_1, not_taken); | 7228 __ j(zero, &load_smi_1, not_taken); |
7195 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); | 7229 __ GenerateHeapNumberValueAddress(scratch, scratch); |
| 7230 __ fld_d(Operand(scratch, 0)); |
7196 __ bind(&done_load_1); | 7231 __ bind(&done_load_1); |
7197 | 7232 |
7198 __ mov(scratch, Operand(esp, 1 * kPointerSize)); | 7233 __ mov(scratch, Operand(esp, 1 * kPointerSize)); |
7199 __ test(scratch, Immediate(kSmiTagMask)); | 7234 __ test(scratch, Immediate(kSmiTagMask)); |
7200 __ j(zero, &load_smi_2, not_taken); | 7235 __ j(zero, &load_smi_2, not_taken); |
7201 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); | 7236 __ GenerateHeapNumberValueAddress(scratch, scratch); |
| 7237 __ fld_d(Operand(scratch, 0)); |
7202 __ jmp(&done); | 7238 __ jmp(&done); |
7203 | 7239 |
7204 __ bind(&load_smi_1); | 7240 __ bind(&load_smi_1); |
7205 __ sar(scratch, kSmiTagSize); | 7241 __ sar(scratch, kSmiTagSize); |
7206 __ push(scratch); | 7242 __ push(scratch); |
7207 __ fild_s(Operand(esp, 0)); | 7243 __ fild_s(Operand(esp, 0)); |
7208 __ pop(scratch); | 7244 __ pop(scratch); |
7209 __ jmp(&done_load_1); | 7245 __ jmp(&done_load_1); |
7210 | 7246 |
7211 __ bind(&load_smi_2); | 7247 __ bind(&load_smi_2); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7278 __ push(eax); | 7314 __ push(eax); |
7279 __ push(ecx); // push return address | 7315 __ push(ecx); // push return address |
7280 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); | 7316 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); |
7281 | 7317 |
7282 // Try floating point case. | 7318 // Try floating point case. |
7283 __ bind(&try_float); | 7319 __ bind(&try_float); |
7284 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 7320 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
7285 __ cmp(edx, Factory::heap_number_map()); | 7321 __ cmp(edx, Factory::heap_number_map()); |
7286 __ j(not_equal, &slow); | 7322 __ j(not_equal, &slow); |
7287 if (overwrite_) { | 7323 if (overwrite_) { |
7288 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); | 7324 __ GenerateHeapNumberValueAddress(ebx, eax); |
| 7325 __ mov(edx, Operand(ebx, HeapNumber::kExponentRelativeOffset)); |
7289 __ xor_(edx, HeapNumber::kSignMask); // Flip sign. | 7326 __ xor_(edx, HeapNumber::kSignMask); // Flip sign. |
7290 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), edx); | 7327 __ mov(Operand(ebx, HeapNumber::kExponentRelativeOffset), edx); |
7291 } else { | 7328 } else { |
7292 __ mov(edx, Operand(eax)); | 7329 __ mov(edx, Operand(eax)); |
7293 // edx: operand | 7330 // edx: operand |
7294 __ AllocateHeapNumber(eax, ebx, ecx, &undo); | 7331 __ AllocateHeapNumber(eax, ebx, ecx, &undo); |
7295 // eax: allocated 'empty' number | 7332 // eax: allocated 'empty' number |
7296 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); | 7333 __ GenerateHeapNumberValueAddress(edx, edx); |
| 7334 __ GenerateHeapNumberValueAddress(ebx, eax); |
| 7335 __ mov(ecx, Operand(edx, HeapNumber::kExponentRelativeOffset)); |
7297 __ xor_(ecx, HeapNumber::kSignMask); // Flip sign. | 7336 __ xor_(ecx, HeapNumber::kSignMask); // Flip sign. |
7298 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ecx); | 7337 __ mov(Operand(ebx, HeapNumber::kExponentRelativeOffset), ecx); |
7299 __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset)); | 7338 __ mov(ecx, Operand(edx, HeapNumber::kMantissaRelativeOffset)); |
7300 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); | 7339 __ mov(Operand(ebx, HeapNumber::kMantissaRelativeOffset), ecx); |
7301 } | 7340 } |
7302 | 7341 |
7303 __ bind(&done); | 7342 __ bind(&done); |
7304 | 7343 |
7305 __ StubReturn(1); | 7344 __ StubReturn(1); |
7306 } | 7345 } |
7307 | 7346 |
7308 | 7347 |
7309 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { | 7348 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { |
7310 // Check if the calling frame is an arguments adaptor frame. | 7349 // Check if the calling frame is an arguments adaptor frame. |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7441 // not NaN. | 7480 // not NaN. |
7442 // The representation of NaN values has all exponent bits (52..62) set, | 7481 // The representation of NaN values has all exponent bits (52..62) set, |
7443 // and not all mantissa bits (0..51) clear. | 7482 // and not all mantissa bits (0..51) clear. |
7444 // We only accept QNaNs, which have bit 51 set. | 7483 // We only accept QNaNs, which have bit 51 set. |
7445 // Read top bits of double representation (second word of value). | 7484 // Read top bits of double representation (second word of value). |
7446 | 7485 |
7447 // Value is a QNaN if value & kQuietNaNMask == kQuietNaNMask, i.e., | 7486 // Value is a QNaN if value & kQuietNaNMask == kQuietNaNMask, i.e., |
7448 // all bits in the mask are set. We only need to check the word | 7487 // all bits in the mask are set. We only need to check the word |
7449 // that contains the exponent and high bit of the mantissa. | 7488 // that contains the exponent and high bit of the mantissa. |
7450 ASSERT_NE(0, (kQuietNaNHighBitsMask << 1) & 0x80000000u); | 7489 ASSERT_NE(0, (kQuietNaNHighBitsMask << 1) & 0x80000000u); |
7451 __ mov(edx, FieldOperand(edx, HeapNumber::kExponentOffset)); | 7490 __ GenerateHeapNumberValueAddress(edx, edx); |
| 7491 __ mov(edx, Operand(edx, HeapNumber::kExponentRelativeOffset)); |
7452 __ xor_(eax, Operand(eax)); | 7492 __ xor_(eax, Operand(eax)); |
7453 // Shift value and mask so kQuietNaNHighBitsMask applies to topmost bits. | 7493 // Shift value and mask so kQuietNaNHighBitsMask applies to topmost bits. |
7454 __ add(edx, Operand(edx)); | 7494 __ add(edx, Operand(edx)); |
7455 __ cmp(edx, kQuietNaNHighBitsMask << 1); | 7495 __ cmp(edx, kQuietNaNHighBitsMask << 1); |
7456 __ setcc(above_equal, eax); | 7496 __ setcc(above_equal, eax); |
7457 __ ret(0); | 7497 __ ret(0); |
7458 | 7498 |
7459 __ bind(¬_identical); | 7499 __ bind(¬_identical); |
7460 } | 7500 } |
7461 | 7501 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7545 __ push(ecx); | 7585 __ push(ecx); |
7546 | 7586 |
7547 // Inlined floating point compare. | 7587 // Inlined floating point compare. |
7548 // Call builtin if operands are not floating point or smi. | 7588 // Call builtin if operands are not floating point or smi. |
7549 Label check_for_symbols; | 7589 Label check_for_symbols; |
7550 Label unordered; | 7590 Label unordered; |
7551 if (CpuFeatures::IsSupported(SSE2)) { | 7591 if (CpuFeatures::IsSupported(SSE2)) { |
7552 CpuFeatures::Scope use_sse2(SSE2); | 7592 CpuFeatures::Scope use_sse2(SSE2); |
7553 CpuFeatures::Scope use_cmov(CMOV); | 7593 CpuFeatures::Scope use_cmov(CMOV); |
7554 | 7594 |
7555 FloatingPointHelper::LoadSse2Operands(masm, &check_for_symbols); | 7595 FloatingPointHelper::LoadSse2Operands(masm, ecx, &check_for_symbols); |
7556 __ comisd(xmm0, xmm1); | 7596 __ comisd(xmm0, xmm1); |
7557 | 7597 |
7558 // Jump to builtin for NaN. | 7598 // Jump to builtin for NaN. |
7559 __ j(parity_even, &unordered, not_taken); | 7599 __ j(parity_even, &unordered, not_taken); |
7560 __ mov(eax, 0); // equal | 7600 __ mov(eax, 0); // equal |
7561 __ mov(ecx, Immediate(Smi::FromInt(1))); | 7601 __ mov(ecx, Immediate(Smi::FromInt(1))); |
7562 __ cmov(above, eax, Operand(ecx)); | 7602 __ cmov(above, eax, Operand(ecx)); |
7563 __ mov(ecx, Immediate(Smi::FromInt(-1))); | 7603 __ mov(ecx, Immediate(Smi::FromInt(-1))); |
7564 __ cmov(below, eax, Operand(ecx)); | 7604 __ cmov(below, eax, Operand(ecx)); |
7565 __ ret(2 * kPointerSize); | 7605 __ ret(2 * kPointerSize); |
(...skipping 833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8399 __ add(Operand(dest), Immediate(2)); | 8439 __ add(Operand(dest), Immediate(2)); |
8400 } | 8440 } |
8401 __ sub(Operand(count), Immediate(1)); | 8441 __ sub(Operand(count), Immediate(1)); |
8402 __ j(not_zero, &loop); | 8442 __ j(not_zero, &loop); |
8403 } | 8443 } |
8404 | 8444 |
8405 | 8445 |
8406 #undef __ | 8446 #undef __ |
8407 | 8447 |
8408 } } // namespace v8::internal | 8448 } } // namespace v8::internal |
OLD | NEW |