| 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 689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 // Test if operands are numbers (smi or HeapNumber objects), and load | 700 // Test if operands are numbers (smi or HeapNumber objects), and load |
| 701 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if | 701 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if |
| 702 // either operand is not a number. Operands are in edx and eax. | 702 // either operand is not a number. Operands are in edx and eax. |
| 703 // Leaves operands unchanged. | 703 // Leaves operands unchanged. |
| 704 static void LoadSSE2Operands(MacroAssembler* masm, Label* not_numbers); | 704 static void LoadSSE2Operands(MacroAssembler* masm, Label* not_numbers); |
| 705 | 705 |
| 706 // Similar to LoadSSE2Operands but assumes that both operands are smis. | 706 // Similar to LoadSSE2Operands but assumes that both operands are smis. |
| 707 // Expects operands in edx, eax. | 707 // Expects operands in edx, eax. |
| 708 static void LoadSSE2Smis(MacroAssembler* masm, Register scratch); | 708 static void LoadSSE2Smis(MacroAssembler* masm, Register scratch); |
| 709 | 709 |
| 710 // Checks that the two floating point numbers loaded into xmm0 and xmm1 | |
| 711 // have int32 values. | |
| 712 static void CheckSSE2OperandsAreInt32(MacroAssembler* masm, | |
| 713 Label* non_int32, | |
| 714 Register scratch); | |
| 715 | |
| 716 // Checks that |operand| has an int32 value. If |int32_result| is different | 710 // Checks that |operand| has an int32 value. If |int32_result| is different |
| 717 // from |scratch|, it will contain that int32 value. | 711 // from |scratch|, it will contain that int32 value. |
| 718 static void CheckSSE2OperandIsInt32(MacroAssembler* masm, | 712 static void CheckSSE2OperandIsInt32(MacroAssembler* masm, |
| 719 Label* non_int32, | 713 Label* non_int32, |
| 720 XMMRegister operand, | 714 XMMRegister operand, |
| 721 Register int32_result, | 715 Register int32_result, |
| 722 Register scratch, | 716 Register scratch, |
| 723 XMMRegister xmm_scratch); | 717 XMMRegister xmm_scratch); |
| 724 }; | 718 }; |
| 725 | 719 |
| (...skipping 878 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1604 __ mov(eax, ebx); | 1598 __ mov(eax, ebx); |
| 1605 break; | 1599 break; |
| 1606 | 1600 |
| 1607 default: | 1601 default: |
| 1608 break; | 1602 break; |
| 1609 } | 1603 } |
| 1610 } | 1604 } |
| 1611 | 1605 |
| 1612 | 1606 |
| 1613 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { | 1607 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { |
| 1614 Label call_runtime; | 1608 Label right_arg_changed, call_runtime; |
| 1615 | 1609 |
| 1616 switch (op_) { | 1610 switch (op_) { |
| 1617 case Token::ADD: | 1611 case Token::ADD: |
| 1618 case Token::SUB: | 1612 case Token::SUB: |
| 1619 case Token::MUL: | 1613 case Token::MUL: |
| 1620 case Token::DIV: | 1614 case Token::DIV: |
| 1621 break; | 1615 break; |
| 1622 case Token::MOD: | 1616 case Token::MOD: |
| 1623 case Token::BIT_OR: | 1617 case Token::BIT_OR: |
| 1624 case Token::BIT_AND: | 1618 case Token::BIT_AND: |
| 1625 case Token::BIT_XOR: | 1619 case Token::BIT_XOR: |
| 1626 case Token::SAR: | 1620 case Token::SAR: |
| 1627 case Token::SHL: | 1621 case Token::SHL: |
| 1628 case Token::SHR: | 1622 case Token::SHR: |
| 1629 GenerateRegisterArgsPush(masm); | 1623 GenerateRegisterArgsPush(masm); |
| 1630 break; | 1624 break; |
| 1631 default: | 1625 default: |
| 1632 UNREACHABLE(); | 1626 UNREACHABLE(); |
| 1633 } | 1627 } |
| 1634 | 1628 |
| 1629 if (op_ == Token::MOD && has_fixed_right_arg_) { |
| 1630 // It is guaranteed that the value will fit into a Smi, because if it |
| 1631 // didn't, we wouldn't be here, see BinaryOp_Patch. |
| 1632 __ cmp(eax, Immediate(Smi::FromInt(fixed_right_arg_value()))); |
| 1633 __ j(not_equal, &right_arg_changed); |
| 1634 } |
| 1635 |
| 1635 if (result_type_ == BinaryOpIC::UNINITIALIZED || | 1636 if (result_type_ == BinaryOpIC::UNINITIALIZED || |
| 1636 result_type_ == BinaryOpIC::SMI) { | 1637 result_type_ == BinaryOpIC::SMI) { |
| 1637 BinaryOpStub_GenerateSmiCode( | 1638 BinaryOpStub_GenerateSmiCode( |
| 1638 masm, &call_runtime, NO_HEAPNUMBER_RESULTS, op_); | 1639 masm, &call_runtime, NO_HEAPNUMBER_RESULTS, op_); |
| 1639 } else { | 1640 } else { |
| 1640 BinaryOpStub_GenerateSmiCode( | 1641 BinaryOpStub_GenerateSmiCode( |
| 1641 masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS, op_); | 1642 masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS, op_); |
| 1642 } | 1643 } |
| 1643 | 1644 |
| 1644 // Code falls through if the result is not returned as either a smi or heap | 1645 // Code falls through if the result is not returned as either a smi or heap |
| 1645 // number. | 1646 // number. |
| 1647 __ bind(&right_arg_changed); |
| 1646 switch (op_) { | 1648 switch (op_) { |
| 1647 case Token::ADD: | 1649 case Token::ADD: |
| 1648 case Token::SUB: | 1650 case Token::SUB: |
| 1649 case Token::MUL: | 1651 case Token::MUL: |
| 1650 case Token::DIV: | 1652 case Token::DIV: |
| 1651 GenerateTypeTransition(masm); | 1653 GenerateTypeTransition(masm); |
| 1652 break; | 1654 break; |
| 1653 case Token::MOD: | 1655 case Token::MOD: |
| 1654 case Token::BIT_OR: | 1656 case Token::BIT_OR: |
| 1655 case Token::BIT_AND: | 1657 case Token::BIT_AND: |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1738 Label call_runtime; | 1740 Label call_runtime; |
| 1739 ASSERT(Max(left_type_, right_type_) == BinaryOpIC::INT32); | 1741 ASSERT(Max(left_type_, right_type_) == BinaryOpIC::INT32); |
| 1740 | 1742 |
| 1741 // Floating point case. | 1743 // Floating point case. |
| 1742 switch (op_) { | 1744 switch (op_) { |
| 1743 case Token::ADD: | 1745 case Token::ADD: |
| 1744 case Token::SUB: | 1746 case Token::SUB: |
| 1745 case Token::MUL: | 1747 case Token::MUL: |
| 1746 case Token::DIV: | 1748 case Token::DIV: |
| 1747 case Token::MOD: { | 1749 case Token::MOD: { |
| 1748 Label not_floats; | 1750 Label not_floats, not_int32, right_arg_changed; |
| 1749 Label not_int32; | |
| 1750 if (CpuFeatures::IsSupported(SSE2)) { | 1751 if (CpuFeatures::IsSupported(SSE2)) { |
| 1751 CpuFeatureScope use_sse2(masm, SSE2); | 1752 CpuFeatureScope use_sse2(masm, SSE2); |
| 1752 // It could be that only SMIs have been seen at either the left | 1753 // It could be that only SMIs have been seen at either the left |
| 1753 // or the right operand. For precise type feedback, patch the IC | 1754 // or the right operand. For precise type feedback, patch the IC |
| 1754 // again if this changes. | 1755 // again if this changes. |
| 1755 // In theory, we would need the same check in the non-SSE2 case, | 1756 // In theory, we would need the same check in the non-SSE2 case, |
| 1756 // but since we don't support Crankshaft on such hardware we can | 1757 // but since we don't support Crankshaft on such hardware we can |
| 1757 // afford not to care about precise type feedback. | 1758 // afford not to care about precise type feedback. |
| 1758 if (left_type_ == BinaryOpIC::SMI) { | 1759 if (left_type_ == BinaryOpIC::SMI) { |
| 1759 __ JumpIfNotSmi(edx, ¬_int32); | 1760 __ JumpIfNotSmi(edx, ¬_int32); |
| 1760 } | 1761 } |
| 1761 if (right_type_ == BinaryOpIC::SMI) { | 1762 if (right_type_ == BinaryOpIC::SMI) { |
| 1762 __ JumpIfNotSmi(eax, ¬_int32); | 1763 __ JumpIfNotSmi(eax, ¬_int32); |
| 1763 } | 1764 } |
| 1764 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats); | 1765 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats); |
| 1765 FloatingPointHelper::CheckSSE2OperandsAreInt32(masm, ¬_int32, ecx); | 1766 FloatingPointHelper::CheckSSE2OperandIsInt32( |
| 1767 masm, ¬_int32, xmm0, ebx, ecx, xmm2); |
| 1768 FloatingPointHelper::CheckSSE2OperandIsInt32( |
| 1769 masm, ¬_int32, xmm1, edi, ecx, xmm2); |
| 1766 if (op_ == Token::MOD) { | 1770 if (op_ == Token::MOD) { |
| 1771 if (has_fixed_right_arg_) { |
| 1772 __ cmp(edi, Immediate(fixed_right_arg_value())); |
| 1773 __ j(not_equal, &right_arg_changed); |
| 1774 } |
| 1767 GenerateRegisterArgsPush(masm); | 1775 GenerateRegisterArgsPush(masm); |
| 1768 __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION); | 1776 __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION); |
| 1769 } else { | 1777 } else { |
| 1770 switch (op_) { | 1778 switch (op_) { |
| 1771 case Token::ADD: __ addsd(xmm0, xmm1); break; | 1779 case Token::ADD: __ addsd(xmm0, xmm1); break; |
| 1772 case Token::SUB: __ subsd(xmm0, xmm1); break; | 1780 case Token::SUB: __ subsd(xmm0, xmm1); break; |
| 1773 case Token::MUL: __ mulsd(xmm0, xmm1); break; | 1781 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
| 1774 case Token::DIV: __ divsd(xmm0, xmm1); break; | 1782 case Token::DIV: __ divsd(xmm0, xmm1); break; |
| 1775 default: UNREACHABLE(); | 1783 default: UNREACHABLE(); |
| 1776 } | 1784 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1809 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 1817 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 1810 __ ret(0); | 1818 __ ret(0); |
| 1811 __ bind(&after_alloc_failure); | 1819 __ bind(&after_alloc_failure); |
| 1812 __ fstp(0); // Pop FPU stack before calling runtime. | 1820 __ fstp(0); // Pop FPU stack before calling runtime. |
| 1813 __ jmp(&call_runtime); | 1821 __ jmp(&call_runtime); |
| 1814 } | 1822 } |
| 1815 } | 1823 } |
| 1816 | 1824 |
| 1817 __ bind(¬_floats); | 1825 __ bind(¬_floats); |
| 1818 __ bind(¬_int32); | 1826 __ bind(¬_int32); |
| 1827 __ bind(&right_arg_changed); |
| 1819 GenerateTypeTransition(masm); | 1828 GenerateTypeTransition(masm); |
| 1820 break; | 1829 break; |
| 1821 } | 1830 } |
| 1822 | 1831 |
| 1823 case Token::BIT_OR: | 1832 case Token::BIT_OR: |
| 1824 case Token::BIT_AND: | 1833 case Token::BIT_AND: |
| 1825 case Token::BIT_XOR: | 1834 case Token::BIT_XOR: |
| 1826 case Token::SAR: | 1835 case Token::SAR: |
| 1827 case Token::SHL: | 1836 case Token::SHL: |
| 1828 case Token::SHR: { | 1837 case Token::SHR: { |
| (...skipping 1071 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2900 ASSERT(!scratch.is(right)); // We're about to clobber scratch. | 2909 ASSERT(!scratch.is(right)); // We're about to clobber scratch. |
| 2901 __ SmiUntag(scratch); | 2910 __ SmiUntag(scratch); |
| 2902 __ cvtsi2sd(xmm0, scratch); | 2911 __ cvtsi2sd(xmm0, scratch); |
| 2903 | 2912 |
| 2904 __ mov(scratch, right); | 2913 __ mov(scratch, right); |
| 2905 __ SmiUntag(scratch); | 2914 __ SmiUntag(scratch); |
| 2906 __ cvtsi2sd(xmm1, scratch); | 2915 __ cvtsi2sd(xmm1, scratch); |
| 2907 } | 2916 } |
| 2908 | 2917 |
| 2909 | 2918 |
| 2910 void FloatingPointHelper::CheckSSE2OperandsAreInt32(MacroAssembler* masm, | |
| 2911 Label* non_int32, | |
| 2912 Register scratch) { | |
| 2913 CheckSSE2OperandIsInt32(masm, non_int32, xmm0, scratch, scratch, xmm2); | |
| 2914 CheckSSE2OperandIsInt32(masm, non_int32, xmm1, scratch, scratch, xmm2); | |
| 2915 } | |
| 2916 | |
| 2917 | |
| 2918 void FloatingPointHelper::CheckSSE2OperandIsInt32(MacroAssembler* masm, | 2919 void FloatingPointHelper::CheckSSE2OperandIsInt32(MacroAssembler* masm, |
| 2919 Label* non_int32, | 2920 Label* non_int32, |
| 2920 XMMRegister operand, | 2921 XMMRegister operand, |
| 2921 Register int32_result, | 2922 Register int32_result, |
| 2922 Register scratch, | 2923 Register scratch, |
| 2923 XMMRegister xmm_scratch) { | 2924 XMMRegister xmm_scratch) { |
| 2924 __ cvttsd2si(int32_result, Operand(operand)); | 2925 __ cvttsd2si(int32_result, Operand(operand)); |
| 2925 __ cvtsi2sd(xmm_scratch, int32_result); | 2926 __ cvtsi2sd(xmm_scratch, int32_result); |
| 2926 __ pcmpeqd(xmm_scratch, operand); | 2927 __ pcmpeqd(xmm_scratch, operand); |
| 2927 __ movmskps(scratch, xmm_scratch); | 2928 __ movmskps(scratch, xmm_scratch); |
| (...skipping 5135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8063 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 8064 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
| 8064 } | 8065 } |
| 8065 } | 8066 } |
| 8066 | 8067 |
| 8067 | 8068 |
| 8068 #undef __ | 8069 #undef __ |
| 8069 | 8070 |
| 8070 } } // namespace v8::internal | 8071 } } // namespace v8::internal |
| 8071 | 8072 |
| 8072 #endif // V8_TARGET_ARCH_IA32 | 8073 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |