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 |