OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 | 141 |
142 | 142 |
143 void FastCodeGenerator::EmitBitOr() { | 143 void FastCodeGenerator::EmitBitOr() { |
144 if (is_smi(accumulator0()) && is_smi(accumulator1())) { | 144 if (is_smi(accumulator0()) && is_smi(accumulator1())) { |
145 // If both operands are known to be a smi then there is no need to check | 145 // If both operands are known to be a smi then there is no need to check |
146 // the operands or result. There is no need to perform the operation in | 146 // the operands or result. There is no need to perform the operation in |
147 // an effect context. | 147 // an effect context. |
148 if (!destination().is(no_reg)) { | 148 if (!destination().is(no_reg)) { |
149 __ orr(destination(), accumulator1(), Operand(accumulator0())); | 149 __ orr(destination(), accumulator1(), Operand(accumulator0())); |
150 } | 150 } |
151 } else if (destination().is(no_reg)) { | |
152 // Result is not needed but do not clobber the operands in case of | |
153 // bailout. | |
154 __ orr(scratch0(), accumulator1(), Operand(accumulator0())); | |
155 __ BranchOnNotSmi(scratch0(), bailout()); | |
156 } else { | 151 } else { |
157 // Preserve the destination operand in a scratch register in case of | 152 // Left is in accumulator1, right in accumulator0. |
158 // bailout. | 153 if (destination().is(accumulator0())) { |
159 __ mov(scratch0(), destination()); | 154 __ mov(scratch0(), accumulator0()); |
160 __ orr(destination(), accumulator1(), Operand(accumulator0())); | 155 __ orr(destination(), accumulator1(), Operand(accumulator1())); |
161 __ BranchOnNotSmi(destination(), bailout()); | 156 Label* bailout = |
| 157 info()->AddBailout(accumulator1(), scratch0()); // Left, right. |
| 158 __ BranchOnNotSmi(destination(), bailout); |
| 159 } else if (destination().is(accumulator1())) { |
| 160 __ mov(scratch0(), accumulator1()); |
| 161 __ orr(destination(), accumulator1(), Operand(accumulator0())); |
| 162 Label* bailout = info()->AddBailout(scratch0(), accumulator0()); |
| 163 __ BranchOnNotSmi(destination(), bailout); |
| 164 } else { |
| 165 ASSERT(destination().is(no_reg)); |
| 166 __ orr(scratch0(), accumulator1(), Operand(accumulator0())); |
| 167 Label* bailout = info()->AddBailout(accumulator1(), accumulator0()); |
| 168 __ BranchOnNotSmi(scratch0(), bailout); |
| 169 } |
162 } | 170 } |
163 | 171 |
164 // If we didn't bailout, the result (in fact, both inputs too) is known to | 172 // If we didn't bailout, the result (in fact, both inputs too) is known to |
165 // be a smi. | 173 // be a smi. |
166 set_as_smi(accumulator0()); | 174 set_as_smi(accumulator0()); |
167 set_as_smi(accumulator1()); | 175 set_as_smi(accumulator1()); |
168 } | 176 } |
169 | 177 |
170 | 178 |
171 void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { | 179 void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { |
172 ASSERT(info_ == NULL); | 180 ASSERT(info_ == NULL); |
173 info_ = compilation_info; | 181 info_ = compilation_info; |
174 | 182 |
175 // Save the caller's frame pointer and set up our own. | 183 // Save the caller's frame pointer and set up our own. |
176 Comment prologue_cmnt(masm(), ";; Prologue"); | 184 Comment prologue_cmnt(masm(), ";; Prologue"); |
177 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); | 185 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); |
178 __ add(fp, sp, Operand(2 * kPointerSize)); | 186 __ add(fp, sp, Operand(2 * kPointerSize)); |
179 // Note that we keep a live register reference to cp (context) at | 187 // Note that we keep a live register reference to cp (context) at |
180 // this point. | 188 // this point. |
181 | 189 |
| 190 Label* bailout_to_beginning = info()->AddBailout(); |
182 // Receiver (this) is allocated to a fixed register. | 191 // Receiver (this) is allocated to a fixed register. |
183 if (info()->has_this_properties()) { | 192 if (info()->has_this_properties()) { |
184 Comment cmnt(masm(), ";; MapCheck(this)"); | 193 Comment cmnt(masm(), ";; MapCheck(this)"); |
185 if (FLAG_print_ir) { | 194 if (FLAG_print_ir) { |
186 PrintF("MapCheck(this)\n"); | 195 PrintF("MapCheck(this)\n"); |
187 } | 196 } |
188 ASSERT(info()->has_receiver() && info()->receiver()->IsHeapObject()); | 197 ASSERT(info()->has_receiver() && info()->receiver()->IsHeapObject()); |
189 Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver()); | 198 Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver()); |
190 Handle<Map> map(object->map()); | 199 Handle<Map> map(object->map()); |
191 EmitLoadReceiver(); | 200 EmitLoadReceiver(); |
192 __ CheckMap(receiver_reg(), scratch0(), map, bailout(), false); | 201 __ CheckMap(receiver_reg(), scratch0(), map, bailout_to_beginning, false); |
193 } | 202 } |
194 | 203 |
195 // If there is a global variable access check if the global object is the | 204 // If there is a global variable access check if the global object is the |
196 // same as at lazy-compilation time. | 205 // same as at lazy-compilation time. |
197 if (info()->has_globals()) { | 206 if (info()->has_globals()) { |
198 Comment cmnt(masm(), ";; MapCheck(GLOBAL)"); | 207 Comment cmnt(masm(), ";; MapCheck(GLOBAL)"); |
199 if (FLAG_print_ir) { | 208 if (FLAG_print_ir) { |
200 PrintF("MapCheck(GLOBAL)\n"); | 209 PrintF("MapCheck(GLOBAL)\n"); |
201 } | 210 } |
202 ASSERT(info()->has_global_object()); | 211 ASSERT(info()->has_global_object()); |
203 Handle<Map> map(info()->global_object()->map()); | 212 Handle<Map> map(info()->global_object()->map()); |
204 __ ldr(scratch0(), CodeGenerator::GlobalObject()); | 213 __ ldr(scratch0(), CodeGenerator::GlobalObject()); |
205 __ CheckMap(scratch0(), scratch1(), map, bailout(), true); | 214 __ CheckMap(scratch0(), scratch1(), map, bailout_to_beginning, true); |
206 } | 215 } |
207 | 216 |
208 VisitStatements(function()->body()); | 217 VisitStatements(function()->body()); |
209 | 218 |
210 Comment return_cmnt(masm(), ";; Return(<undefined>)"); | 219 Comment return_cmnt(masm(), ";; Return(<undefined>)"); |
211 if (FLAG_print_ir) { | 220 if (FLAG_print_ir) { |
212 PrintF("Return(<undefined>)\n"); | 221 PrintF("Return(<undefined>)\n"); |
213 } | 222 } |
214 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 223 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
215 __ mov(sp, fp); | 224 __ mov(sp, fp); |
216 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | 225 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
217 int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize; | 226 int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize; |
218 __ add(sp, sp, Operand(sp_delta)); | 227 __ add(sp, sp, Operand(sp_delta)); |
219 __ Jump(lr); | 228 __ Jump(lr); |
220 | |
221 __ bind(&bailout_); | |
222 } | 229 } |
223 | 230 |
224 | 231 |
225 #undef __ | 232 #undef __ |
226 | 233 |
227 | 234 |
228 } } // namespace v8::internal | 235 } } // namespace v8::internal |
OLD | NEW |