OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 4866 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4877 // | 4877 // |
4878 // We combine the overflow and the smi check if we could | 4878 // We combine the overflow and the smi check if we could |
4879 // successfully allocate a temporary byte register. | 4879 // successfully allocate a temporary byte register. |
4880 if (tmp.is_valid()) { | 4880 if (tmp.is_valid()) { |
4881 __ setcc(overflow, tmp.reg()); | 4881 __ setcc(overflow, tmp.reg()); |
4882 __ or_(Operand(tmp.reg()), value.reg()); | 4882 __ or_(Operand(tmp.reg()), value.reg()); |
4883 __ test(tmp.reg(), Immediate(kSmiTagMask)); | 4883 __ test(tmp.reg(), Immediate(kSmiTagMask)); |
4884 tmp.Unuse(); | 4884 tmp.Unuse(); |
4885 deferred->enter()->Branch(not_zero, &value, not_taken); | 4885 deferred->enter()->Branch(not_zero, &value, not_taken); |
4886 } else { // Otherwise we test separately for overflow and smi check. | 4886 } else { // Otherwise we test separately for overflow and smi check. |
| 4887 deferred->SetEntryFrame(&value); |
4887 deferred->enter()->Branch(overflow, &value, not_taken); | 4888 deferred->enter()->Branch(overflow, &value, not_taken); |
4888 __ test(value.reg(), Immediate(kSmiTagMask)); | 4889 __ test(value.reg(), Immediate(kSmiTagMask)); |
4889 deferred->enter()->Branch(not_zero, &value, not_taken); | 4890 deferred->enter()->Branch(not_zero, &value, not_taken); |
4890 } | 4891 } |
4891 | 4892 |
4892 // Store the new value in the target if not const. | 4893 // Store the new value in the target if not const. |
4893 deferred->BindExit(&value); | 4894 deferred->BindExit(&value); |
4894 frame_->Push(&value); | 4895 frame_->Push(&value); |
4895 if (!is_const) { | 4896 if (!is_const) { |
4896 target.SetValue(NOT_CONST_INIT); | 4897 target.SetValue(NOT_CONST_INIT); |
(...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5733 ASSERT(answer.is_valid()); | 5734 ASSERT(answer.is_valid()); |
5734 // Perform the smi check. | 5735 // Perform the smi check. |
5735 if (left->reg().is(right->reg())) { | 5736 if (left->reg().is(right->reg())) { |
5736 __ test(left->reg(), Immediate(kSmiTagMask)); | 5737 __ test(left->reg(), Immediate(kSmiTagMask)); |
5737 } else { | 5738 } else { |
5738 __ mov(answer.reg(), left->reg()); | 5739 __ mov(answer.reg(), left->reg()); |
5739 __ or_(answer.reg(), Operand(right->reg())); | 5740 __ or_(answer.reg(), Operand(right->reg())); |
5740 ASSERT(kSmiTag == 0); // adjust zero check if not the case | 5741 ASSERT(kSmiTag == 0); // adjust zero check if not the case |
5741 __ test(answer.reg(), Immediate(kSmiTagMask)); | 5742 __ test(answer.reg(), Immediate(kSmiTagMask)); |
5742 } | 5743 } |
5743 enter()->Branch(not_zero, left, right, not_taken); | |
5744 | |
5745 // All operations start by copying the left argument into answer. | |
5746 __ mov(answer.reg(), left->reg()); | |
5747 switch (op_) { | 5744 switch (op_) { |
5748 case Token::ADD: | 5745 case Token::ADD: |
| 5746 SetEntryFrame(left, right); |
| 5747 enter()->Branch(not_zero, left, right, not_taken); |
| 5748 __ mov(answer.reg(), left->reg()); |
5749 __ add(answer.reg(), Operand(right->reg())); // add optimistically | 5749 __ add(answer.reg(), Operand(right->reg())); // add optimistically |
5750 enter()->Branch(overflow, left, right, not_taken); | 5750 enter()->Branch(overflow, left, right, not_taken); |
5751 break; | 5751 break; |
5752 | 5752 |
5753 case Token::SUB: | 5753 case Token::SUB: |
| 5754 SetEntryFrame(left, right); |
| 5755 enter()->Branch(not_zero, left, right, not_taken); |
| 5756 __ mov(answer.reg(), left->reg()); |
5754 __ sub(answer.reg(), Operand(right->reg())); // subtract optimistically | 5757 __ sub(answer.reg(), Operand(right->reg())); // subtract optimistically |
5755 enter()->Branch(overflow, left, right, not_taken); | 5758 enter()->Branch(overflow, left, right, not_taken); |
5756 break; | 5759 break; |
5757 | 5760 |
5758 case Token::MUL: { | 5761 case Token::MUL: { |
| 5762 SetEntryFrame(left, right); |
| 5763 enter()->Branch(not_zero, left, right, not_taken); |
| 5764 __ mov(answer.reg(), left->reg()); |
5759 // If the smi tag is 0 we can just leave the tag on one operand. | 5765 // If the smi tag is 0 we can just leave the tag on one operand. |
5760 ASSERT(kSmiTag == 0); // adjust code below if not the case | 5766 ASSERT(kSmiTag == 0); // adjust code below if not the case |
5761 // Remove tag from the left operand (but keep sign). | 5767 // Remove tag from the left operand (but keep sign). |
5762 // Left hand operand has been copied into answer. | 5768 // Left hand operand has been copied into answer. |
5763 __ sar(answer.reg(), kSmiTagSize); | 5769 __ sar(answer.reg(), kSmiTagSize); |
5764 // Do multiplication of smis, leaving result in answer. | 5770 // Do multiplication of smis, leaving result in answer. |
5765 __ imul(answer.reg(), Operand(right->reg())); | 5771 __ imul(answer.reg(), Operand(right->reg())); |
5766 // Go slow on overflows. | 5772 // Go slow on overflows. |
5767 enter()->Branch(overflow, left, right, not_taken); | 5773 enter()->Branch(overflow, left, right, not_taken); |
5768 // Check for negative zero result. If product is zero, | 5774 // Check for negative zero result. If product is zero, |
5769 // and one argument is negative, go to slow case. | 5775 // and one argument is negative, go to slow case. |
5770 // The frame is unchanged in this block, so local control flow can | 5776 // The frame is unchanged in this block, so local control flow can |
5771 // use a Label rather than a JumpTarget. | 5777 // use a Label rather than a JumpTarget. |
5772 Label non_zero_result; | 5778 Label non_zero_result; |
5773 __ test(answer.reg(), Operand(answer.reg())); | 5779 __ test(answer.reg(), Operand(answer.reg())); |
5774 __ j(not_zero, &non_zero_result, taken); | 5780 __ j(not_zero, &non_zero_result, taken); |
5775 __ mov(answer.reg(), left->reg()); | 5781 __ mov(answer.reg(), left->reg()); |
5776 __ or_(answer.reg(), Operand(right->reg())); | 5782 __ or_(answer.reg(), Operand(right->reg())); |
5777 enter()->Branch(negative, left, right, not_taken); | 5783 enter()->Branch(negative, left, right, not_taken); |
5778 __ xor_(answer.reg(), Operand(answer.reg())); // Positive 0 is correct. | 5784 __ xor_(answer.reg(), Operand(answer.reg())); // Positive 0 is correct. |
5779 __ bind(&non_zero_result); | 5785 __ bind(&non_zero_result); |
5780 break; | 5786 break; |
5781 } | 5787 } |
5782 | 5788 |
5783 case Token::DIV: // Fall through. | 5789 case Token::DIV: // Fall through. |
5784 case Token::MOD: { | 5790 case Token::MOD: { |
| 5791 enter()->Branch(not_zero, left, right, not_taken); |
| 5792 __ mov(answer.reg(), left->reg()); |
5785 // Div and mod use the registers eax and edx. Left and right must | 5793 // Div and mod use the registers eax and edx. Left and right must |
5786 // be preserved, because the original operands are needed if we switch | 5794 // be preserved, because the original operands are needed if we switch |
5787 // to the slow case. Move them if either is in eax or edx. | 5795 // to the slow case. Move them if either is in eax or edx. |
5788 // The Result answer should be changed into an alias for eax. | 5796 // The Result answer should be changed into an alias for eax. |
5789 // Precondition: | 5797 // Precondition: |
5790 // The Results left and right are valid. They may be the same register, | 5798 // The Results left and right are valid. They may be the same register, |
5791 // and may be unspilled. The Result answer is valid and is distinct | 5799 // and may be unspilled. The Result answer is valid and is distinct |
5792 // from left and right, and is spilled. | 5800 // from left and right, and is spilled. |
5793 // The value in left is copied to answer. | 5801 // The value in left is copied to answer. |
5794 | 5802 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5912 __ j(not_zero, &non_zero_result, taken); | 5920 __ j(not_zero, &non_zero_result, taken); |
5913 __ test(left->reg(), Operand(left->reg())); | 5921 __ test(left->reg(), Operand(left->reg())); |
5914 enter()->Branch(negative, left, right, not_taken); | 5922 enter()->Branch(negative, left, right, not_taken); |
5915 __ bind(&non_zero_result); | 5923 __ bind(&non_zero_result); |
5916 // The answer is in edx. | 5924 // The answer is in edx. |
5917 answer = reg_edx; | 5925 answer = reg_edx; |
5918 } | 5926 } |
5919 break; | 5927 break; |
5920 } | 5928 } |
5921 case Token::BIT_OR: | 5929 case Token::BIT_OR: |
| 5930 enter()->Branch(not_zero, left, right, not_taken); |
| 5931 __ mov(answer.reg(), left->reg()); |
5922 __ or_(answer.reg(), Operand(right->reg())); | 5932 __ or_(answer.reg(), Operand(right->reg())); |
5923 break; | 5933 break; |
5924 | 5934 |
5925 case Token::BIT_AND: | 5935 case Token::BIT_AND: |
| 5936 enter()->Branch(not_zero, left, right, not_taken); |
| 5937 __ mov(answer.reg(), left->reg()); |
5926 __ and_(answer.reg(), Operand(right->reg())); | 5938 __ and_(answer.reg(), Operand(right->reg())); |
5927 break; | 5939 break; |
5928 | 5940 |
5929 case Token::BIT_XOR: | 5941 case Token::BIT_XOR: |
| 5942 enter()->Branch(not_zero, left, right, not_taken); |
| 5943 __ mov(answer.reg(), left->reg()); |
5930 __ xor_(answer.reg(), Operand(right->reg())); | 5944 __ xor_(answer.reg(), Operand(right->reg())); |
5931 break; | 5945 break; |
5932 | 5946 |
5933 case Token::SHL: | 5947 case Token::SHL: |
5934 case Token::SHR: | 5948 case Token::SHR: |
5935 case Token::SAR: | 5949 case Token::SAR: |
| 5950 enter()->Branch(not_zero, left, right, not_taken); |
| 5951 __ mov(answer.reg(), left->reg()); |
5936 // Move right into ecx. | 5952 // Move right into ecx. |
5937 // Left is in two registers already, so even if left or answer is ecx, | 5953 // Left is in two registers already, so even if left or answer is ecx, |
5938 // we can move right to it, and use the other one. | 5954 // we can move right to it, and use the other one. |
5939 // Right operand must be in register cl because x86 likes it that way. | 5955 // Right operand must be in register cl because x86 likes it that way. |
5940 if (right->reg().is(ecx)) { | 5956 if (right->reg().is(ecx)) { |
5941 // Right is already in the right place. Left may be in the | 5957 // Right is already in the right place. Left may be in the |
5942 // same register, which causes problems. Always use answer | 5958 // same register, which causes problems. Always use answer |
5943 // instead of left, even if left is not ecx, since this avoids | 5959 // instead of left, even if left is not ecx, since this avoids |
5944 // spilling left. | 5960 // spilling left. |
5945 *left = answer; | 5961 *left = answer; |
(...skipping 1311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7257 | 7273 |
7258 // Slow-case: Go through the JavaScript implementation. | 7274 // Slow-case: Go through the JavaScript implementation. |
7259 __ bind(&slow); | 7275 __ bind(&slow); |
7260 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 7276 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
7261 } | 7277 } |
7262 | 7278 |
7263 | 7279 |
7264 #undef __ | 7280 #undef __ |
7265 | 7281 |
7266 } } // namespace v8::internal | 7282 } } // namespace v8::internal |
OLD | NEW |