| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 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 2706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2717 | 2717 |
| 2718 virtual void Generate(); | 2718 virtual void Generate(); |
| 2719 | 2719 |
| 2720 private: | 2720 private: |
| 2721 Register dst_; | 2721 Register dst_; |
| 2722 bool is_increment_; | 2722 bool is_increment_; |
| 2723 }; | 2723 }; |
| 2724 | 2724 |
| 2725 | 2725 |
| 2726 void DeferredPrefixCountOperation::Generate() { | 2726 void DeferredPrefixCountOperation::Generate() { |
| 2727 // Undo the optimistic smi operation. | |
| 2728 if (is_increment_) { | |
| 2729 __ subq(dst_, Immediate(Smi::FromInt(1))); | |
| 2730 } else { | |
| 2731 __ addq(dst_, Immediate(Smi::FromInt(1))); | |
| 2732 } | |
| 2733 __ push(dst_); | 2727 __ push(dst_); |
| 2734 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); | 2728 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); |
| 2735 __ push(rax); | 2729 __ push(rax); |
| 2736 __ push(Immediate(Smi::FromInt(1))); | 2730 __ push(Immediate(Smi::FromInt(1))); |
| 2737 if (is_increment_) { | 2731 if (is_increment_) { |
| 2738 __ CallRuntime(Runtime::kNumberAdd, 2); | 2732 __ CallRuntime(Runtime::kNumberAdd, 2); |
| 2739 } else { | 2733 } else { |
| 2740 __ CallRuntime(Runtime::kNumberSub, 2); | 2734 __ CallRuntime(Runtime::kNumberSub, 2); |
| 2741 } | 2735 } |
| 2742 if (!dst_.is(rax)) __ movq(dst_, rax); | 2736 if (!dst_.is(rax)) __ movq(dst_, rax); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2758 virtual void Generate(); | 2752 virtual void Generate(); |
| 2759 | 2753 |
| 2760 private: | 2754 private: |
| 2761 Register dst_; | 2755 Register dst_; |
| 2762 Register old_; | 2756 Register old_; |
| 2763 bool is_increment_; | 2757 bool is_increment_; |
| 2764 }; | 2758 }; |
| 2765 | 2759 |
| 2766 | 2760 |
| 2767 void DeferredPostfixCountOperation::Generate() { | 2761 void DeferredPostfixCountOperation::Generate() { |
| 2768 // Undo the optimistic smi operation. | |
| 2769 if (is_increment_) { | |
| 2770 __ subq(dst_, Immediate(Smi::FromInt(1))); | |
| 2771 } else { | |
| 2772 __ addq(dst_, Immediate(Smi::FromInt(1))); | |
| 2773 } | |
| 2774 __ push(dst_); | 2762 __ push(dst_); |
| 2775 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); | 2763 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); |
| 2776 | 2764 |
| 2777 // Save the result of ToNumber to use as the old value. | 2765 // Save the result of ToNumber to use as the old value. |
| 2778 __ push(rax); | 2766 __ push(rax); |
| 2779 | 2767 |
| 2780 // Call the runtime for the addition or subtraction. | 2768 // Call the runtime for the addition or subtraction. |
| 2781 __ push(rax); | 2769 __ push(rax); |
| 2782 __ push(Immediate(Smi::FromInt(1))); | 2770 __ push(Immediate(Smi::FromInt(1))); |
| 2783 if (is_increment_) { | 2771 if (is_increment_) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2820 Result old_value; // Only allocated in the postfix case. | 2808 Result old_value; // Only allocated in the postfix case. |
| 2821 if (is_postfix) { | 2809 if (is_postfix) { |
| 2822 // Allocate a temporary to preserve the old value. | 2810 // Allocate a temporary to preserve the old value. |
| 2823 old_value = allocator_->Allocate(); | 2811 old_value = allocator_->Allocate(); |
| 2824 ASSERT(old_value.is_valid()); | 2812 ASSERT(old_value.is_valid()); |
| 2825 __ movq(old_value.reg(), new_value.reg()); | 2813 __ movq(old_value.reg(), new_value.reg()); |
| 2826 } | 2814 } |
| 2827 // Ensure the new value is writable. | 2815 // Ensure the new value is writable. |
| 2828 frame_->Spill(new_value.reg()); | 2816 frame_->Spill(new_value.reg()); |
| 2829 | 2817 |
| 2830 // In order to combine the overflow and the smi tag check, we need | |
| 2831 // to be able to allocate a byte register. We attempt to do so | |
| 2832 // without spilling. If we fail, we will generate separate overflow | |
| 2833 // and smi tag checks. | |
| 2834 // | |
| 2835 // We allocate and clear the temporary register before | |
| 2836 // performing the count operation since clearing the register using | |
| 2837 // xor will clear the overflow flag. | |
| 2838 Result tmp = allocator_->AllocateWithoutSpilling(); | |
| 2839 | |
| 2840 // Clear scratch register to prepare it for setcc after the operation below. | |
| 2841 __ xor_(kScratchRegister, kScratchRegister); | |
| 2842 | |
| 2843 DeferredCode* deferred = NULL; | 2818 DeferredCode* deferred = NULL; |
| 2844 if (is_postfix) { | 2819 if (is_postfix) { |
| 2845 deferred = new DeferredPostfixCountOperation(new_value.reg(), | 2820 deferred = new DeferredPostfixCountOperation(new_value.reg(), |
| 2846 old_value.reg(), | 2821 old_value.reg(), |
| 2847 is_increment); | 2822 is_increment); |
| 2848 } else { | 2823 } else { |
| 2849 deferred = new DeferredPrefixCountOperation(new_value.reg(), | 2824 deferred = new DeferredPrefixCountOperation(new_value.reg(), |
| 2850 is_increment); | 2825 is_increment); |
| 2851 } | 2826 } |
| 2852 | 2827 |
| 2828 Result tmp = allocator_->AllocateWithoutSpilling(); |
| 2829 ASSERT(kSmiTagMask == 1 && kSmiTag == 0); |
| 2830 __ movl(tmp.reg(), Immediate(kSmiTagMask)); |
| 2831 // Smi test. |
| 2832 __ movq(kScratchRegister, new_value.reg()); |
| 2853 if (is_increment) { | 2833 if (is_increment) { |
| 2854 __ addq(new_value.reg(), Immediate(Smi::FromInt(1))); | 2834 __ addl(kScratchRegister, Immediate(Smi::FromInt(1))); |
| 2855 } else { | 2835 } else { |
| 2856 __ subq(new_value.reg(), Immediate(Smi::FromInt(1))); | 2836 __ subl(kScratchRegister, Immediate(Smi::FromInt(1))); |
| 2857 } | 2837 } |
| 2858 | 2838 // deferred->Branch(overflow); |
| 2859 // If the count operation didn't overflow and the result is a valid | 2839 __ cmovl(overflow, kScratchRegister, tmp.reg()); |
| 2860 // smi, we're done. Otherwise, we jump to the deferred slow-case | 2840 __ testl(kScratchRegister, tmp.reg()); |
| 2861 // code. | |
| 2862 | |
| 2863 // We combine the overflow and the smi tag check. | |
| 2864 __ setcc(overflow, kScratchRegister); | |
| 2865 __ or_(kScratchRegister, new_value.reg()); | |
| 2866 __ testl(kScratchRegister, Immediate(kSmiTagMask)); | |
| 2867 tmp.Unuse(); | 2841 tmp.Unuse(); |
| 2868 deferred->Branch(not_zero); | 2842 deferred->Branch(not_zero); |
| 2843 __ movq(new_value.reg(), kScratchRegister); |
| 2869 | 2844 |
| 2870 deferred->BindExit(); | 2845 deferred->BindExit(); |
| 2871 | 2846 |
| 2847 |
| 2872 // Postfix: store the old value in the allocated slot under the | 2848 // Postfix: store the old value in the allocated slot under the |
| 2873 // reference. | 2849 // reference. |
| 2874 if (is_postfix) frame_->SetElementAt(target.size(), &old_value); | 2850 if (is_postfix) frame_->SetElementAt(target.size(), &old_value); |
| 2875 | 2851 |
| 2876 frame_->Push(&new_value); | 2852 frame_->Push(&new_value); |
| 2877 // Non-constant: update the reference. | 2853 // Non-constant: update the reference. |
| 2878 if (!is_const) target.SetValue(NOT_CONST_INIT); | 2854 if (!is_const) target.SetValue(NOT_CONST_INIT); |
| 2879 } | 2855 } |
| 2880 | 2856 |
| 2881 // Postfix: drop the new value and use the old. | 2857 // Postfix: drop the new value and use the old. |
| (...skipping 2192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5074 __ testl(answer.reg(), Immediate(kSmiTagMask)); | 5050 __ testl(answer.reg(), Immediate(kSmiTagMask)); |
| 5075 deferred->Branch(not_zero); | 5051 deferred->Branch(not_zero); |
| 5076 | 5052 |
| 5077 // Untag both operands. | 5053 // Untag both operands. |
| 5078 __ movq(answer.reg(), left->reg()); | 5054 __ movq(answer.reg(), left->reg()); |
| 5079 __ sar(answer.reg(), Immediate(kSmiTagSize)); | 5055 __ sar(answer.reg(), Immediate(kSmiTagSize)); |
| 5080 __ sar(rcx, Immediate(kSmiTagSize)); | 5056 __ sar(rcx, Immediate(kSmiTagSize)); |
| 5081 // Perform the operation. | 5057 // Perform the operation. |
| 5082 switch (op) { | 5058 switch (op) { |
| 5083 case Token::SAR: | 5059 case Token::SAR: |
| 5084 __ sar(answer.reg()); | 5060 __ sarl(answer.reg()); |
| 5085 // No checks of result necessary | 5061 // No checks of result necessary |
| 5086 break; | 5062 break; |
| 5087 case Token::SHR: { | 5063 case Token::SHR: { |
| 5088 Label result_ok; | 5064 Label result_ok; |
| 5089 __ shr(answer.reg()); | 5065 __ shrl(answer.reg()); |
| 5090 // Check that the *unsigned* result fits in a smi. Neither of | 5066 // Check that the *unsigned* result fits in a smi. Neither of |
| 5091 // the two high-order bits can be set: | 5067 // the two high-order bits can be set: |
| 5092 // * 0x80000000: high bit would be lost when smi tagging. | 5068 // * 0x80000000: high bit would be lost when smi tagging. |
| 5093 // * 0x40000000: this number would convert to negative when smi | 5069 // * 0x40000000: this number would convert to negative when smi |
| 5094 // tagging. | 5070 // tagging. |
| 5095 // These two cases can only happen with shifts by 0 or 1 when | 5071 // These two cases can only happen with shifts by 0 or 1 when |
| 5096 // handed a valid smi. If the answer cannot be represented by a | 5072 // handed a valid smi. If the answer cannot be represented by a |
| 5097 // smi, restore the left and right arguments, and jump to slow | 5073 // smi, restore the left and right arguments, and jump to slow |
| 5098 // case. The low bit of the left argument may be lost, but only | 5074 // case. The low bit of the left argument may be lost, but only |
| 5099 // in a case where it is dropped anyway. | 5075 // in a case where it is dropped anyway. |
| (...skipping 1706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6806 if (use_sse3) { | 6782 if (use_sse3) { |
| 6807 // Truncate the operands to 32-bit integers and check for | 6783 // Truncate the operands to 32-bit integers and check for |
| 6808 // exceptions in doing so. | 6784 // exceptions in doing so. |
| 6809 CpuFeatures::Scope scope(CpuFeatures::SSE3); | 6785 CpuFeatures::Scope scope(CpuFeatures::SSE3); |
| 6810 __ fisttp_s(Operand(rsp, 0 * kPointerSize)); | 6786 __ fisttp_s(Operand(rsp, 0 * kPointerSize)); |
| 6811 __ fisttp_s(Operand(rsp, 1 * kPointerSize)); | 6787 __ fisttp_s(Operand(rsp, 1 * kPointerSize)); |
| 6812 __ fnstsw_ax(); | 6788 __ fnstsw_ax(); |
| 6813 __ testl(rax, Immediate(1)); | 6789 __ testl(rax, Immediate(1)); |
| 6814 __ j(not_zero, &operand_conversion_failure); | 6790 __ j(not_zero, &operand_conversion_failure); |
| 6815 } else { | 6791 } else { |
| 6816 // TODO(X64): Verify that SSE3 is always supported, drop this code. | |
| 6817 // Check if right operand is int32. | 6792 // Check if right operand is int32. |
| 6818 __ fist_s(Operand(rsp, 0 * kPointerSize)); | 6793 __ fist_s(Operand(rsp, 0 * kPointerSize)); |
| 6819 __ fild_s(Operand(rsp, 0 * kPointerSize)); | 6794 __ fild_s(Operand(rsp, 0 * kPointerSize)); |
| 6820 __ fucompp(); | 6795 __ fucompp(); |
| 6821 __ fnstsw_ax(); | 6796 __ fnstsw_ax(); |
| 6822 __ sahf(); // TODO(X64): Not available. | 6797 __ sahf(); // TODO(X64): Not available. |
| 6823 __ j(not_zero, &operand_conversion_failure); | 6798 __ j(not_zero, &operand_conversion_failure); |
| 6824 __ j(parity_even, &operand_conversion_failure); | 6799 __ j(parity_even, &operand_conversion_failure); |
| 6825 | 6800 |
| 6826 // Check if left operand is int32. | 6801 // Check if left operand is int32. |
| 6827 __ fist_s(Operand(rsp, 1 * kPointerSize)); | 6802 __ fist_s(Operand(rsp, 1 * kPointerSize)); |
| 6828 __ fild_s(Operand(rsp, 1 * kPointerSize)); | 6803 __ fild_s(Operand(rsp, 1 * kPointerSize)); |
| 6829 __ fucompp(); | 6804 __ fucompp(); |
| 6830 __ fnstsw_ax(); | 6805 __ fnstsw_ax(); |
| 6831 __ sahf(); // TODO(X64): Not available. Test bits in ax directly | 6806 __ sahf(); // TODO(X64): Not available. Test bits in ax directly |
| 6832 __ j(not_zero, &operand_conversion_failure); | 6807 __ j(not_zero, &operand_conversion_failure); |
| 6833 __ j(parity_even, &operand_conversion_failure); | 6808 __ j(parity_even, &operand_conversion_failure); |
| 6834 } | 6809 } |
| 6835 | 6810 |
| 6836 // Get int32 operands and perform bitop. | 6811 // Get int32 operands and perform bitop. |
| 6837 __ pop(rcx); | 6812 __ pop(rcx); |
| 6838 __ pop(rax); | 6813 __ pop(rax); |
| 6839 switch (op_) { | 6814 switch (op_) { |
| 6840 case Token::BIT_OR: __ or_(rax, rcx); break; | 6815 case Token::BIT_OR: __ or_(rax, rcx); break; |
| 6841 case Token::BIT_AND: __ and_(rax, rcx); break; | 6816 case Token::BIT_AND: __ and_(rax, rcx); break; |
| 6842 case Token::BIT_XOR: __ xor_(rax, rcx); break; | 6817 case Token::BIT_XOR: __ xor_(rax, rcx); break; |
| 6843 case Token::SAR: __ sar(rax); break; | 6818 case Token::SAR: __ sarl(rax); break; |
| 6844 case Token::SHL: __ shl(rax); break; | 6819 case Token::SHL: __ shll(rax); break; |
| 6845 case Token::SHR: __ shr(rax); break; | 6820 case Token::SHR: __ shrl(rax); break; |
| 6846 default: UNREACHABLE(); | 6821 default: UNREACHABLE(); |
| 6847 } | 6822 } |
| 6848 if (op_ == Token::SHR) { | 6823 if (op_ == Token::SHR) { |
| 6849 // Check if result is non-negative and fits in a smi. | 6824 // Check if result is non-negative and fits in a smi. |
| 6850 __ testl(rax, Immediate(0xc0000000)); | 6825 __ testl(rax, Immediate(0xc0000000)); |
| 6851 __ j(not_zero, &non_smi_result); | 6826 __ j(not_zero, &non_smi_result); |
| 6852 } else { | 6827 } else { |
| 6853 // Check if result fits in a smi. | 6828 // Check if result fits in a smi. |
| 6854 __ cmpl(rax, Immediate(0xc0000000)); | 6829 __ cmpl(rax, Immediate(0xc0000000)); |
| 6855 __ j(negative, &non_smi_result); | 6830 __ j(negative, &non_smi_result); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6961 int CompareStub::MinorKey() { | 6936 int CompareStub::MinorKey() { |
| 6962 // Encode the two parameters in a unique 16 bit value. | 6937 // Encode the two parameters in a unique 16 bit value. |
| 6963 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); | 6938 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); |
| 6964 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); | 6939 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); |
| 6965 } | 6940 } |
| 6966 | 6941 |
| 6967 | 6942 |
| 6968 #undef __ | 6943 #undef __ |
| 6969 | 6944 |
| 6970 } } // namespace v8::internal | 6945 } } // namespace v8::internal |
| OLD | NEW |