Chromium Code Reviews| 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 5717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5728 __ ret(1 * kPointerSize); | 5728 __ ret(1 * kPointerSize); |
| 5729 __ bind(&false_result); | 5729 __ bind(&false_result); |
| 5730 __ mov(eax, 0); | 5730 __ mov(eax, 0); |
| 5731 __ ret(1 * kPointerSize); | 5731 __ ret(1 * kPointerSize); |
| 5732 } | 5732 } |
| 5733 | 5733 |
| 5734 | 5734 |
| 5735 Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left, | 5735 Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left, |
| 5736 Result* right) { | 5736 Result* right) { |
| 5737 MacroAssembler* masm = cgen()->masm(); | 5737 MacroAssembler* masm = cgen()->masm(); |
| 5738 // Perform fast-case smi code for the operation (left <op> right) and | |
| 5739 // returns the result in a Result. | |
| 5740 // If any fast-case tests fail, it jumps to the slow-case deferred code, | |
| 5741 // which calls the binary operation stub, with the arguments (in registers) | |
| 5742 // on top of the frame. | |
| 5743 // Consumes its arguments (sets left and right to invalid and frees their | |
| 5744 // registers). | |
| 5745 | 5738 |
| 5739 // Special handling of div and mod because they use fixed registers. | |
| 5740 if (op_ == Token::DIV || op_ == Token::MOD) { | |
| 5741 // We need eax as the quotient register, edx as the remainder | |
| 5742 // register, neither left nor right in eax or edx, and left copied | |
| 5743 // to eax. | |
| 5744 Result quotient; | |
| 5745 Result remainder; | |
| 5746 bool left_is_in_eax = false; | |
| 5747 // Step 1: get eax for quotient. | |
| 5748 if ((left->is_register() && left->reg().is(eax)) || | |
| 5749 (right->is_register() && right->reg().is(eax))) { | |
| 5750 // One or both is in eax. Use a fresh non-edx register for | |
| 5751 // them. | |
| 5752 Result fresh = cgen()->allocator()->Allocate(); | |
| 5753 ASSERT(fresh.is_valid()); | |
| 5754 if (fresh.reg().is(edx)) { | |
| 5755 remainder = fresh; | |
| 5756 fresh = cgen()->allocator()->Allocate(); | |
| 5757 ASSERT(fresh.is_valid()); | |
| 5758 } | |
| 5759 if (left->is_register() && left->reg().is(eax)) { | |
| 5760 quotient = *left; | |
| 5761 *left = fresh; | |
| 5762 left_is_in_eax = true; | |
| 5763 } | |
| 5764 if (right->is_register() && right->reg().is(eax)) { | |
| 5765 quotient = *right; | |
| 5766 *right = fresh; | |
| 5767 } | |
| 5768 __ mov(fresh.reg(), eax); | |
| 5769 } else { | |
| 5770 // Neither left nor right is in eax. | |
| 5771 quotient = cgen()->allocator()->Allocate(eax); | |
| 5772 } | |
| 5773 ASSERT(quotient.is_register() && quotient.reg().is(eax)); | |
| 5774 ASSERT(!(left->is_register() && left->reg().is(eax))); | |
| 5775 ASSERT(!(right->is_register() && right->reg().is(eax))); | |
| 5776 | |
| 5777 // Step 2: get edx for remainder if necessary. | |
| 5778 if (!(remainder.is_register() && remainder.reg().is(edx))) { | |
|
William Hesse
2009/06/02 09:11:54
remainder is either invalid or edx at this point,
Kevin Millikin (Chromium)
2009/06/02 10:37:00
Thanks. I've changed it to !remainder.is_valid()
| |
| 5779 if ((left->is_register() && left->reg().is(edx)) || | |
| 5780 (right->is_register() && right->reg().is(edx))) { | |
| 5781 Result fresh = cgen()->allocator()->Allocate(); | |
| 5782 ASSERT(fresh.is_valid()); | |
| 5783 if (left->is_register() && left->reg().is(edx)) { | |
| 5784 remainder = *left; | |
| 5785 *left = fresh; | |
| 5786 } | |
| 5787 if (right->is_register() && right->reg().is(edx)) { | |
| 5788 remainder = *right; | |
| 5789 *right = fresh; | |
| 5790 } | |
| 5791 __ mov(fresh.reg(), edx); | |
| 5792 } else { | |
| 5793 // Neither left nor right is in edx. | |
| 5794 remainder = cgen()->allocator()->Allocate(edx); | |
| 5795 } | |
| 5796 } | |
| 5797 ASSERT(remainder.is_register() && remainder.reg().is(edx)); | |
| 5798 ASSERT(!(left->is_register() && left->reg().is(edx))); | |
| 5799 ASSERT(!(right->is_register() && right->reg().is(edx))); | |
| 5800 | |
| 5801 left->ToRegister(); | |
| 5802 right->ToRegister(); | |
| 5803 cgen()->frame()->Spill(quotient.reg()); | |
| 5804 cgen()->frame()->Spill(remainder.reg()); | |
| 5805 | |
| 5806 // Check that left and right are smi tagged. | |
| 5807 if (left->reg().is(right->reg())) { | |
| 5808 __ test(left->reg(), Immediate(kSmiTagMask)); | |
| 5809 } else { | |
| 5810 // Use the quotient register as a scratch for the tag check. | |
| 5811 if (!left_is_in_eax) __ mov(quotient.reg(), left->reg()); | |
| 5812 left_is_in_eax = false; | |
| 5813 __ or_(quotient.reg(), Operand(right->reg())); | |
| 5814 ASSERT(kSmiTag == 0); // Adjust test if not the case. | |
| 5815 __ test(quotient.reg(), Immediate(kSmiTagMask)); | |
| 5816 } | |
| 5817 SetEntryFrame(left, right); | |
| 5818 enter()->Branch(not_zero, left, right); | |
| 5819 | |
| 5820 if (!left_is_in_eax) __ mov(quotient.reg(), left->reg()); | |
| 5821 | |
| 5822 // Sign extend eax into edx:eax. | |
| 5823 __ cdq(); | |
| 5824 // Check for 0 divisor. | |
| 5825 __ test(right->reg(), Operand(right->reg())); | |
| 5826 enter()->Branch(zero, left, right); | |
| 5827 // Divide edx:eax by the right operand. | |
| 5828 __ idiv(right->reg()); | |
| 5829 | |
| 5830 // Complete the operation. | |
| 5831 if (op_ == Token::DIV) { | |
| 5832 // Check for negative zero result. If result is zero, and divisor | |
| 5833 // is negative, return a floating point negative zero. The | |
| 5834 // virtual frame is unchanged in this block, so local control flow | |
| 5835 // can use a Label rather than a JumpTarget. | |
| 5836 Label non_zero_result; | |
| 5837 __ test(left->reg(), Operand(left->reg())); | |
| 5838 __ j(not_zero, &non_zero_result); | |
| 5839 __ test(right->reg(), Operand(right->reg())); | |
| 5840 enter()->Branch(negative, left, right); | |
| 5841 __ bind(&non_zero_result); | |
| 5842 // Check for the corner case of dividing the most negative smi by | |
| 5843 // -1. We cannot use the overflow flag, since it is not set by | |
| 5844 // idiv instruction. | |
| 5845 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | |
| 5846 __ cmp(quotient.reg(), 0x40000000); | |
| 5847 enter()->Branch(equal, left, right); | |
| 5848 // Check that the remainder is zero. | |
| 5849 __ test(remainder.reg(), Operand(remainder.reg())); | |
| 5850 enter()->Branch(not_zero, left, right); | |
| 5851 left->Unuse(); | |
| 5852 right->Unuse(); | |
| 5853 // Tag the result and store it in the quotient register. | |
| 5854 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | |
| 5855 __ lea(quotient.reg(), | |
| 5856 Operand(quotient.reg(), quotient.reg(), times_1, kSmiTag)); | |
| 5857 return quotient; | |
| 5858 } else { | |
| 5859 ASSERT(op_ == Token::MOD); | |
| 5860 // Check for a negative zero result. If the result is zero, and | |
| 5861 // the dividend is negative, return a floating point negative | |
| 5862 // zero. The frame is unchanged in this block, so local control | |
| 5863 // flow can use a Label rather than a JumpTarget. | |
| 5864 Label non_zero_result; | |
| 5865 __ test(remainder.reg(), Operand(remainder.reg())); | |
| 5866 __ j(not_zero, &non_zero_result, taken); | |
| 5867 __ test(left->reg(), Operand(left->reg())); | |
| 5868 enter()->Branch(negative, left, right); | |
| 5869 left->Unuse(); | |
| 5870 right->Unuse(); | |
| 5871 __ bind(&non_zero_result); | |
| 5872 return remainder; | |
| 5873 } | |
| 5874 } | |
| 5875 | |
| 5876 // Handle the other binary operations. | |
| 5746 left->ToRegister(); | 5877 left->ToRegister(); |
| 5747 right->ToRegister(); | 5878 right->ToRegister(); |
| 5748 // A newly allocated register answer is used to hold the answer. | 5879 // A newly allocated register answer is used to hold the answer. The |
| 5749 // The registers containing left and right are not modified in | 5880 // registers containing left and right are not modified in most cases, |
| 5750 // most cases, so they usually don't need to be spilled in the fast case. | 5881 // so they usually don't need to be spilled in the fast case. |
| 5751 Result answer = cgen()->allocator()->Allocate(); | 5882 Result answer = cgen()->allocator()->Allocate(); |
| 5752 | 5883 |
| 5753 ASSERT(answer.is_valid()); | 5884 ASSERT(answer.is_valid()); |
| 5754 // Perform the smi check. | 5885 // Perform the smi tag check. |
| 5755 if (left->reg().is(right->reg())) { | 5886 if (left->reg().is(right->reg())) { |
| 5756 __ test(left->reg(), Immediate(kSmiTagMask)); | 5887 __ test(left->reg(), Immediate(kSmiTagMask)); |
| 5757 } else { | 5888 } else { |
| 5758 __ mov(answer.reg(), left->reg()); | 5889 __ mov(answer.reg(), left->reg()); |
| 5759 __ or_(answer.reg(), Operand(right->reg())); | 5890 __ or_(answer.reg(), Operand(right->reg())); |
| 5760 ASSERT(kSmiTag == 0); // adjust zero check if not the case | 5891 ASSERT(kSmiTag == 0); // Adjust test if not the case. |
| 5761 __ test(answer.reg(), Immediate(kSmiTagMask)); | 5892 __ test(answer.reg(), Immediate(kSmiTagMask)); |
| 5762 } | 5893 } |
| 5763 switch (op_) { | 5894 switch (op_) { |
| 5764 case Token::ADD: | 5895 case Token::ADD: |
| 5765 SetEntryFrame(left, right); | 5896 SetEntryFrame(left, right); |
| 5766 enter()->Branch(not_zero, left, right, not_taken); | 5897 enter()->Branch(not_zero, left, right, not_taken); |
| 5767 __ mov(answer.reg(), left->reg()); | 5898 __ mov(answer.reg(), left->reg()); |
| 5768 __ add(answer.reg(), Operand(right->reg())); // add optimistically | 5899 __ add(answer.reg(), Operand(right->reg())); // Add optimistically. |
| 5769 enter()->Branch(overflow, left, right, not_taken); | 5900 enter()->Branch(overflow, left, right, not_taken); |
| 5770 break; | 5901 break; |
| 5771 | 5902 |
| 5772 case Token::SUB: | 5903 case Token::SUB: |
| 5773 SetEntryFrame(left, right); | 5904 SetEntryFrame(left, right); |
| 5774 enter()->Branch(not_zero, left, right, not_taken); | 5905 enter()->Branch(not_zero, left, right, not_taken); |
| 5775 __ mov(answer.reg(), left->reg()); | 5906 __ mov(answer.reg(), left->reg()); |
| 5776 __ sub(answer.reg(), Operand(right->reg())); // subtract optimistically | 5907 __ sub(answer.reg(), Operand(right->reg())); // Subtract optimistically. |
| 5777 enter()->Branch(overflow, left, right, not_taken); | 5908 enter()->Branch(overflow, left, right, not_taken); |
| 5778 break; | 5909 break; |
| 5779 | 5910 |
| 5780 case Token::MUL: { | 5911 case Token::MUL: { |
| 5781 SetEntryFrame(left, right); | 5912 SetEntryFrame(left, right); |
| 5782 enter()->Branch(not_zero, left, right, not_taken); | 5913 enter()->Branch(not_zero, left, right, not_taken); |
| 5783 __ mov(answer.reg(), left->reg()); | 5914 __ mov(answer.reg(), left->reg()); |
| 5784 // If the smi tag is 0 we can just leave the tag on one operand. | 5915 // If the smi tag is 0 we can just leave the tag on one operand. |
| 5785 ASSERT(kSmiTag == 0); // adjust code below if not the case | 5916 ASSERT(kSmiTag == 0); // Adjust code below if not the case. |
| 5786 // Remove tag from the left operand (but keep sign). | 5917 // Remove smi tag from the left operand (but keep sign). |
| 5787 // Left hand operand has been copied into answer. | 5918 // Left-hand operand has been copied into answer. |
| 5788 __ sar(answer.reg(), kSmiTagSize); | 5919 __ sar(answer.reg(), kSmiTagSize); |
| 5789 // Do multiplication of smis, leaving result in answer. | 5920 // Do multiplication of smis, leaving result in answer. |
| 5790 __ imul(answer.reg(), Operand(right->reg())); | 5921 __ imul(answer.reg(), Operand(right->reg())); |
| 5791 // Go slow on overflows. | 5922 // Go slow on overflows. |
| 5792 enter()->Branch(overflow, left, right, not_taken); | 5923 enter()->Branch(overflow, left, right, not_taken); |
| 5793 // Check for negative zero result. If product is zero, | 5924 // Check for negative zero result. If product is zero, and one |
| 5794 // and one argument is negative, go to slow case. | 5925 // argument is negative, go to slow case. The frame is unchanged |
| 5795 // The frame is unchanged in this block, so local control flow can | 5926 // in this block, so local control flow can use a Label rather |
| 5796 // use a Label rather than a JumpTarget. | 5927 // than a JumpTarget. |
| 5797 Label non_zero_result; | 5928 Label non_zero_result; |
| 5798 __ test(answer.reg(), Operand(answer.reg())); | 5929 __ test(answer.reg(), Operand(answer.reg())); |
| 5799 __ j(not_zero, &non_zero_result, taken); | 5930 __ j(not_zero, &non_zero_result, taken); |
| 5800 __ mov(answer.reg(), left->reg()); | 5931 __ mov(answer.reg(), left->reg()); |
| 5801 __ or_(answer.reg(), Operand(right->reg())); | 5932 __ or_(answer.reg(), Operand(right->reg())); |
| 5802 enter()->Branch(negative, left, right, not_taken); | 5933 enter()->Branch(negative, left, right, not_taken); |
| 5803 __ xor_(answer.reg(), Operand(answer.reg())); // Positive 0 is correct. | 5934 __ xor_(answer.reg(), Operand(answer.reg())); // Positive 0 is correct. |
| 5804 __ bind(&non_zero_result); | 5935 __ bind(&non_zero_result); |
| 5805 break; | 5936 break; |
| 5806 } | 5937 } |
| 5807 | 5938 |
| 5808 case Token::DIV: // Fall through. | |
| 5809 case Token::MOD: { | |
| 5810 enter()->Branch(not_zero, left, right, not_taken); | |
| 5811 __ mov(answer.reg(), left->reg()); | |
| 5812 // Div and mod use the registers eax and edx. Left and right must | |
| 5813 // be preserved, because the original operands are needed if we switch | |
| 5814 // to the slow case. Move them if either is in eax or edx. | |
| 5815 // The Result answer should be changed into an alias for eax. | |
| 5816 // Precondition: | |
| 5817 // The Results left and right are valid. They may be the same register, | |
| 5818 // and may be unspilled. The Result answer is valid and is distinct | |
| 5819 // from left and right, and is spilled. | |
| 5820 // The value in left is copied to answer. | |
| 5821 | |
| 5822 Result reg_eax = cgen()->allocator()->Allocate(eax); | |
| 5823 Result reg_edx = cgen()->allocator()->Allocate(edx); | |
| 5824 // These allocations may have failed, if one of left, right, or answer | |
| 5825 // is in register eax or edx. | |
| 5826 bool left_copied_to_eax = false; // We will make sure this becomes true. | |
| 5827 | |
| 5828 // Part 1: Get eax | |
| 5829 if (answer.reg().is(eax)) { | |
| 5830 reg_eax = answer; | |
| 5831 left_copied_to_eax = true; | |
| 5832 } else if (right->reg().is(eax) || left->reg().is(eax)) { | |
| 5833 // We need a non-edx register to move one or both of left and right to. | |
| 5834 // We use answer if it is not edx, otherwise we allocate one. | |
| 5835 if (answer.reg().is(edx)) { | |
| 5836 reg_edx = answer; | |
| 5837 answer = cgen()->allocator()->Allocate(); | |
| 5838 ASSERT(answer.is_valid()); | |
| 5839 } | |
| 5840 | |
| 5841 if (left->reg().is(eax)) { | |
| 5842 reg_eax = *left; | |
| 5843 left_copied_to_eax = true; | |
| 5844 *left = answer; | |
| 5845 } | |
| 5846 if (right->reg().is(eax)) { | |
| 5847 reg_eax = *right; | |
| 5848 *right = answer; | |
| 5849 } | |
| 5850 __ mov(answer.reg(), eax); | |
| 5851 } | |
| 5852 // End of Part 1. | |
| 5853 // reg_eax is valid, and neither left nor right is in eax. | |
| 5854 ASSERT(reg_eax.is_valid()); | |
| 5855 ASSERT(!left->reg().is(eax)); | |
| 5856 ASSERT(!right->reg().is(eax)); | |
| 5857 | |
| 5858 // Part 2: Get edx | |
| 5859 // reg_edx is invalid if and only if either left, right, | |
| 5860 // or answer is in edx. If edx is valid, then either edx | |
| 5861 // was free, or it was answer, but answer was reallocated. | |
| 5862 if (answer.reg().is(edx)) { | |
| 5863 reg_edx = answer; | |
| 5864 } else if (right->reg().is(edx) || left->reg().is(edx)) { | |
| 5865 // Is answer used? | |
| 5866 if (answer.reg().is(eax) || answer.reg().is(left->reg()) || | |
| 5867 answer.reg().is(right->reg())) { | |
| 5868 answer = cgen()->allocator()->Allocate(); | |
| 5869 ASSERT(answer.is_valid()); // We cannot hit both Allocate() calls. | |
| 5870 } | |
| 5871 if (left->reg().is(edx)) { | |
| 5872 reg_edx = *left; | |
| 5873 *left = answer; | |
| 5874 } | |
| 5875 if (right->reg().is(edx)) { | |
| 5876 reg_edx = *right; | |
| 5877 *right = answer; | |
| 5878 } | |
| 5879 __ mov(answer.reg(), edx); | |
| 5880 } | |
| 5881 // End of Part 2 | |
| 5882 ASSERT(reg_edx.is_valid()); | |
| 5883 ASSERT(!left->reg().is(eax)); | |
| 5884 ASSERT(!right->reg().is(eax)); | |
| 5885 | |
| 5886 answer = reg_eax; // May free answer, if it was never used. | |
| 5887 cgen()->frame()->Spill(eax); | |
| 5888 if (!left_copied_to_eax) { | |
| 5889 __ mov(eax, left->reg()); | |
| 5890 left_copied_to_eax = true; | |
| 5891 } | |
| 5892 cgen()->frame()->Spill(edx); | |
| 5893 | |
| 5894 // Postcondition: | |
| 5895 // reg_eax, reg_edx are valid, correct, and spilled. | |
| 5896 // reg_eax contains the value originally in left | |
| 5897 // left and right are not eax or edx. They may or may not be | |
| 5898 // spilled or distinct. | |
| 5899 // answer is an alias for reg_eax. | |
| 5900 | |
| 5901 // Sign extend eax into edx:eax. | |
| 5902 __ cdq(); | |
| 5903 // Check for 0 divisor. | |
| 5904 __ test(right->reg(), Operand(right->reg())); | |
| 5905 enter()->Branch(zero, left, right, not_taken); | |
| 5906 // Divide edx:eax by the right operand. | |
| 5907 __ idiv(right->reg()); | |
| 5908 if (op_ == Token::DIV) { | |
| 5909 // Check for negative zero result. If result is zero, and divisor | |
| 5910 // is negative, return a floating point negative zero. | |
| 5911 // The frame is unchanged in this block, so local control flow can | |
| 5912 // use a Label rather than a JumpTarget. | |
| 5913 Label non_zero_result; | |
| 5914 __ test(left->reg(), Operand(left->reg())); | |
| 5915 __ j(not_zero, &non_zero_result, taken); | |
| 5916 __ test(right->reg(), Operand(right->reg())); | |
| 5917 enter()->Branch(negative, left, right, not_taken); | |
| 5918 __ bind(&non_zero_result); | |
| 5919 // Check for the corner case of dividing the most negative smi | |
| 5920 // by -1. We cannot use the overflow flag, since it is not set | |
| 5921 // by idiv instruction. | |
| 5922 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | |
| 5923 __ cmp(eax, 0x40000000); | |
| 5924 enter()->Branch(equal, left, right, not_taken); | |
| 5925 // Check that the remainder is zero. | |
| 5926 __ test(edx, Operand(edx)); | |
| 5927 enter()->Branch(not_zero, left, right, not_taken); | |
| 5928 // Tag the result and store it in register temp. | |
| 5929 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | |
| 5930 __ lea(answer.reg(), Operand(eax, eax, times_1, kSmiTag)); | |
| 5931 } else { | |
| 5932 ASSERT(op_ == Token::MOD); | |
| 5933 // Check for a negative zero result. If the result is zero, and the | |
| 5934 // dividend is negative, return a floating point negative zero. | |
| 5935 // The frame is unchanged in this block, so local control flow can | |
| 5936 // use a Label rather than a JumpTarget. | |
| 5937 Label non_zero_result; | |
| 5938 __ test(edx, Operand(edx)); | |
| 5939 __ j(not_zero, &non_zero_result, taken); | |
| 5940 __ test(left->reg(), Operand(left->reg())); | |
| 5941 enter()->Branch(negative, left, right, not_taken); | |
| 5942 __ bind(&non_zero_result); | |
| 5943 // The answer is in edx. | |
| 5944 answer = reg_edx; | |
| 5945 } | |
| 5946 break; | |
| 5947 } | |
| 5948 case Token::BIT_OR: | 5939 case Token::BIT_OR: |
| 5949 enter()->Branch(not_zero, left, right, not_taken); | 5940 enter()->Branch(not_zero, left, right, not_taken); |
| 5950 __ mov(answer.reg(), left->reg()); | 5941 __ mov(answer.reg(), left->reg()); |
| 5951 __ or_(answer.reg(), Operand(right->reg())); | 5942 __ or_(answer.reg(), Operand(right->reg())); |
| 5952 break; | 5943 break; |
| 5953 | 5944 |
| 5954 case Token::BIT_AND: | 5945 case Token::BIT_AND: |
| 5955 enter()->Branch(not_zero, left, right, not_taken); | 5946 enter()->Branch(not_zero, left, right, not_taken); |
| 5956 __ mov(answer.reg(), left->reg()); | 5947 __ mov(answer.reg(), left->reg()); |
| 5957 __ and_(answer.reg(), Operand(right->reg())); | 5948 __ and_(answer.reg(), Operand(right->reg())); |
| (...skipping 1331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7289 | 7280 |
| 7290 // Slow-case: Go through the JavaScript implementation. | 7281 // Slow-case: Go through the JavaScript implementation. |
| 7291 __ bind(&slow); | 7282 __ bind(&slow); |
| 7292 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 7283 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 7293 } | 7284 } |
| 7294 | 7285 |
| 7295 | 7286 |
| 7296 #undef __ | 7287 #undef __ |
| 7297 | 7288 |
| 7298 } } // namespace v8::internal | 7289 } } // namespace v8::internal |
| OLD | NEW |