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 |