Chromium Code Reviews| 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 |