| 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 |