OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
740 // Expects operands in edx, eax. | 740 // Expects operands in edx, eax. |
741 static void LoadFloatSmis(MacroAssembler* masm, Register scratch); | 741 static void LoadFloatSmis(MacroAssembler* masm, Register scratch); |
742 | 742 |
743 // Test if operands are smi or number objects (fp). Requirements: | 743 // Test if operands are smi or number objects (fp). Requirements: |
744 // operand_1 in eax, operand_2 in edx; falls through on float | 744 // operand_1 in eax, operand_2 in edx; falls through on float |
745 // operands, jumps to the non_float label otherwise. | 745 // operands, jumps to the non_float label otherwise. |
746 static void CheckFloatOperands(MacroAssembler* masm, | 746 static void CheckFloatOperands(MacroAssembler* masm, |
747 Label* non_float, | 747 Label* non_float, |
748 Register scratch); | 748 Register scratch); |
749 | 749 |
750 // Checks that the two floating point numbers on top of the FPU stack | |
751 // have int32 values. | |
752 static void CheckFloatOperandsAreInt32(MacroAssembler* masm, | |
753 Label* non_int32); | |
754 | |
755 // Takes the operands in edx and eax and loads them as integers in eax | 750 // Takes the operands in edx and eax and loads them as integers in eax |
756 // and ecx. | 751 // and ecx. |
757 static void LoadUnknownsAsIntegers(MacroAssembler* masm, | 752 static void LoadUnknownsAsIntegers(MacroAssembler* masm, |
758 bool use_sse3, | 753 bool use_sse3, |
754 BinaryOpIC::TypeInfo left_type, | |
755 BinaryOpIC::TypeInfo right_type, | |
759 Label* operand_conversion_failure); | 756 Label* operand_conversion_failure); |
760 | 757 |
761 // Must only be called after LoadUnknownsAsIntegers. Assumes that the | |
762 // operands are pushed on the stack, and that their conversions to int32 | |
763 // are in eax and ecx. Checks that the original numbers were in the int32 | |
764 // range. | |
765 static void CheckLoadedIntegersWereInt32(MacroAssembler* masm, | |
766 bool use_sse3, | |
767 Label* not_int32); | |
768 | |
769 // Assumes that operands are smis or heap numbers and loads them | 758 // Assumes that operands are smis or heap numbers and loads them |
770 // into xmm0 and xmm1. Operands are in edx and eax. | 759 // into xmm0 and xmm1. Operands are in edx and eax. |
771 // Leaves operands unchanged. | 760 // Leaves operands unchanged. |
772 static void LoadSSE2Operands(MacroAssembler* masm); | 761 static void LoadSSE2Operands(MacroAssembler* masm); |
773 | 762 |
774 // Test if operands are numbers (smi or HeapNumber objects), and load | 763 // Test if operands are numbers (smi or HeapNumber objects), and load |
775 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if | 764 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if |
776 // either operand is not a number. Operands are in edx and eax. | 765 // either operand is not a number. Operands are in edx and eax. |
777 // Leaves operands unchanged. | 766 // Leaves operands unchanged. |
778 static void LoadSSE2Operands(MacroAssembler* masm, Label* not_numbers); | 767 static void LoadSSE2Operands(MacroAssembler* masm, Label* not_numbers); |
779 | 768 |
780 // Similar to LoadSSE2Operands but assumes that both operands are smis. | 769 // Similar to LoadSSE2Operands but assumes that both operands are smis. |
781 // Expects operands in edx, eax. | 770 // Expects operands in edx, eax. |
782 static void LoadSSE2Smis(MacroAssembler* masm, Register scratch); | 771 static void LoadSSE2Smis(MacroAssembler* masm, Register scratch); |
783 | 772 |
784 // Checks that the two floating point numbers loaded into xmm0 and xmm1 | 773 // Checks that the two floating point numbers loaded into xmm0 and xmm1 |
785 // have int32 values. | 774 // have int32 values. |
786 static void CheckSSE2OperandsAreInt32(MacroAssembler* masm, | 775 static void CheckSSE2OperandsAreInt32(MacroAssembler* masm, |
787 Label* non_int32, | 776 Label* non_int32, |
788 Register scratch); | 777 Register scratch); |
789 | 778 |
779 // Checks that |operand| has an int32 value. If |int32_result| is different | |
780 // from |scratch|, it will contain that int32 value. | |
790 static void CheckSSE2OperandIsInt32(MacroAssembler* masm, | 781 static void CheckSSE2OperandIsInt32(MacroAssembler* masm, |
791 Label* non_int32, | 782 Label* non_int32, |
792 XMMRegister operand, | 783 XMMRegister operand, |
784 Register int32_result, | |
793 Register scratch, | 785 Register scratch, |
794 XMMRegister xmm_scratch); | 786 XMMRegister xmm_scratch); |
795 }; | 787 }; |
796 | 788 |
797 | 789 |
798 // Get the integer part of a heap number. Surprisingly, all this bit twiddling | 790 // Get the integer part of a heap number. Surprisingly, all this bit twiddling |
799 // is faster than using the built-in instructions on floating point registers. | 791 // is faster than using the built-in instructions on floating point registers. |
800 // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the | 792 // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the |
801 // trashed registers. | 793 // trashed registers. |
802 static void IntegerConvert(MacroAssembler* masm, | 794 static void IntegerConvert(MacroAssembler* masm, |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
916 __ j(greater, &negative, Label::kNear); | 908 __ j(greater, &negative, Label::kNear); |
917 __ mov(ecx, scratch2); | 909 __ mov(ecx, scratch2); |
918 __ jmp(&done, Label::kNear); | 910 __ jmp(&done, Label::kNear); |
919 __ bind(&negative); | 911 __ bind(&negative); |
920 __ sub(ecx, scratch2); | 912 __ sub(ecx, scratch2); |
921 } | 913 } |
922 __ bind(&done); | 914 __ bind(&done); |
923 } | 915 } |
924 | 916 |
925 | 917 |
918 // Uses SSE2 to convert the heap number in |source| to an integer. | |
919 // Result is in ecx. Trashes ebx, xmm0, and xmm1. | |
920 static void ConvertHeapNumberToInt32(MacroAssembler* masm, | |
Jakob Kummerow
2013/02/07 15:28:35
Basically a drop-in replacement for IntegerConvert
| |
921 Register source, | |
922 Label* conversion_failure) { | |
923 __ movdbl(xmm0, FieldOperand(source, HeapNumber::kValueOffset)); | |
924 FloatingPointHelper::CheckSSE2OperandIsInt32( | |
925 masm, conversion_failure, xmm0, ecx, ebx, xmm1); | |
926 } | |
927 | |
928 | |
926 void UnaryOpStub::PrintName(StringStream* stream) { | 929 void UnaryOpStub::PrintName(StringStream* stream) { |
927 const char* op_name = Token::Name(op_); | 930 const char* op_name = Token::Name(op_); |
928 const char* overwrite_name = NULL; // Make g++ happy. | 931 const char* overwrite_name = NULL; // Make g++ happy. |
929 switch (mode_) { | 932 switch (mode_) { |
930 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break; | 933 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break; |
931 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break; | 934 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break; |
932 } | 935 } |
933 stream->Add("UnaryOpStub_%s_%s_%s", | 936 stream->Add("UnaryOpStub_%s_%s_%s", |
934 op_name, | 937 op_name, |
935 overwrite_name, | 938 overwrite_name, |
(...skipping 854 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1790 switch (op_) { | 1793 switch (op_) { |
1791 case Token::ADD: __ addsd(xmm0, xmm1); break; | 1794 case Token::ADD: __ addsd(xmm0, xmm1); break; |
1792 case Token::SUB: __ subsd(xmm0, xmm1); break; | 1795 case Token::SUB: __ subsd(xmm0, xmm1); break; |
1793 case Token::MUL: __ mulsd(xmm0, xmm1); break; | 1796 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
1794 case Token::DIV: __ divsd(xmm0, xmm1); break; | 1797 case Token::DIV: __ divsd(xmm0, xmm1); break; |
1795 default: UNREACHABLE(); | 1798 default: UNREACHABLE(); |
1796 } | 1799 } |
1797 // Check result type if it is currently Int32. | 1800 // Check result type if it is currently Int32. |
1798 if (result_type_ <= BinaryOpIC::INT32) { | 1801 if (result_type_ <= BinaryOpIC::INT32) { |
1799 FloatingPointHelper::CheckSSE2OperandIsInt32( | 1802 FloatingPointHelper::CheckSSE2OperandIsInt32( |
1800 masm, ¬_int32, xmm0, ecx, xmm2); | 1803 masm, ¬_int32, xmm0, ecx, ecx, xmm2); |
1801 } | 1804 } |
1802 BinaryOpStub_GenerateHeapResultAllocation(masm, &call_runtime, mode_); | 1805 BinaryOpStub_GenerateHeapResultAllocation(masm, &call_runtime, mode_); |
1803 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 1806 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
1804 __ ret(0); | 1807 __ ret(0); |
1805 } | 1808 } |
1806 } else { // SSE2 not available, use FPU. | 1809 } else { // SSE2 not available, use FPU. |
1807 FloatingPointHelper::CheckFloatOperands(masm, ¬_floats, ebx); | 1810 FloatingPointHelper::CheckFloatOperands(masm, ¬_floats, ebx); |
1808 FloatingPointHelper::LoadFloatOperands( | 1811 FloatingPointHelper::LoadFloatOperands( |
1809 masm, | 1812 masm, |
1810 ecx, | 1813 ecx, |
1811 FloatingPointHelper::ARGS_IN_REGISTERS); | 1814 FloatingPointHelper::ARGS_IN_REGISTERS); |
1812 FloatingPointHelper::CheckFloatOperandsAreInt32(masm, ¬_int32); | |
1813 if (op_ == Token::MOD) { | 1815 if (op_ == Token::MOD) { |
1814 // The operands are now on the FPU stack, but we don't need them. | 1816 // The operands are now on the FPU stack, but we don't need them. |
1815 __ fstp(0); | 1817 __ fstp(0); |
1816 __ fstp(0); | 1818 __ fstp(0); |
1817 GenerateRegisterArgsPush(masm); | 1819 GenerateRegisterArgsPush(masm); |
1818 __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION); | 1820 __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION); |
1819 } else { | 1821 } else { |
1820 switch (op_) { | 1822 switch (op_) { |
1821 case Token::ADD: __ faddp(1); break; | 1823 case Token::ADD: __ faddp(1); break; |
1822 case Token::SUB: __ fsubp(1); break; | 1824 case Token::SUB: __ fsubp(1); break; |
(...skipping 21 matching lines...) Expand all Loading... | |
1844 case Token::BIT_OR: | 1846 case Token::BIT_OR: |
1845 case Token::BIT_AND: | 1847 case Token::BIT_AND: |
1846 case Token::BIT_XOR: | 1848 case Token::BIT_XOR: |
1847 case Token::SAR: | 1849 case Token::SAR: |
1848 case Token::SHL: | 1850 case Token::SHL: |
1849 case Token::SHR: { | 1851 case Token::SHR: { |
1850 GenerateRegisterArgsPush(masm); | 1852 GenerateRegisterArgsPush(masm); |
1851 Label not_floats; | 1853 Label not_floats; |
1852 Label not_int32; | 1854 Label not_int32; |
1853 Label non_smi_result; | 1855 Label non_smi_result; |
1854 // We do not check the input arguments here, as any value is | |
1855 // unconditionally truncated to an int32 anyway. To get the | |
1856 // right optimized code, int32 type feedback is just right. | |
Jakob Kummerow
2013/02/07 15:28:35
Yeah, well, turns out it's not quite right after a
| |
1857 bool use_sse3 = platform_specific_bit_; | 1856 bool use_sse3 = platform_specific_bit_; |
1858 FloatingPointHelper::LoadUnknownsAsIntegers(masm, | 1857 FloatingPointHelper::LoadUnknownsAsIntegers( |
1859 use_sse3, | 1858 masm, use_sse3, left_type_, right_type_, ¬_floats); |
1860 ¬_floats); | |
1861 FloatingPointHelper::CheckLoadedIntegersWereInt32(masm, use_sse3, | |
1862 ¬_int32); | |
1863 switch (op_) { | 1859 switch (op_) { |
1864 case Token::BIT_OR: __ or_(eax, ecx); break; | 1860 case Token::BIT_OR: __ or_(eax, ecx); break; |
1865 case Token::BIT_AND: __ and_(eax, ecx); break; | 1861 case Token::BIT_AND: __ and_(eax, ecx); break; |
1866 case Token::BIT_XOR: __ xor_(eax, ecx); break; | 1862 case Token::BIT_XOR: __ xor_(eax, ecx); break; |
1867 case Token::SAR: __ sar_cl(eax); break; | 1863 case Token::SAR: __ sar_cl(eax); break; |
1868 case Token::SHL: __ shl_cl(eax); break; | 1864 case Token::SHL: __ shl_cl(eax); break; |
1869 case Token::SHR: __ shr_cl(eax); break; | 1865 case Token::SHR: __ shr_cl(eax); break; |
1870 default: UNREACHABLE(); | 1866 default: UNREACHABLE(); |
1871 } | 1867 } |
1872 if (op_ == Token::SHR) { | 1868 if (op_ == Token::SHR) { |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2006 // afford not to care about precise type feedback. | 2002 // afford not to care about precise type feedback. |
2007 if (left_type_ == BinaryOpIC::SMI) { | 2003 if (left_type_ == BinaryOpIC::SMI) { |
2008 __ JumpIfNotSmi(edx, ¬_floats); | 2004 __ JumpIfNotSmi(edx, ¬_floats); |
2009 } | 2005 } |
2010 if (right_type_ == BinaryOpIC::SMI) { | 2006 if (right_type_ == BinaryOpIC::SMI) { |
2011 __ JumpIfNotSmi(eax, ¬_floats); | 2007 __ JumpIfNotSmi(eax, ¬_floats); |
2012 } | 2008 } |
2013 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats); | 2009 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats); |
2014 if (left_type_ == BinaryOpIC::INT32) { | 2010 if (left_type_ == BinaryOpIC::INT32) { |
2015 FloatingPointHelper::CheckSSE2OperandIsInt32( | 2011 FloatingPointHelper::CheckSSE2OperandIsInt32( |
2016 masm, ¬_floats, xmm0, ecx, xmm2); | 2012 masm, ¬_floats, xmm0, ecx, ecx, xmm2); |
2017 } | 2013 } |
2018 if (right_type_ == BinaryOpIC::INT32) { | 2014 if (right_type_ == BinaryOpIC::INT32) { |
2019 FloatingPointHelper::CheckSSE2OperandIsInt32( | 2015 FloatingPointHelper::CheckSSE2OperandIsInt32( |
2020 masm, ¬_floats, xmm1, ecx, xmm2); | 2016 masm, ¬_floats, xmm1, ecx, ecx, xmm2); |
2021 } | 2017 } |
2022 | 2018 |
2023 switch (op_) { | 2019 switch (op_) { |
2024 case Token::ADD: __ addsd(xmm0, xmm1); break; | 2020 case Token::ADD: __ addsd(xmm0, xmm1); break; |
2025 case Token::SUB: __ subsd(xmm0, xmm1); break; | 2021 case Token::SUB: __ subsd(xmm0, xmm1); break; |
2026 case Token::MUL: __ mulsd(xmm0, xmm1); break; | 2022 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
2027 case Token::DIV: __ divsd(xmm0, xmm1); break; | 2023 case Token::DIV: __ divsd(xmm0, xmm1); break; |
2028 default: UNREACHABLE(); | 2024 default: UNREACHABLE(); |
2029 } | 2025 } |
2030 BinaryOpStub_GenerateHeapResultAllocation(masm, &call_runtime, mode_); | 2026 BinaryOpStub_GenerateHeapResultAllocation(masm, &call_runtime, mode_); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2068 case Token::SAR: | 2064 case Token::SAR: |
2069 case Token::SHL: | 2065 case Token::SHL: |
2070 case Token::SHR: { | 2066 case Token::SHR: { |
2071 GenerateRegisterArgsPush(masm); | 2067 GenerateRegisterArgsPush(masm); |
2072 Label not_floats; | 2068 Label not_floats; |
2073 Label non_smi_result; | 2069 Label non_smi_result; |
2074 // We do not check the input arguments here, as any value is | 2070 // We do not check the input arguments here, as any value is |
2075 // unconditionally truncated to an int32 anyway. To get the | 2071 // unconditionally truncated to an int32 anyway. To get the |
2076 // right optimized code, int32 type feedback is just right. | 2072 // right optimized code, int32 type feedback is just right. |
2077 bool use_sse3 = platform_specific_bit_; | 2073 bool use_sse3 = platform_specific_bit_; |
2078 FloatingPointHelper::LoadUnknownsAsIntegers(masm, | 2074 FloatingPointHelper::LoadUnknownsAsIntegers( |
2079 use_sse3, | 2075 masm, use_sse3, left_type_, right_type_, ¬_floats); |
2080 ¬_floats); | |
2081 switch (op_) { | 2076 switch (op_) { |
2082 case Token::BIT_OR: __ or_(eax, ecx); break; | 2077 case Token::BIT_OR: __ or_(eax, ecx); break; |
2083 case Token::BIT_AND: __ and_(eax, ecx); break; | 2078 case Token::BIT_AND: __ and_(eax, ecx); break; |
2084 case Token::BIT_XOR: __ xor_(eax, ecx); break; | 2079 case Token::BIT_XOR: __ xor_(eax, ecx); break; |
2085 case Token::SAR: __ sar_cl(eax); break; | 2080 case Token::SAR: __ sar_cl(eax); break; |
2086 case Token::SHL: __ shl_cl(eax); break; | 2081 case Token::SHL: __ shl_cl(eax); break; |
2087 case Token::SHR: __ shr_cl(eax); break; | 2082 case Token::SHR: __ shr_cl(eax); break; |
2088 default: UNREACHABLE(); | 2083 default: UNREACHABLE(); |
2089 } | 2084 } |
2090 if (op_ == Token::SHR) { | 2085 if (op_ == Token::SHR) { |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2249 case Token::BIT_OR: | 2244 case Token::BIT_OR: |
2250 case Token::BIT_AND: | 2245 case Token::BIT_AND: |
2251 case Token::BIT_XOR: | 2246 case Token::BIT_XOR: |
2252 case Token::SAR: | 2247 case Token::SAR: |
2253 case Token::SHL: | 2248 case Token::SHL: |
2254 case Token::SHR: { | 2249 case Token::SHR: { |
2255 Label non_smi_result; | 2250 Label non_smi_result; |
2256 bool use_sse3 = platform_specific_bit_; | 2251 bool use_sse3 = platform_specific_bit_; |
2257 FloatingPointHelper::LoadUnknownsAsIntegers(masm, | 2252 FloatingPointHelper::LoadUnknownsAsIntegers(masm, |
2258 use_sse3, | 2253 use_sse3, |
2254 BinaryOpIC::GENERIC, | |
Jakob Kummerow
2013/02/07 15:28:35
Strictly speaking, this is inconsistent, but it do
| |
2255 BinaryOpIC::GENERIC, | |
2259 &call_runtime); | 2256 &call_runtime); |
2260 switch (op_) { | 2257 switch (op_) { |
2261 case Token::BIT_OR: __ or_(eax, ecx); break; | 2258 case Token::BIT_OR: __ or_(eax, ecx); break; |
2262 case Token::BIT_AND: __ and_(eax, ecx); break; | 2259 case Token::BIT_AND: __ and_(eax, ecx); break; |
2263 case Token::BIT_XOR: __ xor_(eax, ecx); break; | 2260 case Token::BIT_XOR: __ xor_(eax, ecx); break; |
2264 case Token::SAR: __ sar_cl(eax); break; | 2261 case Token::SAR: __ sar_cl(eax); break; |
2265 case Token::SHL: __ shl_cl(eax); break; | 2262 case Token::SHL: __ shl_cl(eax); break; |
2266 case Token::SHR: __ shr_cl(eax); break; | 2263 case Token::SHR: __ shr_cl(eax); break; |
2267 default: UNREACHABLE(); | 2264 default: UNREACHABLE(); |
2268 } | 2265 } |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2729 ASSERT(type == TranscendentalCache::LOG); | 2726 ASSERT(type == TranscendentalCache::LOG); |
2730 __ fldln2(); | 2727 __ fldln2(); |
2731 __ fxch(); | 2728 __ fxch(); |
2732 __ fyl2x(); | 2729 __ fyl2x(); |
2733 } | 2730 } |
2734 } | 2731 } |
2735 | 2732 |
2736 | 2733 |
2737 // Input: edx, eax are the left and right objects of a bit op. | 2734 // Input: edx, eax are the left and right objects of a bit op. |
2738 // Output: eax, ecx are left and right integers for a bit op. | 2735 // Output: eax, ecx are left and right integers for a bit op. |
2739 void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm, | 2736 // Warning: can clobber inputs even when it jumps to |conversion_failure|! |
2740 bool use_sse3, | 2737 void FloatingPointHelper::LoadUnknownsAsIntegers( |
2741 Label* conversion_failure) { | 2738 MacroAssembler* masm, |
2739 bool use_sse3, | |
2740 BinaryOpIC::TypeInfo left_type, | |
2741 BinaryOpIC::TypeInfo right_type, | |
2742 Label* conversion_failure) { | |
2742 // Check float operands. | 2743 // Check float operands. |
2743 Label arg1_is_object, check_undefined_arg1; | 2744 Label arg1_is_object, check_undefined_arg1; |
2744 Label arg2_is_object, check_undefined_arg2; | 2745 Label arg2_is_object, check_undefined_arg2; |
2745 Label load_arg2, done; | 2746 Label load_arg2, done; |
2746 | 2747 |
2747 // Test if arg1 is a Smi. | 2748 // Test if arg1 is a Smi. |
2748 __ JumpIfNotSmi(edx, &arg1_is_object, Label::kNear); | 2749 if (left_type == BinaryOpIC::SMI) { |
2750 __ JumpIfNotSmi(edx, conversion_failure); | |
2751 } else { | |
2752 __ JumpIfNotSmi(edx, &arg1_is_object, Label::kNear); | |
2753 } | |
2749 | 2754 |
2750 __ SmiUntag(edx); | 2755 __ SmiUntag(edx); |
2751 __ jmp(&load_arg2); | 2756 __ jmp(&load_arg2); |
2752 | 2757 |
2753 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 2758 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
2754 __ bind(&check_undefined_arg1); | 2759 __ bind(&check_undefined_arg1); |
2755 Factory* factory = masm->isolate()->factory(); | 2760 Factory* factory = masm->isolate()->factory(); |
2756 __ cmp(edx, factory->undefined_value()); | 2761 __ cmp(edx, factory->undefined_value()); |
2757 __ j(not_equal, conversion_failure); | 2762 __ j(not_equal, conversion_failure); |
2758 __ mov(edx, Immediate(0)); | 2763 __ mov(edx, Immediate(0)); |
2759 __ jmp(&load_arg2); | 2764 __ jmp(&load_arg2); |
2760 | 2765 |
2761 __ bind(&arg1_is_object); | 2766 __ bind(&arg1_is_object); |
2762 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 2767 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
2763 __ cmp(ebx, factory->heap_number_map()); | 2768 __ cmp(ebx, factory->heap_number_map()); |
2764 __ j(not_equal, &check_undefined_arg1); | 2769 if (left_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) { |
2765 | 2770 CpuFeatures::Scope use_sse2(SSE2); |
2766 // Get the untagged integer version of the edx heap number in ecx. | 2771 __ j(not_equal, conversion_failure); |
2767 IntegerConvert(masm, edx, use_sse3, conversion_failure); | 2772 // Get the untagged integer version of the edx heap number in ecx. |
2773 ConvertHeapNumberToInt32(masm, edx, conversion_failure); | |
2774 } else { | |
2775 __ j(not_equal, &check_undefined_arg1); | |
2776 // Get the untagged integer version of the edx heap number in ecx. | |
2777 IntegerConvert(masm, edx, use_sse3, conversion_failure); | |
2778 } | |
2768 __ mov(edx, ecx); | 2779 __ mov(edx, ecx); |
2769 | 2780 |
2770 // Here edx has the untagged integer, eax has a Smi or a heap number. | 2781 // Here edx has the untagged integer, eax has a Smi or a heap number. |
2771 __ bind(&load_arg2); | 2782 __ bind(&load_arg2); |
2772 | 2783 |
2773 // Test if arg2 is a Smi. | 2784 // Test if arg2 is a Smi. |
2774 __ JumpIfNotSmi(eax, &arg2_is_object, Label::kNear); | 2785 if (right_type == BinaryOpIC::SMI) { |
2786 __ JumpIfNotSmi(eax, conversion_failure); | |
2787 } else { | |
2788 __ JumpIfNotSmi(eax, &arg2_is_object, Label::kNear); | |
2789 } | |
2775 | 2790 |
2776 __ SmiUntag(eax); | 2791 __ SmiUntag(eax); |
2777 __ mov(ecx, eax); | 2792 __ mov(ecx, eax); |
2778 __ jmp(&done); | 2793 __ jmp(&done); |
2779 | 2794 |
2780 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 2795 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
2781 __ bind(&check_undefined_arg2); | 2796 __ bind(&check_undefined_arg2); |
2782 __ cmp(eax, factory->undefined_value()); | 2797 __ cmp(eax, factory->undefined_value()); |
2783 __ j(not_equal, conversion_failure); | 2798 __ j(not_equal, conversion_failure); |
2784 __ mov(ecx, Immediate(0)); | 2799 __ mov(ecx, Immediate(0)); |
2785 __ jmp(&done); | 2800 __ jmp(&done); |
2786 | 2801 |
2787 __ bind(&arg2_is_object); | 2802 __ bind(&arg2_is_object); |
2788 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2803 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
2789 __ cmp(ebx, factory->heap_number_map()); | 2804 __ cmp(ebx, factory->heap_number_map()); |
2790 __ j(not_equal, &check_undefined_arg2); | 2805 if (right_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) { |
2806 CpuFeatures::Scope use_sse2(SSE2); | |
2807 __ j(not_equal, conversion_failure); | |
2808 // Get the untagged integer version of the eax heap number in ecx. | |
2809 ConvertHeapNumberToInt32(masm, eax, conversion_failure); | |
2810 } else { | |
2811 __ j(not_equal, &check_undefined_arg2); | |
2812 // Get the untagged integer version of the eax heap number in ecx. | |
2813 IntegerConvert(masm, eax, use_sse3, conversion_failure); | |
2814 } | |
2791 | 2815 |
2792 // Get the untagged integer version of the eax heap number in ecx. | |
2793 IntegerConvert(masm, eax, use_sse3, conversion_failure); | |
2794 __ bind(&done); | 2816 __ bind(&done); |
2795 __ mov(eax, edx); | 2817 __ mov(eax, edx); |
2796 } | 2818 } |
2797 | 2819 |
2798 | 2820 |
2799 void FloatingPointHelper::CheckLoadedIntegersWereInt32(MacroAssembler* masm, | |
2800 bool use_sse3, | |
2801 Label* not_int32) { | |
2802 return; | |
Jakob Kummerow
2013/02/07 15:28:35
Who are we kidding?
| |
2803 } | |
2804 | |
2805 | |
2806 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, | 2821 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, |
2807 Register number) { | 2822 Register number) { |
2808 Label load_smi, done; | 2823 Label load_smi, done; |
2809 | 2824 |
2810 __ JumpIfSmi(number, &load_smi, Label::kNear); | 2825 __ JumpIfSmi(number, &load_smi, Label::kNear); |
2811 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); | 2826 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); |
2812 __ jmp(&done, Label::kNear); | 2827 __ jmp(&done, Label::kNear); |
2813 | 2828 |
2814 __ bind(&load_smi); | 2829 __ bind(&load_smi); |
2815 __ SmiUntag(number); | 2830 __ SmiUntag(number); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2890 | 2905 |
2891 __ mov(scratch, right); | 2906 __ mov(scratch, right); |
2892 __ SmiUntag(scratch); | 2907 __ SmiUntag(scratch); |
2893 __ cvtsi2sd(xmm1, scratch); | 2908 __ cvtsi2sd(xmm1, scratch); |
2894 } | 2909 } |
2895 | 2910 |
2896 | 2911 |
2897 void FloatingPointHelper::CheckSSE2OperandsAreInt32(MacroAssembler* masm, | 2912 void FloatingPointHelper::CheckSSE2OperandsAreInt32(MacroAssembler* masm, |
2898 Label* non_int32, | 2913 Label* non_int32, |
2899 Register scratch) { | 2914 Register scratch) { |
2900 CheckSSE2OperandIsInt32(masm, non_int32, xmm0, scratch, xmm2); | 2915 CheckSSE2OperandIsInt32(masm, non_int32, xmm0, scratch, scratch, xmm2); |
2901 CheckSSE2OperandIsInt32(masm, non_int32, xmm1, scratch, xmm2); | 2916 CheckSSE2OperandIsInt32(masm, non_int32, xmm1, scratch, scratch, xmm2); |
2902 } | 2917 } |
2903 | 2918 |
2904 | 2919 |
2905 void FloatingPointHelper::CheckSSE2OperandIsInt32(MacroAssembler* masm, | 2920 void FloatingPointHelper::CheckSSE2OperandIsInt32(MacroAssembler* masm, |
2906 Label* non_int32, | 2921 Label* non_int32, |
2907 XMMRegister operand, | 2922 XMMRegister operand, |
2923 Register int32_result, | |
2908 Register scratch, | 2924 Register scratch, |
2909 XMMRegister xmm_scratch) { | 2925 XMMRegister xmm_scratch) { |
2910 __ cvttsd2si(scratch, Operand(operand)); | 2926 __ cvttsd2si(int32_result, Operand(operand)); |
2911 __ cvtsi2sd(xmm_scratch, scratch); | 2927 __ cvtsi2sd(xmm_scratch, int32_result); |
2912 __ pcmpeqd(xmm_scratch, operand); | 2928 __ pcmpeqd(xmm_scratch, operand); |
2913 __ movmskps(scratch, xmm_scratch); | 2929 __ movmskps(scratch, xmm_scratch); |
2914 // Two least significant bits should be both set. | 2930 // Two least significant bits should be both set. |
2915 __ not_(scratch); | 2931 __ not_(scratch); |
2916 __ test(scratch, Immediate(3)); | 2932 __ test(scratch, Immediate(3)); |
2917 __ j(not_zero, non_int32); | 2933 __ j(not_zero, non_int32); |
2918 } | 2934 } |
2919 | 2935 |
2920 | 2936 |
2921 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, | 2937 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2991 __ JumpIfSmi(eax, &done, Label::kNear); | 3007 __ JumpIfSmi(eax, &done, Label::kNear); |
2992 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); | 3008 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); |
2993 __ cmp(scratch, factory->heap_number_map()); | 3009 __ cmp(scratch, factory->heap_number_map()); |
2994 __ j(not_equal, non_float); // argument in eax is not a number -> NaN | 3010 __ j(not_equal, non_float); // argument in eax is not a number -> NaN |
2995 | 3011 |
2996 // Fall-through: Both operands are numbers. | 3012 // Fall-through: Both operands are numbers. |
2997 __ bind(&done); | 3013 __ bind(&done); |
2998 } | 3014 } |
2999 | 3015 |
3000 | 3016 |
3001 void FloatingPointHelper::CheckFloatOperandsAreInt32(MacroAssembler* masm, | |
Jakob Kummerow
2013/02/07 15:28:35
This seems rather similar in functionality to Floa
| |
3002 Label* non_int32) { | |
3003 return; | |
3004 } | |
3005 | |
3006 | |
3007 void MathPowStub::Generate(MacroAssembler* masm) { | 3017 void MathPowStub::Generate(MacroAssembler* masm) { |
3008 CpuFeatures::Scope use_sse2(SSE2); | 3018 CpuFeatures::Scope use_sse2(SSE2); |
3009 Factory* factory = masm->isolate()->factory(); | 3019 Factory* factory = masm->isolate()->factory(); |
3010 const Register exponent = eax; | 3020 const Register exponent = eax; |
3011 const Register base = edx; | 3021 const Register base = edx; |
3012 const Register scratch = ecx; | 3022 const Register scratch = ecx; |
3013 const XMMRegister double_result = xmm3; | 3023 const XMMRegister double_result = xmm3; |
3014 const XMMRegister double_base = xmm2; | 3024 const XMMRegister double_base = xmm2; |
3015 const XMMRegister double_exponent = xmm1; | 3025 const XMMRegister double_exponent = xmm1; |
3016 const XMMRegister double_scratch = xmm4; | 3026 const XMMRegister double_scratch = xmm4; |
(...skipping 4670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7687 // Restore ecx. | 7697 // Restore ecx. |
7688 __ pop(ecx); | 7698 __ pop(ecx); |
7689 __ ret(0); | 7699 __ ret(0); |
7690 } | 7700 } |
7691 | 7701 |
7692 #undef __ | 7702 #undef __ |
7693 | 7703 |
7694 } } // namespace v8::internal | 7704 } } // namespace v8::internal |
7695 | 7705 |
7696 #endif // V8_TARGET_ARCH_IA32 | 7706 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |