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

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 15735005: Collect type feedback for power-of-2 right operands in BinaryOps. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Handle INT32. Avoid transition interference. Cleanup. Rebased. Created 7 years, 7 months 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
OLDNEW
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
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
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
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, &not_int32); 1760 __ JumpIfNotSmi(edx, &not_int32);
1760 } 1761 }
1761 if (right_type_ == BinaryOpIC::SMI) { 1762 if (right_type_ == BinaryOpIC::SMI) {
1762 __ JumpIfNotSmi(eax, &not_int32); 1763 __ JumpIfNotSmi(eax, &not_int32);
1763 } 1764 }
1764 FloatingPointHelper::LoadSSE2Operands(masm, &not_floats); 1765 FloatingPointHelper::LoadSSE2Operands(masm, &not_floats);
1765 FloatingPointHelper::CheckSSE2OperandsAreInt32(masm, &not_int32, ecx); 1766 FloatingPointHelper::CheckSSE2OperandIsInt32(
1767 masm, &not_int32, xmm0, ebx, ecx, xmm2);
1768 FloatingPointHelper::CheckSSE2OperandIsInt32(
1769 masm, &not_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
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(&not_floats); 1825 __ bind(&not_floats);
1818 __ bind(&not_int32); 1826 __ bind(&not_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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698