Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Side by Side Diff: src/x64/codegen-x64.cc

Issue 155281: X64: Fixed more bad smi operations. (Closed)
Patch Set: Different approach to unifying tests in count operations. Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/mjsunit/date-parse.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/date-parse.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698