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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |