Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 460043: Always 64-bit align floating point values in heap numbers.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/heap.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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(&not_string); 6537 __ bind(&not_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
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
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
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
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
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
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
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(&not_identical); 7499 __ bind(&not_identical);
7460 } 7500 }
7461 7501
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
OLDNEW
« no previous file with comments | « src/heap.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698