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

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

Issue 164054: X64: Optimize MOD operator by a constant power of 2. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « src/x64/codegen-x64.h ('k') | no next file » | 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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 owner_->set_state(this); 90 owner_->set_state(this);
91 } 91 }
92 92
93 93
94 CodeGenState::~CodeGenState() { 94 CodeGenState::~CodeGenState() {
95 ASSERT(owner_->state() == this); 95 ASSERT(owner_->state() == this);
96 owner_->set_state(previous_); 96 owner_->set_state(previous_);
97 } 97 }
98 98
99 99
100 // -------------------------------------------------------------------------
101 // Deferred code objects
102 //
103 // These subclasses of DeferredCode add pieces of code to the end of generated
104 // code. They are branched to from the generated code, and
105 // keep some slower code out of the main body of the generated code.
106 // Many of them call a code stub or a runtime function.
107
108 class DeferredInlineSmiAdd: public DeferredCode {
109 public:
110 DeferredInlineSmiAdd(Register dst,
111 Smi* value,
112 OverwriteMode overwrite_mode)
113 : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) {
114 set_comment("[ DeferredInlineSmiAdd");
115 }
116
117 virtual void Generate();
118
119 private:
120 Register dst_;
121 Smi* value_;
122 OverwriteMode overwrite_mode_;
123 };
124
125
126 class DeferredInlineSmiSub: public DeferredCode {
127 public:
128 DeferredInlineSmiSub(Register dst,
129 Smi* value,
130 OverwriteMode overwrite_mode)
131 : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) {
132 set_comment("[ DeferredInlineSmiSub");
133 }
134
135 virtual void Generate();
136
137 private:
138 Register dst_;
139 Smi* value_;
140 OverwriteMode overwrite_mode_;
141 };
142
143
144 // Call the appropriate binary operation stub to compute src op value
145 // and leave the result in dst.
146 class DeferredInlineSmiOperation: public DeferredCode {
147 public:
148 DeferredInlineSmiOperation(Token::Value op,
149 Register dst,
150 Register src,
151 Smi* value,
152 OverwriteMode overwrite_mode)
153 : op_(op),
154 dst_(dst),
155 src_(src),
156 value_(value),
157 overwrite_mode_(overwrite_mode) {
158 set_comment("[ DeferredInlineSmiOperation");
159 }
160
161 virtual void Generate();
162
163 private:
164 Token::Value op_;
165 Register dst_;
166 Register src_;
167 Smi* value_;
168 OverwriteMode overwrite_mode_;
169 };
170
171
100 // ----------------------------------------------------------------------------- 172 // -----------------------------------------------------------------------------
101 // CodeGenerator implementation. 173 // CodeGenerator implementation.
102 174
103 CodeGenerator::CodeGenerator(int buffer_size, 175 CodeGenerator::CodeGenerator(int buffer_size,
104 Handle<Script> script, 176 Handle<Script> script,
105 bool is_eval) 177 bool is_eval)
106 : is_eval_(is_eval), 178 : is_eval_(is_eval),
107 script_(script), 179 script_(script),
108 deferred_(8), 180 deferred_(8),
109 masm_(new MacroAssembler(NULL, buffer_size)), 181 masm_(new MacroAssembler(NULL, buffer_size)),
(...skipping 4654 matching lines...) Expand 10 before | Expand all | Expand 10 after
4764 // Here we use masm_-> instead of the __ macro because this is the 4836 // Here we use masm_-> instead of the __ macro because this is the
4765 // instruction that gets patched and coverage code gets in the way. 4837 // instruction that gets patched and coverage code gets in the way.
4766 masm_->testl(rax, Immediate(-delta_to_patch_site)); 4838 masm_->testl(rax, Immediate(-delta_to_patch_site));
4767 __ IncrementCounter(&Counters::named_load_inline_miss, 1); 4839 __ IncrementCounter(&Counters::named_load_inline_miss, 1);
4768 4840
4769 if (!dst_.is(rax)) __ movq(dst_, rax); 4841 if (!dst_.is(rax)) __ movq(dst_, rax);
4770 __ pop(receiver_); 4842 __ pop(receiver_);
4771 } 4843 }
4772 4844
4773 4845
4774
4775
4776 // The result of src + value is in dst. It either overflowed or was not
4777 // smi tagged. Undo the speculative addition and call the appropriate
4778 // specialized stub for add. The result is left in dst.
4779 class DeferredInlineSmiAdd: public DeferredCode {
4780 public:
4781 DeferredInlineSmiAdd(Register dst,
4782 Smi* value,
4783 OverwriteMode overwrite_mode)
4784 : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) {
4785 set_comment("[ DeferredInlineSmiAdd");
4786 }
4787
4788 virtual void Generate();
4789
4790 private:
4791 Register dst_;
4792 Smi* value_;
4793 OverwriteMode overwrite_mode_;
4794 };
4795
4796
4797 void DeferredInlineSmiAdd::Generate() { 4846 void DeferredInlineSmiAdd::Generate() {
4798 __ push(dst_); 4847 __ push(dst_);
4799 __ push(Immediate(value_)); 4848 __ push(Immediate(value_));
4800 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); 4849 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
4801 __ CallStub(&igostub); 4850 __ CallStub(&igostub);
4802 if (!dst_.is(rax)) __ movq(dst_, rax); 4851 if (!dst_.is(rax)) __ movq(dst_, rax);
4803 } 4852 }
4804 4853
4805 4854
4806 // The result of value + src is in dst. It either overflowed or was not 4855 // The result of value + src is in dst. It either overflowed or was not
(...skipping 11 matching lines...) Expand all
4818 virtual void Generate(); 4867 virtual void Generate();
4819 4868
4820 private: 4869 private:
4821 Register dst_; 4870 Register dst_;
4822 Smi* value_; 4871 Smi* value_;
4823 OverwriteMode overwrite_mode_; 4872 OverwriteMode overwrite_mode_;
4824 }; 4873 };
4825 4874
4826 4875
4827 void DeferredInlineSmiAddReversed::Generate() { 4876 void DeferredInlineSmiAddReversed::Generate() {
4828 __ push(Immediate(value_)); 4877 __ push(Immediate(value_)); // Note: sign extended.
4829 __ push(dst_); 4878 __ push(dst_);
4830 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); 4879 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
4831 __ CallStub(&igostub); 4880 __ CallStub(&igostub);
4832 if (!dst_.is(rax)) __ movq(dst_, rax); 4881 if (!dst_.is(rax)) __ movq(dst_, rax);
4833 } 4882 }
4834 4883
4835 4884
4836 // The result of src - value is in dst. It either overflowed or was not
4837 // smi tagged. Undo the speculative subtraction and call the
4838 // appropriate specialized stub for subtract. The result is left in
4839 // dst.
4840 class DeferredInlineSmiSub: public DeferredCode {
4841 public:
4842 DeferredInlineSmiSub(Register dst,
4843 Smi* value,
4844 OverwriteMode overwrite_mode)
4845 : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) {
4846 set_comment("[ DeferredInlineSmiSub");
4847 }
4848
4849 virtual void Generate();
4850
4851 private:
4852 Register dst_;
4853 Smi* value_;
4854 OverwriteMode overwrite_mode_;
4855 };
4856
4857
4858 void DeferredInlineSmiSub::Generate() { 4885 void DeferredInlineSmiSub::Generate() {
4859 __ push(dst_); 4886 __ push(dst_);
4860 __ push(Immediate(value_)); 4887 __ push(Immediate(value_)); // Note: sign extended.
4861 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); 4888 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED);
4862 __ CallStub(&igostub); 4889 __ CallStub(&igostub);
4863 if (!dst_.is(rax)) __ movq(dst_, rax); 4890 if (!dst_.is(rax)) __ movq(dst_, rax);
4864 } 4891 }
4865 4892
4866 4893
4894 void DeferredInlineSmiOperation::Generate() {
4895 __ push(src_);
4896 __ push(Immediate(value_)); // Note: sign extended.
4897 // For mod we don't generate all the Smi code inline.
4898 GenericBinaryOpStub stub(
4899 op_,
4900 overwrite_mode_,
4901 (op_ == Token::MOD) ? SMI_CODE_IN_STUB : SMI_CODE_INLINED);
4902 __ CallStub(&stub);
4903 if (!dst_.is(rax)) __ movq(dst_, rax);
4904 }
4905
4906
4867 void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 4907 void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
4868 Result* operand, 4908 Result* operand,
4869 Handle<Object> value, 4909 Handle<Object> value,
4870 SmiAnalysis* type, 4910 SmiAnalysis* type,
4871 bool reversed, 4911 bool reversed,
4872 OverwriteMode overwrite_mode) { 4912 OverwriteMode overwrite_mode) {
4873 // NOTE: This is an attempt to inline (a bit) more of the code for 4913 // NOTE: This is an attempt to inline (a bit) more of the code for
4874 // some possible smi operations (like + and -) when (at least) one 4914 // some possible smi operations (like + and -) when (at least) one
4875 // of the operands is a constant smi. 4915 // of the operands is a constant smi.
4876 // Consumes the argument "operand". 4916 // Consumes the argument "operand".
4877 4917
4878 // TODO(199): Optimize some special cases of operations involving a 4918 // TODO(199): Optimize some special cases of operations involving a
4879 // smi literal (multiply by 2, shift by 0, etc.). 4919 // smi literal (multiply by 2, shift by 0, etc.).
4880 if (IsUnsafeSmi(value)) { 4920 if (IsUnsafeSmi(value)) {
4881 Result unsafe_operand(value); 4921 Result unsafe_operand(value);
4882 if (reversed) { 4922 if (reversed) {
4883 LikelySmiBinaryOperation(op, &unsafe_operand, operand, 4923 LikelySmiBinaryOperation(op, &unsafe_operand, operand,
4884 overwrite_mode); 4924 overwrite_mode);
4885 } else { 4925 } else {
4886 LikelySmiBinaryOperation(op, operand, &unsafe_operand, 4926 LikelySmiBinaryOperation(op, operand, &unsafe_operand,
4887 overwrite_mode); 4927 overwrite_mode);
4888 } 4928 }
4889 ASSERT(!operand->is_valid()); 4929 ASSERT(!operand->is_valid());
4890 return; 4930 return;
4891 } 4931 }
4892 4932
4893 // Get the literal value. 4933 // Get the literal value.
4894 Smi* smi_value = Smi::cast(*value); 4934 Smi* smi_value = Smi::cast(*value);
4935 int int_value = smi_value->value();
4895 4936
4896 switch (op) { 4937 switch (op) {
4897 case Token::ADD: { 4938 case Token::ADD: {
4898 operand->ToRegister(); 4939 operand->ToRegister();
4899 frame_->Spill(operand->reg()); 4940 frame_->Spill(operand->reg());
4900 DeferredCode* deferred = NULL; 4941 DeferredCode* deferred = NULL;
4901 if (reversed) { 4942 if (reversed) {
4902 deferred = new DeferredInlineSmiAddReversed(operand->reg(), 4943 deferred = new DeferredInlineSmiAddReversed(operand->reg(),
4903 smi_value, 4944 smi_value,
4904 overwrite_mode); 4945 overwrite_mode);
4905 } else { 4946 } else {
4906 deferred = new DeferredInlineSmiAdd(operand->reg(), 4947 deferred = new DeferredInlineSmiAdd(operand->reg(),
4907 smi_value, 4948 smi_value,
4908 overwrite_mode); 4949 overwrite_mode);
4909 } 4950 }
4910 __ testl(operand->reg(), Immediate(kSmiTagMask)); 4951 __ testl(operand->reg(), Immediate(kSmiTagMask));
4911 deferred->Branch(not_zero); 4952 deferred->Branch(not_zero);
4912 // A smi currently fits in a 32-bit Immediate. 4953 // A smi currently fits in a 32-bit Immediate.
4913 __ addl(operand->reg(), Immediate(smi_value)); 4954 __ addl(operand->reg(), Immediate(smi_value));
4914 Label add_success; 4955 Label add_success;
4915 __ j(no_overflow, &add_success); 4956 __ j(no_overflow, &add_success);
4916 __ subl(operand->reg(), Immediate(smi_value)); 4957 __ subl(operand->reg(), Immediate(smi_value));
4917 deferred->Jump(); 4958 deferred->Jump();
4918 __ bind(&add_success); 4959 __ bind(&add_success);
4919 deferred->BindExit(); 4960 deferred->BindExit();
4920 frame_->Push(operand); 4961 frame_->Push(operand);
4921 break; 4962 break;
4922 } 4963 }
4923 // TODO(X64): Move other implementations from ia32 to here. 4964 // TODO(X64): Move other implementations from ia32 to here.
4965
4966 // Generate inline code for mod of powers of 2 and negative powers of 2.
4967 case Token::MOD:
4968 if (!reversed &&
4969 int_value != 0 &&
4970 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) {
4971 operand->ToRegister();
4972 frame_->Spill(operand->reg());
4973 DeferredCode* deferred = new DeferredInlineSmiOperation(op,
4974 operand->reg(),
4975 operand->reg(),
4976 smi_value,
4977 overwrite_mode);
4978 // Check for negative or non-Smi left hand side.
4979 __ testl(operand->reg(),
4980 Immediate(static_cast<int32_t>(kSmiTagMask | 0x80000000)));
4981 deferred->Branch(not_zero);
4982 if (int_value < 0) int_value = -int_value;
4983 if (int_value == 1) {
4984 __ movl(operand->reg(), Immediate(Smi::FromInt(0)));
4985 } else {
4986 __ and_(operand->reg(), Immediate((int_value << kSmiTagSize) - 1));
4987 }
4988 deferred->BindExit();
4989 frame_->Push(operand);
4990 break; // This break only applies if we generated code for MOD.
4991 }
4992 // Fall through if we did not find a power of 2 on the right hand side!
4993 // The next case must be the default.
4994
4924 default: { 4995 default: {
4925 Result constant_operand(value); 4996 Result constant_operand(value);
4926 if (reversed) { 4997 if (reversed) {
4927 LikelySmiBinaryOperation(op, &constant_operand, operand, 4998 LikelySmiBinaryOperation(op, &constant_operand, operand,
4928 overwrite_mode); 4999 overwrite_mode);
4929 } else { 5000 } else {
4930 LikelySmiBinaryOperation(op, operand, &constant_operand, 5001 LikelySmiBinaryOperation(op, operand, &constant_operand,
4931 overwrite_mode); 5002 overwrite_mode);
4932 } 5003 }
4933 break; 5004 break;
(...skipping 2276 matching lines...) Expand 10 before | Expand all | Expand 10 after
7210 int CompareStub::MinorKey() { 7281 int CompareStub::MinorKey() {
7211 // Encode the two parameters in a unique 16 bit value. 7282 // Encode the two parameters in a unique 16 bit value.
7212 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); 7283 ASSERT(static_cast<unsigned>(cc_) < (1 << 15));
7213 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); 7284 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0);
7214 } 7285 }
7215 7286
7216 7287
7217 #undef __ 7288 #undef __
7218 7289
7219 } } // namespace v8::internal 7290 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698