OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 12 matching lines...) Expand all Loading... |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #include "bootstrapper.h" | 30 #include "bootstrapper.h" |
31 #include "codegen-inl.h" | 31 #include "codegen-inl.h" |
32 #include "debug.h" | 32 #include "debug.h" |
33 #include "prettyprinter.h" | |
34 #include "scopeinfo.h" | |
35 #include "scopes.h" | 33 #include "scopes.h" |
36 #include "runtime.h" | 34 #include "runtime.h" |
37 | 35 |
38 namespace v8 { namespace internal { | 36 namespace v8 { namespace internal { |
39 | 37 |
40 class ArmCodeGenerator; | |
41 | |
42 | |
43 // ----------------------------------------------------------------------------- | |
44 // Reference support | |
45 | |
46 // A reference is a C++ stack-allocated object that keeps an ECMA | |
47 // reference on the execution stack while in scope. For variables | |
48 // the reference is empty, indicating that it isn't necessary to | |
49 // store state on the stack for keeping track of references to those. | |
50 // For properties, we keep either one (named) or two (indexed) values | |
51 // on the execution stack to represent the reference. | |
52 | |
53 enum InitState { CONST_INIT, NOT_CONST_INIT }; | |
54 enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF }; | |
55 | |
56 class Reference BASE_EMBEDDED { | |
57 public: | |
58 // The values of the types is important, see size(). | |
59 enum Type { ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 }; | |
60 Reference(ArmCodeGenerator* cgen, Expression* expression); | |
61 ~Reference(); | |
62 | |
63 Expression* expression() const { return expression_; } | |
64 Type type() const { return type_; } | |
65 void set_type(Type value) { | |
66 ASSERT(type_ == ILLEGAL); | |
67 type_ = value; | |
68 } | |
69 // The size of the reference or -1 if the reference is illegal. | |
70 int size() const { return type_; } | |
71 | |
72 bool is_illegal() const { return type_ == ILLEGAL; } | |
73 bool is_slot() const { return type_ == SLOT; } | |
74 bool is_property() const { return type_ == NAMED || type_ == KEYED; } | |
75 | |
76 // Return the name. Only valid for named property references. | |
77 Handle<String> GetName(); | |
78 | |
79 // Generate code to push the value of the reference on top of the | |
80 // expression stack. The reference is expected to be already on top of | |
81 // the expression stack, and it is left in place with its value above it. | |
82 void GetValue(TypeofState typeof_state); | |
83 | |
84 // Generate code to store the value on top of the expression stack in the | |
85 // reference. The reference is expected to be immediately below the value | |
86 // on the expression stack. The stored value is left in place (with the | |
87 // reference intact below it) to support chained assignments. | |
88 void SetValue(InitState init_state); | |
89 | |
90 private: | |
91 ArmCodeGenerator* cgen_; | |
92 Expression* expression_; | |
93 Type type_; | |
94 }; | |
95 | |
96 | |
97 // ------------------------------------------------------------------------- | |
98 // Code generation state | |
99 | |
100 // The state is passed down the AST by the code generator (and back up, in | |
101 // the form of the state of the label pair). It is threaded through the | |
102 // call stack. Constructing a state implicitly pushes it on the owning code | |
103 // generator's stack of states, and destroying one implicitly pops it. | |
104 | |
105 class CodeGenState BASE_EMBEDDED { | |
106 public: | |
107 // Create an initial code generator state. Destroying the initial state | |
108 // leaves the code generator with a NULL state. | |
109 explicit CodeGenState(ArmCodeGenerator* owner); | |
110 | |
111 // Create a code generator state based on a code generator's current | |
112 // state. The new state has its own typeof state and pair of branch | |
113 // labels. | |
114 CodeGenState(ArmCodeGenerator* owner, | |
115 TypeofState typeof_state, | |
116 Label* true_target, | |
117 Label* false_target); | |
118 | |
119 // Destroy a code generator state and restore the owning code generator's | |
120 // previous state. | |
121 ~CodeGenState(); | |
122 | |
123 TypeofState typeof_state() const { return typeof_state_; } | |
124 Label* true_target() const { return true_target_; } | |
125 Label* false_target() const { return false_target_; } | |
126 | |
127 private: | |
128 ArmCodeGenerator* owner_; | |
129 TypeofState typeof_state_; | |
130 Label* true_target_; | |
131 Label* false_target_; | |
132 CodeGenState* previous_; | |
133 }; | |
134 | |
135 | |
136 // ----------------------------------------------------------------------------- | |
137 // ArmCodeGenerator | |
138 | |
139 class ArmCodeGenerator: public CodeGenerator { | |
140 public: | |
141 static Handle<Code> MakeCode(FunctionLiteral* fun, | |
142 Handle<Script> script, | |
143 bool is_eval); | |
144 | |
145 MacroAssembler* masm() { return masm_; } | |
146 | |
147 Scope* scope() const { return scope_; } | |
148 | |
149 CodeGenState* state() { return state_; } | |
150 void set_state(CodeGenState* state) { state_ = state; } | |
151 | |
152 private: | |
153 // Assembler | |
154 MacroAssembler* masm_; // to generate code | |
155 | |
156 // Code generation state | |
157 Scope* scope_; | |
158 Condition cc_reg_; | |
159 CodeGenState* state_; | |
160 int break_stack_height_; | |
161 | |
162 // Labels | |
163 Label function_return_; | |
164 | |
165 // Construction/destruction | |
166 ArmCodeGenerator(int buffer_size, | |
167 Handle<Script> script, | |
168 bool is_eval); | |
169 | |
170 virtual ~ArmCodeGenerator() { delete masm_; } | |
171 | |
172 // Main code generation function | |
173 void GenCode(FunctionLiteral* fun); | |
174 | |
175 // The following are used by class Reference. | |
176 void LoadReference(Reference* ref); | |
177 void UnloadReference(Reference* ref); | |
178 | |
179 // State | |
180 bool has_cc() const { return cc_reg_ != al; } | |
181 TypeofState typeof_state() const { return state_->typeof_state(); } | |
182 Label* true_target() const { return state_->true_target(); } | |
183 Label* false_target() const { return state_->false_target(); } | |
184 | |
185 | |
186 // Expressions | |
187 MemOperand GlobalObject() const { | |
188 return ContextOperand(cp, Context::GLOBAL_INDEX); | |
189 } | |
190 | |
191 MemOperand ContextOperand(Register context, int index) const { | |
192 return MemOperand(context, Context::SlotOffset(index)); | |
193 } | |
194 | |
195 MemOperand ParameterOperand(int index) const { | |
196 int num_parameters = scope()->num_parameters(); | |
197 // index -2 corresponds to the activated closure, -1 corresponds | |
198 // to the receiver | |
199 ASSERT(-2 <= index && index < num_parameters); | |
200 int offset = (1 + num_parameters - index) * kPointerSize; | |
201 return MemOperand(fp, offset); | |
202 } | |
203 | |
204 MemOperand FunctionOperand() const { | |
205 return MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset); | |
206 } | |
207 | |
208 MemOperand SlotOperand(Slot* slot, Register tmp); | |
209 | |
210 void LoadCondition(Expression* x, | |
211 TypeofState typeof_state, | |
212 Label* true_target, | |
213 Label* false_target, | |
214 bool force_cc); | |
215 void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF); | |
216 void LoadGlobal(); | |
217 | |
218 // Read a value from a slot and leave it on top of the expression stack. | |
219 void LoadFromSlot(Slot* slot, TypeofState typeof_state); | |
220 | |
221 // Special code for typeof expressions: Unfortunately, we must | |
222 // be careful when loading the expression in 'typeof' | |
223 // expressions. We are not allowed to throw reference errors for | |
224 // non-existing properties of the global object, so we must make it | |
225 // look like an explicit property access, instead of an access | |
226 // through the context chain. | |
227 void LoadTypeofExpression(Expression* x); | |
228 | |
229 void ToBoolean(Label* true_target, Label* false_target); | |
230 | |
231 void GenericBinaryOperation(Token::Value op); | |
232 void Comparison(Condition cc, bool strict = false); | |
233 | |
234 void SmiOperation(Token::Value op, Handle<Object> value, bool reversed); | |
235 | |
236 void CallWithArguments(ZoneList<Expression*>* arguments, int position); | |
237 | |
238 // Declare global variables and functions in the given array of | |
239 // name/value pairs. | |
240 virtual void DeclareGlobals(Handle<FixedArray> pairs); | |
241 | |
242 // Instantiate the function boilerplate. | |
243 void InstantiateBoilerplate(Handle<JSFunction> boilerplate); | |
244 | |
245 // Control flow | |
246 void Branch(bool if_true, Label* L); | |
247 void CheckStack(); | |
248 void CleanStack(int num_bytes); | |
249 | |
250 // Node visitors | |
251 #define DEF_VISIT(type) \ | |
252 virtual void Visit##type(type* node); | |
253 NODE_LIST(DEF_VISIT) | |
254 #undef DEF_VISIT | |
255 | |
256 // Fast-case switch | |
257 static const int kFastCaseSwitchMaxOverheadFactor = 10; | |
258 static const int kFastCaseSwitchMinCaseCount = 5; | |
259 virtual int FastCaseSwitchMaxOverheadFactor(); | |
260 virtual int FastCaseSwitchMinCaseCount(); | |
261 virtual void GenerateFastCaseSwitchJumpTable( | |
262 SwitchStatement* node, int min_index, int range, Label *fail_label, | |
263 SmartPointer<Label*> &case_targets, SmartPointer<Label> &case_labels); | |
264 | |
265 void RecordStatementPosition(Node* node); | |
266 | |
267 // Activation frames | |
268 void EnterJSFrame(); | |
269 void ExitJSFrame(); | |
270 | |
271 virtual void GenerateIsSmi(ZoneList<Expression*>* args); | |
272 virtual void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args); | |
273 virtual void GenerateIsArray(ZoneList<Expression*>* args); | |
274 | |
275 virtual void GenerateArgumentsLength(ZoneList<Expression*>* args); | |
276 virtual void GenerateArgumentsAccess(ZoneList<Expression*>* args); | |
277 | |
278 virtual void GenerateValueOf(ZoneList<Expression*>* args); | |
279 virtual void GenerateSetValueOf(ZoneList<Expression*>* args); | |
280 | |
281 virtual void GenerateFastCharCodeAt(ZoneList<Expression*>* args); | |
282 | |
283 virtual void GenerateObjectEquals(ZoneList<Expression*>* args); | |
284 | |
285 friend class Reference; | |
286 friend class Property; | |
287 friend class VariableProxy; | |
288 friend class Slot; | |
289 }; | |
290 | |
291 | |
292 // ------------------------------------------------------------------------- | 38 // ------------------------------------------------------------------------- |
293 // CodeGenState implementation. | 39 // CodeGenState implementation. |
294 | 40 |
295 CodeGenState::CodeGenState(ArmCodeGenerator* owner) | 41 CodeGenState::CodeGenState(CodeGenerator* owner) |
296 : owner_(owner), | 42 : owner_(owner), |
297 typeof_state_(NOT_INSIDE_TYPEOF), | 43 typeof_state_(NOT_INSIDE_TYPEOF), |
298 true_target_(NULL), | 44 true_target_(NULL), |
299 false_target_(NULL), | 45 false_target_(NULL), |
300 previous_(NULL) { | 46 previous_(NULL) { |
301 owner_->set_state(this); | 47 owner_->set_state(this); |
302 } | 48 } |
303 | 49 |
304 | 50 |
305 CodeGenState::CodeGenState(ArmCodeGenerator* owner, | 51 CodeGenState::CodeGenState(CodeGenerator* owner, |
306 TypeofState typeof_state, | 52 TypeofState typeof_state, |
307 Label* true_target, | 53 Label* true_target, |
308 Label* false_target) | 54 Label* false_target) |
309 : owner_(owner), | 55 : owner_(owner), |
310 typeof_state_(typeof_state), | 56 typeof_state_(typeof_state), |
311 true_target_(true_target), | 57 true_target_(true_target), |
312 false_target_(false_target), | 58 false_target_(false_target), |
313 previous_(owner->state()) { | 59 previous_(owner->state()) { |
314 owner_->set_state(this); | 60 owner_->set_state(this); |
315 } | 61 } |
316 | 62 |
317 | 63 |
318 CodeGenState::~CodeGenState() { | 64 CodeGenState::~CodeGenState() { |
319 ASSERT(owner_->state() == this); | 65 ASSERT(owner_->state() == this); |
320 owner_->set_state(previous_); | 66 owner_->set_state(previous_); |
321 } | 67 } |
322 | 68 |
323 | 69 |
324 // ----------------------------------------------------------------------------- | 70 // ----------------------------------------------------------------------------- |
325 // ArmCodeGenerator implementation | 71 // CodeGenerator implementation |
326 | 72 |
327 #define __ masm_-> | 73 #define __ masm_-> |
328 | 74 |
329 Handle<Code> ArmCodeGenerator::MakeCode(FunctionLiteral* flit, | 75 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script, |
330 Handle<Script> script, | 76 bool is_eval) |
331 bool is_eval) { | 77 : is_eval_(is_eval), |
332 #ifdef ENABLE_DISASSEMBLER | 78 script_(script), |
333 bool print_code = FLAG_print_code && !Bootstrapper::IsActive(); | 79 deferred_(8), |
334 #endif // ENABLE_DISASSEMBLER | |
335 | |
336 #ifdef DEBUG | |
337 bool print_source = false; | |
338 bool print_ast = false; | |
339 const char* ftype; | |
340 | |
341 if (Bootstrapper::IsActive()) { | |
342 print_source = FLAG_print_builtin_source; | |
343 print_ast = FLAG_print_builtin_ast; | |
344 print_code = FLAG_print_builtin_code; | |
345 ftype = "builtin"; | |
346 } else { | |
347 print_source = FLAG_print_source; | |
348 print_ast = FLAG_print_ast; | |
349 ftype = "user-defined"; | |
350 } | |
351 | |
352 if (FLAG_trace_codegen || print_source || print_ast) { | |
353 PrintF("*** Generate code for %s function: ", ftype); | |
354 flit->name()->ShortPrint(); | |
355 PrintF(" ***\n"); | |
356 } | |
357 | |
358 if (print_source) { | |
359 PrintF("--- Source from AST ---\n%s\n", PrettyPrinter().PrintProgram(flit)); | |
360 } | |
361 | |
362 if (print_ast) { | |
363 PrintF("--- AST ---\n%s\n", AstPrinter().PrintProgram(flit)); | |
364 } | |
365 #endif // DEBUG | |
366 | |
367 // Generate code. | |
368 const int initial_buffer_size = 4 * KB; | |
369 ArmCodeGenerator cgen(initial_buffer_size, script, is_eval); | |
370 cgen.GenCode(flit); | |
371 if (cgen.HasStackOverflow()) { | |
372 ASSERT(!Top::has_pending_exception()); | |
373 return Handle<Code>::null(); | |
374 } | |
375 | |
376 // Process any deferred code. | |
377 cgen.ProcessDeferred(); | |
378 | |
379 // Allocate and install the code. | |
380 CodeDesc desc; | |
381 cgen.masm()->GetCode(&desc); | |
382 ScopeInfo<> sinfo(flit->scope()); | |
383 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION); | |
384 Handle<Code> code = Factory::NewCode(desc, &sinfo, flags); | |
385 | |
386 // Add unresolved entries in the code to the fixup list. | |
387 Bootstrapper::AddFixup(*code, cgen.masm()); | |
388 | |
389 #ifdef ENABLE_DISASSEMBLER | |
390 if (print_code) { | |
391 // Print the source code if available. | |
392 if (!script->IsUndefined() && !script->source()->IsUndefined()) { | |
393 PrintF("--- Raw source ---\n"); | |
394 StringInputBuffer stream(String::cast(script->source())); | |
395 stream.Seek(flit->start_position()); | |
396 // flit->end_position() points to the last character in the stream. We | |
397 // need to compensate by adding one to calculate the length. | |
398 int source_len = flit->end_position() - flit->start_position() + 1; | |
399 for (int i = 0; i < source_len; i++) { | |
400 if (stream.has_more()) PrintF("%c", stream.GetNext()); | |
401 } | |
402 PrintF("\n\n"); | |
403 } | |
404 PrintF("--- Code ---\n"); | |
405 code->Disassemble(); | |
406 } | |
407 #endif // ENABLE_DISASSEMBLER | |
408 | |
409 return code; | |
410 } | |
411 | |
412 | |
413 ArmCodeGenerator::ArmCodeGenerator(int buffer_size, | |
414 Handle<Script> script, | |
415 bool is_eval) | |
416 : CodeGenerator(is_eval, script), | |
417 masm_(new MacroAssembler(NULL, buffer_size)), | 80 masm_(new MacroAssembler(NULL, buffer_size)), |
418 scope_(NULL), | 81 scope_(NULL), |
419 cc_reg_(al), | 82 cc_reg_(al), |
420 state_(NULL), | 83 state_(NULL), |
421 break_stack_height_(0) { | 84 break_stack_height_(0) { |
422 } | 85 } |
423 | 86 |
424 | 87 |
425 // Calling conventions: | 88 // Calling conventions: |
426 | 89 |
427 // r0: the number of arguments | 90 // r0: the number of arguments |
428 // fp: frame pointer | 91 // fp: frame pointer |
429 // sp: stack pointer | 92 // sp: stack pointer |
430 // pp: caller's parameter pointer | 93 // pp: caller's parameter pointer |
431 // cp: callee's context | 94 // cp: callee's context |
432 | 95 |
433 void ArmCodeGenerator::GenCode(FunctionLiteral* fun) { | 96 void CodeGenerator::GenCode(FunctionLiteral* fun) { |
434 Scope* scope = fun->scope(); | 97 Scope* scope = fun->scope(); |
435 ZoneList<Statement*>* body = fun->body(); | 98 ZoneList<Statement*>* body = fun->body(); |
436 | 99 |
437 // Initialize state. | 100 // Initialize state. |
438 { CodeGenState state(this); | 101 { CodeGenState state(this); |
439 scope_ = scope; | 102 scope_ = scope; |
440 cc_reg_ = al; | 103 cc_reg_ = al; |
441 | 104 |
442 // Entry | 105 // Entry |
443 // stack: function, receiver, arguments, return address | 106 // stack: function, receiver, arguments, return address |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize)); | 276 __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize)); |
614 __ mov(pc, lr); | 277 __ mov(pc, lr); |
615 | 278 |
616 // Code generation state must be reset. | 279 // Code generation state must be reset. |
617 scope_ = NULL; | 280 scope_ = NULL; |
618 ASSERT(!has_cc()); | 281 ASSERT(!has_cc()); |
619 ASSERT(state_ == NULL); | 282 ASSERT(state_ == NULL); |
620 } | 283 } |
621 | 284 |
622 | 285 |
623 MemOperand ArmCodeGenerator::SlotOperand(Slot* slot, Register tmp) { | 286 MemOperand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { |
624 // Currently, this assertion will fail if we try to assign to | 287 // Currently, this assertion will fail if we try to assign to |
625 // a constant variable that is constant because it is read-only | 288 // a constant variable that is constant because it is read-only |
626 // (such as the variable referring to a named function expression). | 289 // (such as the variable referring to a named function expression). |
627 // We need to implement assignments to read-only variables. | 290 // We need to implement assignments to read-only variables. |
628 // Ideally, we should do this during AST generation (by converting | 291 // Ideally, we should do this during AST generation (by converting |
629 // such assignments into expression statements); however, in general | 292 // such assignments into expression statements); however, in general |
630 // we may not be able to make the decision until past AST generation, | 293 // we may not be able to make the decision until past AST generation, |
631 // that is when the entire program is known. | 294 // that is when the entire program is known. |
632 ASSERT(slot != NULL); | 295 ASSERT(slot != NULL); |
633 int index = slot->index(); | 296 int index = slot->index(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
672 return MemOperand(r0, 0); | 335 return MemOperand(r0, 0); |
673 } | 336 } |
674 } | 337 } |
675 | 338 |
676 | 339 |
677 // Loads a value on the stack. If it is a boolean value, the result may have | 340 // Loads a value on the stack. If it is a boolean value, the result may have |
678 // been (partially) translated into branches, or it may have set the condition | 341 // been (partially) translated into branches, or it may have set the condition |
679 // code register. If force_cc is set, the value is forced to set the condition | 342 // code register. If force_cc is set, the value is forced to set the condition |
680 // code register and no value is pushed. If the condition code register was set, | 343 // code register and no value is pushed. If the condition code register was set, |
681 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. | 344 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. |
682 void ArmCodeGenerator::LoadCondition(Expression* x, | 345 void CodeGenerator::LoadCondition(Expression* x, |
683 TypeofState typeof_state, | 346 TypeofState typeof_state, |
684 Label* true_target, | 347 Label* true_target, |
685 Label* false_target, | 348 Label* false_target, |
686 bool force_cc) { | 349 bool force_cc) { |
687 ASSERT(!has_cc()); | 350 ASSERT(!has_cc()); |
688 | 351 |
689 { CodeGenState new_state(this, typeof_state, true_target, false_target); | 352 { CodeGenState new_state(this, typeof_state, true_target, false_target); |
690 Visit(x); | 353 Visit(x); |
691 } | 354 } |
692 if (force_cc && !has_cc()) { | 355 if (force_cc && !has_cc()) { |
693 // Convert the TOS value to a boolean in the condition code register. | 356 // Convert the TOS value to a boolean in the condition code register. |
694 ToBoolean(true_target, false_target); | 357 ToBoolean(true_target, false_target); |
695 } | 358 } |
696 ASSERT(has_cc() || !force_cc); | 359 ASSERT(has_cc() || !force_cc); |
697 } | 360 } |
698 | 361 |
699 | 362 |
700 void ArmCodeGenerator::Load(Expression* x, TypeofState typeof_state) { | 363 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { |
701 Label true_target; | 364 Label true_target; |
702 Label false_target; | 365 Label false_target; |
703 LoadCondition(x, typeof_state, &true_target, &false_target, false); | 366 LoadCondition(x, typeof_state, &true_target, &false_target, false); |
704 | 367 |
705 if (has_cc()) { | 368 if (has_cc()) { |
706 // convert cc_reg_ into a bool | 369 // convert cc_reg_ into a bool |
707 Label loaded, materialize_true; | 370 Label loaded, materialize_true; |
708 __ b(cc_reg_, &materialize_true); | 371 __ b(cc_reg_, &materialize_true); |
709 __ mov(r0, Operand(Factory::false_value())); | 372 __ mov(r0, Operand(Factory::false_value())); |
710 __ push(r0); | 373 __ push(r0); |
(...skipping 28 matching lines...) Expand all Loading... |
739 __ mov(r0, Operand(Factory::false_value())); | 402 __ mov(r0, Operand(Factory::false_value())); |
740 __ push(r0); | 403 __ push(r0); |
741 } | 404 } |
742 // everything is loaded at this point | 405 // everything is loaded at this point |
743 __ bind(&loaded); | 406 __ bind(&loaded); |
744 } | 407 } |
745 ASSERT(!has_cc()); | 408 ASSERT(!has_cc()); |
746 } | 409 } |
747 | 410 |
748 | 411 |
749 void ArmCodeGenerator::LoadGlobal() { | 412 void CodeGenerator::LoadGlobal() { |
750 __ ldr(r0, GlobalObject()); | 413 __ ldr(r0, GlobalObject()); |
751 __ push(r0); | 414 __ push(r0); |
752 } | 415 } |
753 | 416 |
754 | 417 |
755 // TODO(1241834): Get rid of this function in favor of just using Load, now | 418 // TODO(1241834): Get rid of this function in favor of just using Load, now |
756 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global | 419 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global |
757 // variables w/o reference errors elsewhere. | 420 // variables w/o reference errors elsewhere. |
758 void ArmCodeGenerator::LoadTypeofExpression(Expression* x) { | 421 void CodeGenerator::LoadTypeofExpression(Expression* x) { |
759 Variable* variable = x->AsVariableProxy()->AsVariable(); | 422 Variable* variable = x->AsVariableProxy()->AsVariable(); |
760 if (variable != NULL && !variable->is_this() && variable->is_global()) { | 423 if (variable != NULL && !variable->is_this() && variable->is_global()) { |
761 // NOTE: This is somewhat nasty. We force the compiler to load | 424 // NOTE: This is somewhat nasty. We force the compiler to load |
762 // the variable as if through '<global>.<variable>' to make sure we | 425 // the variable as if through '<global>.<variable>' to make sure we |
763 // do not get reference errors. | 426 // do not get reference errors. |
764 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); | 427 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); |
765 Literal key(variable->name()); | 428 Literal key(variable->name()); |
766 // TODO(1241834): Fetch the position from the variable instead of using | 429 // TODO(1241834): Fetch the position from the variable instead of using |
767 // no position. | 430 // no position. |
768 Property property(&global, &key, RelocInfo::kNoPosition); | 431 Property property(&global, &key, RelocInfo::kNoPosition); |
769 Load(&property); | 432 Load(&property); |
770 } else { | 433 } else { |
771 Load(x, INSIDE_TYPEOF); | 434 Load(x, INSIDE_TYPEOF); |
772 } | 435 } |
773 } | 436 } |
774 | 437 |
775 | 438 |
776 Reference::Reference(ArmCodeGenerator* cgen, Expression* expression) | 439 Reference::Reference(CodeGenerator* cgen, Expression* expression) |
777 : cgen_(cgen), expression_(expression), type_(ILLEGAL) { | 440 : cgen_(cgen), expression_(expression), type_(ILLEGAL) { |
778 cgen->LoadReference(this); | 441 cgen->LoadReference(this); |
779 } | 442 } |
780 | 443 |
781 | 444 |
782 Reference::~Reference() { | 445 Reference::~Reference() { |
783 cgen_->UnloadReference(this); | 446 cgen_->UnloadReference(this); |
784 } | 447 } |
785 | 448 |
786 | 449 |
787 void ArmCodeGenerator::LoadReference(Reference* ref) { | 450 void CodeGenerator::LoadReference(Reference* ref) { |
788 Comment cmnt(masm_, "[ LoadReference"); | 451 Comment cmnt(masm_, "[ LoadReference"); |
| 452 |
789 Expression* e = ref->expression(); | 453 Expression* e = ref->expression(); |
790 Property* property = e->AsProperty(); | 454 Property* property = e->AsProperty(); |
791 Variable* var = e->AsVariableProxy()->AsVariable(); | 455 Variable* var = e->AsVariableProxy()->AsVariable(); |
792 | 456 |
793 if (property != NULL) { | 457 if (property != NULL) { |
794 // The expression is either a property or a variable proxy that rewrites | 458 // The expression is either a property or a variable proxy that rewrites |
795 // to a property. | 459 // to a property. |
796 Load(property->obj()); | 460 Load(property->obj()); |
797 // We use a named reference if the key is a literal symbol, unless it is | 461 // We use a named reference if the key is a literal symbol, unless it is |
798 // a string that can be legally parsed as an integer. This is because | 462 // a string that can be legally parsed as an integer. This is because |
(...skipping 20 matching lines...) Expand all Loading... |
819 ref->set_type(Reference::SLOT); | 483 ref->set_type(Reference::SLOT); |
820 } | 484 } |
821 } else { | 485 } else { |
822 // Anything else is a runtime error. | 486 // Anything else is a runtime error. |
823 Load(e); | 487 Load(e); |
824 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 488 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
825 } | 489 } |
826 } | 490 } |
827 | 491 |
828 | 492 |
829 void ArmCodeGenerator::UnloadReference(Reference* ref) { | 493 void CodeGenerator::UnloadReference(Reference* ref) { |
830 Comment cmnt(masm_, "[ UnloadReference"); | 494 Comment cmnt(masm_, "[ UnloadReference"); |
| 495 |
831 int size = ref->size(); | 496 int size = ref->size(); |
832 if (size <= 0) { | 497 if (size <= 0) { |
833 // Do nothing. No popping is necessary. | 498 // Do nothing. No popping is necessary. |
834 } else { | 499 } else { |
835 __ pop(r0); | 500 __ pop(r0); |
836 __ add(sp, sp, Operand(size * kPointerSize)); | 501 __ add(sp, sp, Operand(size * kPointerSize)); |
837 __ push(r0); | 502 __ push(r0); |
838 } | 503 } |
839 } | 504 } |
840 | 505 |
841 | 506 |
842 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given | 507 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given |
843 // register to a boolean in the condition code register. The code | 508 // register to a boolean in the condition code register. The code |
844 // may jump to 'false_target' in case the register converts to 'false'. | 509 // may jump to 'false_target' in case the register converts to 'false'. |
845 void ArmCodeGenerator::ToBoolean(Label* true_target, | 510 void CodeGenerator::ToBoolean(Label* true_target, |
846 Label* false_target) { | 511 Label* false_target) { |
847 // Note: The generated code snippet does not change stack variables. | 512 // Note: The generated code snippet does not change stack variables. |
848 // Only the condition code should be set. | 513 // Only the condition code should be set. |
849 __ pop(r0); | 514 __ pop(r0); |
850 | 515 |
851 // Fast case checks | 516 // Fast case checks |
852 | 517 |
853 // Check if the value is 'false'. | 518 // Check if the value is 'false'. |
854 __ cmp(r0, Operand(Factory::false_value())); | 519 __ cmp(r0, Operand(Factory::false_value())); |
855 __ b(eq, false_target); | 520 __ b(eq, false_target); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
950 #ifdef DEBUG | 615 #ifdef DEBUG |
951 void Print() { | 616 void Print() { |
952 PrintF("InvokeBuiltinStub (kind %d, argc, %d)\n", | 617 PrintF("InvokeBuiltinStub (kind %d, argc, %d)\n", |
953 static_cast<int>(kind_), | 618 static_cast<int>(kind_), |
954 argc_); | 619 argc_); |
955 } | 620 } |
956 #endif | 621 #endif |
957 }; | 622 }; |
958 | 623 |
959 | 624 |
960 void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) { | 625 void CodeGenerator::GenericBinaryOperation(Token::Value op) { |
961 // sp[0] : y | 626 // sp[0] : y |
962 // sp[1] : x | 627 // sp[1] : x |
963 // result : r0 | 628 // result : r0 |
964 | 629 |
965 // Stub is entered with a call: 'return address' is in lr. | 630 // Stub is entered with a call: 'return address' is in lr. |
966 switch (op) { | 631 switch (op) { |
967 case Token::ADD: // fall through. | 632 case Token::ADD: // fall through. |
968 case Token::SUB: // fall through. | 633 case Token::SUB: // fall through. |
969 case Token::MUL: | 634 case Token::MUL: |
970 case Token::BIT_OR: | 635 case Token::BIT_OR: |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1075 __ CallStub(&igostub); | 740 __ CallStub(&igostub); |
1076 } | 741 } |
1077 | 742 |
1078 private: | 743 private: |
1079 Token::Value op_; | 744 Token::Value op_; |
1080 int value_; | 745 int value_; |
1081 bool reversed_; | 746 bool reversed_; |
1082 }; | 747 }; |
1083 | 748 |
1084 | 749 |
1085 void ArmCodeGenerator::SmiOperation(Token::Value op, | 750 void CodeGenerator::SmiOperation(Token::Value op, |
1086 Handle<Object> value, | 751 Handle<Object> value, |
1087 bool reversed) { | 752 bool reversed) { |
1088 // NOTE: This is an attempt to inline (a bit) more of the code for | 753 // NOTE: This is an attempt to inline (a bit) more of the code for |
1089 // some possible smi operations (like + and -) when (at least) one | 754 // some possible smi operations (like + and -) when (at least) one |
1090 // of the operands is a literal smi. With this optimization, the | 755 // of the operands is a literal smi. With this optimization, the |
1091 // performance of the system is increased by ~15%, and the generated | 756 // performance of the system is increased by ~15%, and the generated |
1092 // code size is increased by ~1% (measured on a combination of | 757 // code size is increased by ~1% (measured on a combination of |
1093 // different benchmarks). | 758 // different benchmarks). |
1094 | 759 |
1095 // sp[0] : operand | 760 // sp[0] : operand |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1210 __ push(r0); | 875 __ push(r0); |
1211 } | 876 } |
1212 GenericBinaryOperation(op); | 877 GenericBinaryOperation(op); |
1213 break; | 878 break; |
1214 } | 879 } |
1215 | 880 |
1216 __ bind(&exit); | 881 __ bind(&exit); |
1217 } | 882 } |
1218 | 883 |
1219 | 884 |
1220 void ArmCodeGenerator::Comparison(Condition cc, bool strict) { | 885 void CodeGenerator::Comparison(Condition cc, bool strict) { |
1221 // sp[0] : y | 886 // sp[0] : y |
1222 // sp[1] : x | 887 // sp[1] : x |
1223 // result : cc register | 888 // result : cc register |
1224 | 889 |
1225 // Strict only makes sense for equality comparisons. | 890 // Strict only makes sense for equality comparisons. |
1226 ASSERT(!strict || cc == eq); | 891 ASSERT(!strict || cc == eq); |
1227 | 892 |
1228 Label exit, smi; | 893 Label exit, smi; |
1229 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. | 894 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. |
1230 if (cc == gt || cc == le) { | 895 if (cc == gt || cc == le) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1291 #if defined(DEBUG) | 956 #if defined(DEBUG) |
1292 void Print() { PrintF("CallFunctionStub (argc %d)\n", argc_); } | 957 void Print() { PrintF("CallFunctionStub (argc %d)\n", argc_); } |
1293 #endif // defined(DEBUG) | 958 #endif // defined(DEBUG) |
1294 | 959 |
1295 Major MajorKey() { return CallFunction; } | 960 Major MajorKey() { return CallFunction; } |
1296 int MinorKey() { return argc_; } | 961 int MinorKey() { return argc_; } |
1297 }; | 962 }; |
1298 | 963 |
1299 | 964 |
1300 // Call the function on the stack with the given arguments. | 965 // Call the function on the stack with the given arguments. |
1301 void ArmCodeGenerator::CallWithArguments(ZoneList<Expression*>* args, | 966 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, |
1302 int position) { | 967 int position) { |
1303 // Push the arguments ("left-to-right") on the stack. | 968 // Push the arguments ("left-to-right") on the stack. |
1304 for (int i = 0; i < args->length(); i++) { | 969 for (int i = 0; i < args->length(); i++) { |
1305 Load(args->at(i)); | 970 Load(args->at(i)); |
1306 } | 971 } |
1307 | 972 |
1308 // Record the position for debugging purposes. | 973 // Record the position for debugging purposes. |
1309 __ RecordPosition(position); | 974 __ RecordPosition(position); |
1310 | 975 |
1311 // Use the shared code stub to call the function. | 976 // Use the shared code stub to call the function. |
1312 CallFunctionStub call_function(args->length()); | 977 CallFunctionStub call_function(args->length()); |
1313 __ CallStub(&call_function); | 978 __ CallStub(&call_function); |
1314 | 979 |
1315 // Restore context and pop function from the stack. | 980 // Restore context and pop function from the stack. |
1316 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 981 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1317 __ pop(); // discard the TOS | 982 __ pop(); // discard the TOS |
1318 } | 983 } |
1319 | 984 |
1320 | 985 |
1321 void ArmCodeGenerator::Branch(bool if_true, Label* L) { | 986 void CodeGenerator::Branch(bool if_true, Label* L) { |
1322 ASSERT(has_cc()); | 987 ASSERT(has_cc()); |
1323 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); | 988 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); |
1324 __ b(cc, L); | 989 __ b(cc, L); |
1325 cc_reg_ = al; | 990 cc_reg_ = al; |
1326 } | 991 } |
1327 | 992 |
1328 | 993 |
1329 void ArmCodeGenerator::CheckStack() { | 994 void CodeGenerator::CheckStack() { |
1330 if (FLAG_check_stack) { | 995 if (FLAG_check_stack) { |
1331 Comment cmnt(masm_, "[ check stack"); | 996 Comment cmnt(masm_, "[ check stack"); |
1332 StackCheckStub stub; | 997 StackCheckStub stub; |
1333 __ CallStub(&stub); | 998 __ CallStub(&stub); |
1334 } | 999 } |
1335 } | 1000 } |
1336 | 1001 |
1337 | 1002 |
1338 void ArmCodeGenerator::VisitBlock(Block* node) { | 1003 void CodeGenerator::VisitBlock(Block* node) { |
1339 Comment cmnt(masm_, "[ Block"); | 1004 Comment cmnt(masm_, "[ Block"); |
1340 if (FLAG_debug_info) RecordStatementPosition(node); | 1005 if (FLAG_debug_info) RecordStatementPosition(node); |
1341 node->set_break_stack_height(break_stack_height_); | 1006 node->set_break_stack_height(break_stack_height_); |
1342 VisitStatements(node->statements()); | 1007 VisitStatements(node->statements()); |
1343 __ bind(node->break_target()); | 1008 __ bind(node->break_target()); |
1344 } | 1009 } |
1345 | 1010 |
1346 | 1011 |
1347 void ArmCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 1012 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
1348 __ mov(r0, Operand(pairs)); | 1013 __ mov(r0, Operand(pairs)); |
1349 __ push(r0); | 1014 __ push(r0); |
1350 __ push(cp); | 1015 __ push(cp); |
1351 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); | 1016 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); |
1352 __ push(r0); | 1017 __ push(r0); |
1353 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 1018 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
1354 // The result is discarded. | 1019 // The result is discarded. |
1355 } | 1020 } |
1356 | 1021 |
1357 | 1022 |
1358 void ArmCodeGenerator::VisitDeclaration(Declaration* node) { | 1023 void CodeGenerator::VisitDeclaration(Declaration* node) { |
1359 Comment cmnt(masm_, "[ Declaration"); | 1024 Comment cmnt(masm_, "[ Declaration"); |
1360 Variable* var = node->proxy()->var(); | 1025 Variable* var = node->proxy()->var(); |
1361 ASSERT(var != NULL); // must have been resolved | 1026 ASSERT(var != NULL); // must have been resolved |
1362 Slot* slot = var->slot(); | 1027 Slot* slot = var->slot(); |
1363 | 1028 |
1364 // If it was not possible to allocate the variable at compile time, | 1029 // If it was not possible to allocate the variable at compile time, |
1365 // we need to "declare" it at runtime to make sure it actually | 1030 // we need to "declare" it at runtime to make sure it actually |
1366 // exists in the local context. | 1031 // exists in the local context. |
1367 if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1032 if (slot != NULL && slot->type() == Slot::LOOKUP) { |
1368 // Variables with a "LOOKUP" slot were introduced as non-locals | 1033 // Variables with a "LOOKUP" slot were introduced as non-locals |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1413 target.SetValue(NOT_CONST_INIT); | 1078 target.SetValue(NOT_CONST_INIT); |
1414 // Get rid of the assigned value (declarations are statements). It's | 1079 // Get rid of the assigned value (declarations are statements). It's |
1415 // safe to pop the value lying on top of the reference before unloading | 1080 // safe to pop the value lying on top of the reference before unloading |
1416 // the reference itself (which preserves the top of stack) because we | 1081 // the reference itself (which preserves the top of stack) because we |
1417 // know it is a zero-sized reference. | 1082 // know it is a zero-sized reference. |
1418 __ pop(); | 1083 __ pop(); |
1419 } | 1084 } |
1420 } | 1085 } |
1421 | 1086 |
1422 | 1087 |
1423 void ArmCodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { | 1088 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { |
1424 Comment cmnt(masm_, "[ ExpressionStatement"); | 1089 Comment cmnt(masm_, "[ ExpressionStatement"); |
1425 if (FLAG_debug_info) RecordStatementPosition(node); | 1090 if (FLAG_debug_info) RecordStatementPosition(node); |
1426 Expression* expression = node->expression(); | 1091 Expression* expression = node->expression(); |
1427 expression->MarkAsStatement(); | 1092 expression->MarkAsStatement(); |
1428 Load(expression); | 1093 Load(expression); |
1429 __ pop(); | 1094 __ pop(); |
1430 } | 1095 } |
1431 | 1096 |
1432 | 1097 |
1433 void ArmCodeGenerator::VisitEmptyStatement(EmptyStatement* node) { | 1098 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { |
1434 Comment cmnt(masm_, "// EmptyStatement"); | 1099 Comment cmnt(masm_, "// EmptyStatement"); |
1435 // nothing to do | 1100 // nothing to do |
1436 } | 1101 } |
1437 | 1102 |
1438 | 1103 |
1439 void ArmCodeGenerator::VisitIfStatement(IfStatement* node) { | 1104 void CodeGenerator::VisitIfStatement(IfStatement* node) { |
1440 Comment cmnt(masm_, "[ IfStatement"); | 1105 Comment cmnt(masm_, "[ IfStatement"); |
1441 // Generate different code depending on which | 1106 // Generate different code depending on which |
1442 // parts of the if statement are present or not. | 1107 // parts of the if statement are present or not. |
1443 bool has_then_stm = node->HasThenStatement(); | 1108 bool has_then_stm = node->HasThenStatement(); |
1444 bool has_else_stm = node->HasElseStatement(); | 1109 bool has_else_stm = node->HasElseStatement(); |
1445 | 1110 |
1446 if (FLAG_debug_info) RecordStatementPosition(node); | 1111 if (FLAG_debug_info) RecordStatementPosition(node); |
1447 | 1112 |
1448 Label exit; | 1113 Label exit; |
1449 if (has_then_stm && has_else_stm) { | 1114 if (has_then_stm && has_else_stm) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1493 } else { | 1158 } else { |
1494 __ pop(r0); // __ Pop(no_reg) | 1159 __ pop(r0); // __ Pop(no_reg) |
1495 } | 1160 } |
1496 } | 1161 } |
1497 | 1162 |
1498 // end | 1163 // end |
1499 __ bind(&exit); | 1164 __ bind(&exit); |
1500 } | 1165 } |
1501 | 1166 |
1502 | 1167 |
1503 void ArmCodeGenerator::CleanStack(int num_bytes) { | 1168 void CodeGenerator::CleanStack(int num_bytes) { |
1504 ASSERT(num_bytes >= 0); | 1169 ASSERT(num_bytes >= 0); |
1505 if (num_bytes > 0) { | 1170 if (num_bytes > 0) { |
1506 __ add(sp, sp, Operand(num_bytes)); | 1171 __ add(sp, sp, Operand(num_bytes)); |
1507 } | 1172 } |
1508 } | 1173 } |
1509 | 1174 |
1510 | 1175 |
1511 void ArmCodeGenerator::VisitContinueStatement(ContinueStatement* node) { | 1176 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { |
1512 Comment cmnt(masm_, "[ ContinueStatement"); | 1177 Comment cmnt(masm_, "[ ContinueStatement"); |
1513 if (FLAG_debug_info) RecordStatementPosition(node); | 1178 if (FLAG_debug_info) RecordStatementPosition(node); |
1514 CleanStack(break_stack_height_ - node->target()->break_stack_height()); | 1179 CleanStack(break_stack_height_ - node->target()->break_stack_height()); |
1515 __ b(node->target()->continue_target()); | 1180 __ b(node->target()->continue_target()); |
1516 } | 1181 } |
1517 | 1182 |
1518 | 1183 |
1519 void ArmCodeGenerator::VisitBreakStatement(BreakStatement* node) { | 1184 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { |
1520 Comment cmnt(masm_, "[ BreakStatement"); | 1185 Comment cmnt(masm_, "[ BreakStatement"); |
1521 if (FLAG_debug_info) RecordStatementPosition(node); | 1186 if (FLAG_debug_info) RecordStatementPosition(node); |
1522 CleanStack(break_stack_height_ - node->target()->break_stack_height()); | 1187 CleanStack(break_stack_height_ - node->target()->break_stack_height()); |
1523 __ b(node->target()->break_target()); | 1188 __ b(node->target()->break_target()); |
1524 } | 1189 } |
1525 | 1190 |
1526 | 1191 |
1527 void ArmCodeGenerator::VisitReturnStatement(ReturnStatement* node) { | 1192 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { |
1528 Comment cmnt(masm_, "[ ReturnStatement"); | 1193 Comment cmnt(masm_, "[ ReturnStatement"); |
1529 if (FLAG_debug_info) RecordStatementPosition(node); | 1194 if (FLAG_debug_info) RecordStatementPosition(node); |
1530 Load(node->expression()); | 1195 Load(node->expression()); |
1531 // Move the function result into r0. | 1196 // Move the function result into r0. |
1532 __ pop(r0); | 1197 __ pop(r0); |
1533 | 1198 |
1534 __ b(&function_return_); | 1199 __ b(&function_return_); |
1535 } | 1200 } |
1536 | 1201 |
1537 | 1202 |
1538 void ArmCodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { | 1203 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { |
1539 Comment cmnt(masm_, "[ WithEnterStatement"); | 1204 Comment cmnt(masm_, "[ WithEnterStatement"); |
1540 if (FLAG_debug_info) RecordStatementPosition(node); | 1205 if (FLAG_debug_info) RecordStatementPosition(node); |
1541 Load(node->expression()); | 1206 Load(node->expression()); |
1542 __ CallRuntime(Runtime::kPushContext, 1); | 1207 __ CallRuntime(Runtime::kPushContext, 1); |
1543 if (kDebug) { | 1208 if (kDebug) { |
1544 Label verified_true; | 1209 Label verified_true; |
1545 __ cmp(r0, Operand(cp)); | 1210 __ cmp(r0, Operand(cp)); |
1546 __ b(eq, &verified_true); | 1211 __ b(eq, &verified_true); |
1547 __ stop("PushContext: r0 is expected to be the same as cp"); | 1212 __ stop("PushContext: r0 is expected to be the same as cp"); |
1548 __ bind(&verified_true); | 1213 __ bind(&verified_true); |
1549 } | 1214 } |
1550 // Update context local. | 1215 // Update context local. |
1551 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1216 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1552 } | 1217 } |
1553 | 1218 |
1554 | 1219 |
1555 void ArmCodeGenerator::VisitWithExitStatement(WithExitStatement* node) { | 1220 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { |
1556 Comment cmnt(masm_, "[ WithExitStatement"); | 1221 Comment cmnt(masm_, "[ WithExitStatement"); |
1557 // Pop context. | 1222 // Pop context. |
1558 __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX)); | 1223 __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX)); |
1559 // Update context local. | 1224 // Update context local. |
1560 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1225 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1561 } | 1226 } |
1562 | 1227 |
1563 | 1228 |
1564 int ArmCodeGenerator::FastCaseSwitchMaxOverheadFactor() { | 1229 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { |
1565 return kFastCaseSwitchMaxOverheadFactor; | 1230 return kFastSwitchMaxOverheadFactor; |
1566 } | 1231 } |
1567 | 1232 |
1568 int ArmCodeGenerator::FastCaseSwitchMinCaseCount() { | 1233 int CodeGenerator::FastCaseSwitchMinCaseCount() { |
1569 return kFastCaseSwitchMinCaseCount; | 1234 return kFastSwitchMinCaseCount; |
1570 } | 1235 } |
1571 | 1236 |
1572 | 1237 |
1573 void ArmCodeGenerator::GenerateFastCaseSwitchJumpTable( | 1238 void CodeGenerator::GenerateFastCaseSwitchJumpTable( |
1574 SwitchStatement* node, int min_index, int range, Label *fail_label, | 1239 SwitchStatement* node, int min_index, int range, Label *fail_label, |
1575 SmartPointer<Label*> &case_targets, SmartPointer<Label> &case_labels) { | 1240 SmartPointer<Label*> &case_targets, SmartPointer<Label> &case_labels) { |
1576 | 1241 |
1577 ASSERT(kSmiTag == 0 && kSmiTagSize <= 2); | 1242 ASSERT(kSmiTag == 0 && kSmiTagSize <= 2); |
1578 | 1243 |
1579 __ pop(r0); | 1244 __ pop(r0); |
1580 if (min_index != 0) { | 1245 if (min_index != 0) { |
1581 // small positive numbers can be immediate operands. | 1246 // small positive numbers can be immediate operands. |
1582 if (min_index < 0) { | 1247 if (min_index < 0) { |
1583 __ add(r0, r0, Operand(Smi::FromInt(-min_index))); | 1248 __ add(r0, r0, Operand(Smi::FromInt(-min_index))); |
(...skipping 12 matching lines...) Expand all Loading... |
1596 | 1261 |
1597 // table containing branch operations. | 1262 // table containing branch operations. |
1598 for (int i = 0; i < range; i++) { | 1263 for (int i = 0; i < range; i++) { |
1599 __ b(case_targets[i]); | 1264 __ b(case_targets[i]); |
1600 } | 1265 } |
1601 | 1266 |
1602 GenerateFastCaseSwitchCases(node, case_labels); | 1267 GenerateFastCaseSwitchCases(node, case_labels); |
1603 } | 1268 } |
1604 | 1269 |
1605 | 1270 |
1606 void ArmCodeGenerator::VisitSwitchStatement(SwitchStatement* node) { | 1271 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { |
1607 Comment cmnt(masm_, "[ SwitchStatement"); | 1272 Comment cmnt(masm_, "[ SwitchStatement"); |
1608 if (FLAG_debug_info) RecordStatementPosition(node); | 1273 if (FLAG_debug_info) RecordStatementPosition(node); |
1609 node->set_break_stack_height(break_stack_height_); | 1274 node->set_break_stack_height(break_stack_height_); |
1610 | 1275 |
1611 Load(node->tag()); | 1276 Load(node->tag()); |
1612 | 1277 |
1613 if (TryGenerateFastCaseSwitchStatement(node)) { | 1278 if (TryGenerateFastCaseSwitchStatement(node)) { |
1614 return; | 1279 return; |
1615 } | 1280 } |
1616 | 1281 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1664 } else { | 1329 } else { |
1665 // Remove the switch value from the stack. | 1330 // Remove the switch value from the stack. |
1666 __ pop(r0); | 1331 __ pop(r0); |
1667 } | 1332 } |
1668 | 1333 |
1669 __ bind(&fall_through); | 1334 __ bind(&fall_through); |
1670 __ bind(node->break_target()); | 1335 __ bind(node->break_target()); |
1671 } | 1336 } |
1672 | 1337 |
1673 | 1338 |
1674 void ArmCodeGenerator::VisitLoopStatement(LoopStatement* node) { | 1339 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { |
1675 Comment cmnt(masm_, "[ LoopStatement"); | 1340 Comment cmnt(masm_, "[ LoopStatement"); |
1676 if (FLAG_debug_info) RecordStatementPosition(node); | 1341 if (FLAG_debug_info) RecordStatementPosition(node); |
1677 node->set_break_stack_height(break_stack_height_); | 1342 node->set_break_stack_height(break_stack_height_); |
1678 | 1343 |
1679 // simple condition analysis | 1344 // simple condition analysis |
1680 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; | 1345 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; |
1681 if (node->cond() == NULL) { | 1346 if (node->cond() == NULL) { |
1682 ASSERT(node->type() == LoopStatement::FOR_LOOP); | 1347 ASSERT(node->type() == LoopStatement::FOR_LOOP); |
1683 info = ALWAYS_TRUE; | 1348 info = ALWAYS_TRUE; |
1684 } else { | 1349 } else { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1736 true); | 1401 true); |
1737 Branch(true, &loop); | 1402 Branch(true, &loop); |
1738 break; | 1403 break; |
1739 } | 1404 } |
1740 | 1405 |
1741 // exit | 1406 // exit |
1742 __ bind(node->break_target()); | 1407 __ bind(node->break_target()); |
1743 } | 1408 } |
1744 | 1409 |
1745 | 1410 |
1746 void ArmCodeGenerator::VisitForInStatement(ForInStatement* node) { | 1411 void CodeGenerator::VisitForInStatement(ForInStatement* node) { |
1747 Comment cmnt(masm_, "[ ForInStatement"); | 1412 Comment cmnt(masm_, "[ ForInStatement"); |
1748 if (FLAG_debug_info) RecordStatementPosition(node); | 1413 if (FLAG_debug_info) RecordStatementPosition(node); |
1749 | 1414 |
1750 // We keep stuff on the stack while the body is executing. | 1415 // We keep stuff on the stack while the body is executing. |
1751 // Record it, so that a break/continue crossing this statement | 1416 // Record it, so that a break/continue crossing this statement |
1752 // can restore the stack. | 1417 // can restore the stack. |
1753 const int kForInStackSize = 5 * kPointerSize; | 1418 const int kForInStackSize = 5 * kPointerSize; |
1754 break_stack_height_ += kForInStackSize; | 1419 break_stack_height_ += kForInStackSize; |
1755 node->set_break_stack_height(break_stack_height_); | 1420 node->set_break_stack_height(break_stack_height_); |
1756 | 1421 |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1924 __ bind(node->break_target()); | 1589 __ bind(node->break_target()); |
1925 __ add(sp, sp, Operand(5 * kPointerSize)); | 1590 __ add(sp, sp, Operand(5 * kPointerSize)); |
1926 | 1591 |
1927 // Exit. | 1592 // Exit. |
1928 __ bind(&exit); | 1593 __ bind(&exit); |
1929 | 1594 |
1930 break_stack_height_ -= kForInStackSize; | 1595 break_stack_height_ -= kForInStackSize; |
1931 } | 1596 } |
1932 | 1597 |
1933 | 1598 |
1934 void ArmCodeGenerator::VisitTryCatch(TryCatch* node) { | 1599 void CodeGenerator::VisitTryCatch(TryCatch* node) { |
1935 Comment cmnt(masm_, "[ TryCatch"); | 1600 Comment cmnt(masm_, "[ TryCatch"); |
1936 | 1601 |
1937 Label try_block, exit; | 1602 Label try_block, exit; |
1938 | 1603 |
1939 __ bl(&try_block); | 1604 __ bl(&try_block); |
1940 | 1605 |
1941 // --- Catch block --- | 1606 // --- Catch block --- |
1942 | 1607 |
1943 // Store the caught exception in the catch variable. | 1608 // Store the caught exception in the catch variable. |
1944 __ push(r0); | 1609 __ push(r0); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2013 // Code slot popped. | 1678 // Code slot popped. |
2014 | 1679 |
2015 __ b(shadows[i]->shadowed()); | 1680 __ b(shadows[i]->shadowed()); |
2016 } | 1681 } |
2017 } | 1682 } |
2018 | 1683 |
2019 __ bind(&exit); | 1684 __ bind(&exit); |
2020 } | 1685 } |
2021 | 1686 |
2022 | 1687 |
2023 void ArmCodeGenerator::VisitTryFinally(TryFinally* node) { | 1688 void CodeGenerator::VisitTryFinally(TryFinally* node) { |
2024 Comment cmnt(masm_, "[ TryFinally"); | 1689 Comment cmnt(masm_, "[ TryFinally"); |
2025 | 1690 |
2026 // State: Used to keep track of reason for entering the finally | 1691 // State: Used to keep track of reason for entering the finally |
2027 // block. Should probably be extended to hold information for | 1692 // block. Should probably be extended to hold information for |
2028 // break/continue from within the try block. | 1693 // break/continue from within the try block. |
2029 enum { FALLING, THROWING, JUMPING }; | 1694 enum { FALLING, THROWING, JUMPING }; |
2030 | 1695 |
2031 Label exit, unlink, try_block, finally_block; | 1696 Label exit, unlink, try_block, finally_block; |
2032 | 1697 |
2033 __ bl(&try_block); | 1698 __ bl(&try_block); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2146 | 1811 |
2147 // Rethrow exception. | 1812 // Rethrow exception. |
2148 __ push(r0); | 1813 __ push(r0); |
2149 __ CallRuntime(Runtime::kReThrow, 1); | 1814 __ CallRuntime(Runtime::kReThrow, 1); |
2150 | 1815 |
2151 // Done. | 1816 // Done. |
2152 __ bind(&exit); | 1817 __ bind(&exit); |
2153 } | 1818 } |
2154 | 1819 |
2155 | 1820 |
2156 void ArmCodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { | 1821 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { |
2157 Comment cmnt(masm_, "[ DebuggerStatament"); | 1822 Comment cmnt(masm_, "[ DebuggerStatament"); |
2158 if (FLAG_debug_info) RecordStatementPosition(node); | 1823 if (FLAG_debug_info) RecordStatementPosition(node); |
2159 __ CallRuntime(Runtime::kDebugBreak, 1); | 1824 __ CallRuntime(Runtime::kDebugBreak, 1); |
2160 __ push(r0); | 1825 __ push(r0); |
2161 } | 1826 } |
2162 | 1827 |
2163 | 1828 |
2164 void ArmCodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { | 1829 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { |
2165 ASSERT(boilerplate->IsBoilerplate()); | 1830 ASSERT(boilerplate->IsBoilerplate()); |
2166 | 1831 |
2167 // Push the boilerplate on the stack. | 1832 // Push the boilerplate on the stack. |
2168 __ mov(r0, Operand(boilerplate)); | 1833 __ mov(r0, Operand(boilerplate)); |
2169 __ push(r0); | 1834 __ push(r0); |
2170 | 1835 |
2171 // Create a new closure. | 1836 // Create a new closure. |
2172 __ push(cp); | 1837 __ push(cp); |
2173 __ CallRuntime(Runtime::kNewClosure, 2); | 1838 __ CallRuntime(Runtime::kNewClosure, 2); |
2174 __ push(r0); | 1839 __ push(r0); |
2175 } | 1840 } |
2176 | 1841 |
2177 | 1842 |
2178 void ArmCodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { | 1843 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { |
2179 Comment cmnt(masm_, "[ FunctionLiteral"); | 1844 Comment cmnt(masm_, "[ FunctionLiteral"); |
2180 | 1845 |
2181 // Build the function boilerplate and instantiate it. | 1846 // Build the function boilerplate and instantiate it. |
2182 Handle<JSFunction> boilerplate = BuildBoilerplate(node); | 1847 Handle<JSFunction> boilerplate = BuildBoilerplate(node); |
2183 // Check for stack-overflow exception. | 1848 // Check for stack-overflow exception. |
2184 if (HasStackOverflow()) return; | 1849 if (HasStackOverflow()) return; |
2185 InstantiateBoilerplate(boilerplate); | 1850 InstantiateBoilerplate(boilerplate); |
2186 } | 1851 } |
2187 | 1852 |
2188 | 1853 |
2189 void ArmCodeGenerator::VisitFunctionBoilerplateLiteral( | 1854 void CodeGenerator::VisitFunctionBoilerplateLiteral( |
2190 FunctionBoilerplateLiteral* node) { | 1855 FunctionBoilerplateLiteral* node) { |
2191 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); | 1856 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); |
2192 InstantiateBoilerplate(node->boilerplate()); | 1857 InstantiateBoilerplate(node->boilerplate()); |
2193 } | 1858 } |
2194 | 1859 |
2195 | 1860 |
2196 void ArmCodeGenerator::VisitConditional(Conditional* node) { | 1861 void CodeGenerator::VisitConditional(Conditional* node) { |
2197 Comment cmnt(masm_, "[ Conditional"); | 1862 Comment cmnt(masm_, "[ Conditional"); |
2198 Label then, else_, exit; | 1863 Label then, else_, exit; |
2199 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); | 1864 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); |
2200 Branch(false, &else_); | 1865 Branch(false, &else_); |
2201 __ bind(&then); | 1866 __ bind(&then); |
2202 Load(node->then_expression(), typeof_state()); | 1867 Load(node->then_expression(), typeof_state()); |
2203 __ b(&exit); | 1868 __ b(&exit); |
2204 __ bind(&else_); | 1869 __ bind(&else_); |
2205 Load(node->else_expression(), typeof_state()); | 1870 Load(node->else_expression(), typeof_state()); |
2206 __ bind(&exit); | 1871 __ bind(&exit); |
2207 } | 1872 } |
2208 | 1873 |
2209 | 1874 |
2210 void ArmCodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { | 1875 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { |
2211 if (slot->type() == Slot::LOOKUP) { | 1876 if (slot->type() == Slot::LOOKUP) { |
2212 ASSERT(slot->var()->mode() == Variable::DYNAMIC); | 1877 ASSERT(slot->var()->mode() == Variable::DYNAMIC); |
2213 | 1878 |
2214 // For now, just do a runtime call. | 1879 // For now, just do a runtime call. |
2215 __ push(cp); | 1880 __ push(cp); |
2216 __ mov(r0, Operand(slot->var()->name())); | 1881 __ mov(r0, Operand(slot->var()->name())); |
2217 __ push(r0); | 1882 __ push(r0); |
2218 | 1883 |
2219 if (typeof_state == INSIDE_TYPEOF) { | 1884 if (typeof_state == INSIDE_TYPEOF) { |
2220 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 1885 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
(...skipping 17 matching lines...) Expand all Loading... |
2238 Comment cmnt(masm_, "[ Unhole const"); | 1903 Comment cmnt(masm_, "[ Unhole const"); |
2239 __ pop(r0); | 1904 __ pop(r0); |
2240 __ cmp(r0, Operand(Factory::the_hole_value())); | 1905 __ cmp(r0, Operand(Factory::the_hole_value())); |
2241 __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq); | 1906 __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq); |
2242 __ push(r0); | 1907 __ push(r0); |
2243 } | 1908 } |
2244 } | 1909 } |
2245 } | 1910 } |
2246 | 1911 |
2247 | 1912 |
2248 void ArmCodeGenerator::VisitSlot(Slot* node) { | 1913 void CodeGenerator::VisitSlot(Slot* node) { |
2249 Comment cmnt(masm_, "[ Slot"); | 1914 Comment cmnt(masm_, "[ Slot"); |
2250 LoadFromSlot(node, typeof_state()); | 1915 LoadFromSlot(node, typeof_state()); |
2251 } | 1916 } |
2252 | 1917 |
2253 | 1918 |
2254 void ArmCodeGenerator::VisitVariableProxy(VariableProxy* node) { | 1919 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { |
2255 Comment cmnt(masm_, "[ VariableProxy"); | 1920 Comment cmnt(masm_, "[ VariableProxy"); |
| 1921 |
2256 Variable* var = node->var(); | 1922 Variable* var = node->var(); |
2257 Expression* expr = var->rewrite(); | 1923 Expression* expr = var->rewrite(); |
2258 if (expr != NULL) { | 1924 if (expr != NULL) { |
2259 Visit(expr); | 1925 Visit(expr); |
2260 } else { | 1926 } else { |
2261 ASSERT(var->is_global()); | 1927 ASSERT(var->is_global()); |
2262 Reference ref(this, node); | 1928 Reference ref(this, node); |
2263 ref.GetValue(typeof_state()); | 1929 ref.GetValue(typeof_state()); |
2264 } | 1930 } |
2265 } | 1931 } |
2266 | 1932 |
2267 | 1933 |
2268 void ArmCodeGenerator::VisitLiteral(Literal* node) { | 1934 void CodeGenerator::VisitLiteral(Literal* node) { |
2269 Comment cmnt(masm_, "[ Literal"); | 1935 Comment cmnt(masm_, "[ Literal"); |
2270 __ mov(r0, Operand(node->handle())); | 1936 __ mov(r0, Operand(node->handle())); |
2271 __ push(r0); | 1937 __ push(r0); |
2272 } | 1938 } |
2273 | 1939 |
2274 | 1940 |
2275 void ArmCodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { | 1941 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { |
2276 Comment cmnt(masm_, "[ RexExp Literal"); | 1942 Comment cmnt(masm_, "[ RexExp Literal"); |
2277 | 1943 |
2278 // Retrieve the literal array and check the allocated entry. | 1944 // Retrieve the literal array and check the allocated entry. |
2279 | 1945 |
2280 // Load the function of this activation. | 1946 // Load the function of this activation. |
2281 __ ldr(r1, FunctionOperand()); | 1947 __ ldr(r1, FunctionOperand()); |
2282 | 1948 |
2283 // Load the literals array of the function. | 1949 // Load the literals array of the function. |
2284 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); | 1950 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); |
2285 | 1951 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2336 __ mov(r0, Operand(Smi::FromInt(node_->literal_index()))); | 2002 __ mov(r0, Operand(Smi::FromInt(node_->literal_index()))); |
2337 __ push(r0); | 2003 __ push(r0); |
2338 // Constant properties (2). | 2004 // Constant properties (2). |
2339 __ mov(r0, Operand(node_->constant_properties())); | 2005 __ mov(r0, Operand(node_->constant_properties())); |
2340 __ push(r0); | 2006 __ push(r0); |
2341 __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); | 2007 __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); |
2342 __ mov(r2, Operand(r0)); | 2008 __ mov(r2, Operand(r0)); |
2343 } | 2009 } |
2344 | 2010 |
2345 | 2011 |
2346 void ArmCodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { | 2012 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { |
2347 Comment cmnt(masm_, "[ ObjectLiteral"); | 2013 Comment cmnt(masm_, "[ ObjectLiteral"); |
2348 | 2014 |
2349 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); | 2015 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); |
2350 | 2016 |
2351 // Retrieve the literal array and check the allocated entry. | 2017 // Retrieve the literal array and check the allocated entry. |
2352 | 2018 |
2353 // Load the function of this activation. | 2019 // Load the function of this activation. |
2354 __ ldr(r1, FunctionOperand()); | 2020 __ ldr(r1, FunctionOperand()); |
2355 | 2021 |
2356 // Load the literals array of the function. | 2022 // Load the literals array of the function. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2409 Load(value); | 2075 Load(value); |
2410 __ CallRuntime(Runtime::kDefineAccessor, 4); | 2076 __ CallRuntime(Runtime::kDefineAccessor, 4); |
2411 __ ldr(r0, MemOperand(sp, 0)); | 2077 __ ldr(r0, MemOperand(sp, 0)); |
2412 break; | 2078 break; |
2413 } | 2079 } |
2414 } | 2080 } |
2415 } | 2081 } |
2416 } | 2082 } |
2417 | 2083 |
2418 | 2084 |
2419 void ArmCodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { | 2085 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { |
2420 Comment cmnt(masm_, "[ ArrayLiteral"); | 2086 Comment cmnt(masm_, "[ ArrayLiteral"); |
2421 | 2087 |
2422 // Call runtime to create the array literal. | 2088 // Call runtime to create the array literal. |
2423 __ mov(r0, Operand(node->literals())); | 2089 __ mov(r0, Operand(node->literals())); |
2424 __ push(r0); | 2090 __ push(r0); |
2425 // Load the function of this frame. | 2091 // Load the function of this frame. |
2426 __ ldr(r0, FunctionOperand()); | 2092 __ ldr(r0, FunctionOperand()); |
2427 __ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); | 2093 __ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); |
2428 __ push(r0); | 2094 __ push(r0); |
2429 __ CallRuntime(Runtime::kCreateArrayLiteral, 2); | 2095 __ CallRuntime(Runtime::kCreateArrayLiteral, 2); |
(...skipping 23 matching lines...) Expand all Loading... |
2453 __ str(r0, FieldMemOperand(r1, offset)); | 2119 __ str(r0, FieldMemOperand(r1, offset)); |
2454 | 2120 |
2455 // Update the write barrier for the array address. | 2121 // Update the write barrier for the array address. |
2456 __ mov(r3, Operand(offset)); | 2122 __ mov(r3, Operand(offset)); |
2457 __ RecordWrite(r1, r3, r2); | 2123 __ RecordWrite(r1, r3, r2); |
2458 } | 2124 } |
2459 } | 2125 } |
2460 } | 2126 } |
2461 | 2127 |
2462 | 2128 |
2463 void ArmCodeGenerator::VisitAssignment(Assignment* node) { | 2129 void CodeGenerator::VisitAssignment(Assignment* node) { |
2464 Comment cmnt(masm_, "[ Assignment"); | 2130 Comment cmnt(masm_, "[ Assignment"); |
2465 if (FLAG_debug_info) RecordStatementPosition(node); | 2131 if (FLAG_debug_info) RecordStatementPosition(node); |
2466 | 2132 |
2467 Reference target(this, node->target()); | 2133 Reference target(this, node->target()); |
2468 if (target.is_illegal()) return; | 2134 if (target.is_illegal()) return; |
2469 | 2135 |
2470 if (node->op() == Token::ASSIGN || | 2136 if (node->op() == Token::ASSIGN || |
2471 node->op() == Token::INIT_VAR || | 2137 node->op() == Token::INIT_VAR || |
2472 node->op() == Token::INIT_CONST) { | 2138 node->op() == Token::INIT_CONST) { |
2473 Load(node->value()); | 2139 Load(node->value()); |
(...skipping 25 matching lines...) Expand all Loading... |
2499 // and initialize the actual constant declared. Dynamic variable | 2165 // and initialize the actual constant declared. Dynamic variable |
2500 // initializations are simply assignments and use SetValue. | 2166 // initializations are simply assignments and use SetValue. |
2501 target.SetValue(CONST_INIT); | 2167 target.SetValue(CONST_INIT); |
2502 } else { | 2168 } else { |
2503 target.SetValue(NOT_CONST_INIT); | 2169 target.SetValue(NOT_CONST_INIT); |
2504 } | 2170 } |
2505 } | 2171 } |
2506 } | 2172 } |
2507 | 2173 |
2508 | 2174 |
2509 void ArmCodeGenerator::VisitThrow(Throw* node) { | 2175 void CodeGenerator::VisitThrow(Throw* node) { |
2510 Comment cmnt(masm_, "[ Throw"); | 2176 Comment cmnt(masm_, "[ Throw"); |
2511 | 2177 |
2512 Load(node->exception()); | 2178 Load(node->exception()); |
2513 __ RecordPosition(node->position()); | 2179 __ RecordPosition(node->position()); |
2514 __ CallRuntime(Runtime::kThrow, 1); | 2180 __ CallRuntime(Runtime::kThrow, 1); |
2515 __ push(r0); | 2181 __ push(r0); |
2516 } | 2182 } |
2517 | 2183 |
2518 | 2184 |
2519 void ArmCodeGenerator::VisitProperty(Property* node) { | 2185 void CodeGenerator::VisitProperty(Property* node) { |
2520 Comment cmnt(masm_, "[ Property"); | 2186 Comment cmnt(masm_, "[ Property"); |
| 2187 |
2521 Reference property(this, node); | 2188 Reference property(this, node); |
2522 property.GetValue(typeof_state()); | 2189 property.GetValue(typeof_state()); |
2523 } | 2190 } |
2524 | 2191 |
2525 | 2192 |
2526 void ArmCodeGenerator::VisitCall(Call* node) { | 2193 void CodeGenerator::VisitCall(Call* node) { |
2527 Comment cmnt(masm_, "[ Call"); | 2194 Comment cmnt(masm_, "[ Call"); |
2528 | 2195 |
2529 ZoneList<Expression*>* args = node->arguments(); | 2196 ZoneList<Expression*>* args = node->arguments(); |
2530 | 2197 |
2531 if (FLAG_debug_info) RecordStatementPosition(node); | 2198 if (FLAG_debug_info) RecordStatementPosition(node); |
2532 // Standard function call. | 2199 // Standard function call. |
2533 | 2200 |
2534 // Check if the function is a variable or a property. | 2201 // Check if the function is a variable or a property. |
2535 Expression* function = node->expression(); | 2202 Expression* function = node->expression(); |
2536 Variable* var = function->AsVariableProxy()->AsVariable(); | 2203 Variable* var = function->AsVariableProxy()->AsVariable(); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2642 Load(function); | 2309 Load(function); |
2643 // Pass the global object as the receiver. | 2310 // Pass the global object as the receiver. |
2644 LoadGlobal(); | 2311 LoadGlobal(); |
2645 // Call the function. | 2312 // Call the function. |
2646 CallWithArguments(args, node->position()); | 2313 CallWithArguments(args, node->position()); |
2647 __ push(r0); | 2314 __ push(r0); |
2648 } | 2315 } |
2649 } | 2316 } |
2650 | 2317 |
2651 | 2318 |
2652 void ArmCodeGenerator::VisitCallNew(CallNew* node) { | 2319 void CodeGenerator::VisitCallNew(CallNew* node) { |
2653 Comment cmnt(masm_, "[ CallNew"); | 2320 Comment cmnt(masm_, "[ CallNew"); |
2654 | 2321 |
2655 // According to ECMA-262, section 11.2.2, page 44, the function | 2322 // According to ECMA-262, section 11.2.2, page 44, the function |
2656 // expression in new calls must be evaluated before the | 2323 // expression in new calls must be evaluated before the |
2657 // arguments. This is different from ordinary calls, where the | 2324 // arguments. This is different from ordinary calls, where the |
2658 // actual function to call is resolved after the arguments have been | 2325 // actual function to call is resolved after the arguments have been |
2659 // evaluated. | 2326 // evaluated. |
2660 | 2327 |
2661 // Compute function to call and use the global object as the | 2328 // Compute function to call and use the global object as the |
2662 // receiver. | 2329 // receiver. |
(...skipping 14 matching lines...) Expand all Loading... |
2677 // constructor invocation. | 2344 // constructor invocation. |
2678 __ RecordPosition(RelocInfo::POSITION); | 2345 __ RecordPosition(RelocInfo::POSITION); |
2679 __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), | 2346 __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), |
2680 RelocInfo::CONSTRUCT_CALL); | 2347 RelocInfo::CONSTRUCT_CALL); |
2681 | 2348 |
2682 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). | 2349 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). |
2683 __ str(r0, MemOperand(sp, 0 * kPointerSize)); | 2350 __ str(r0, MemOperand(sp, 0 * kPointerSize)); |
2684 } | 2351 } |
2685 | 2352 |
2686 | 2353 |
2687 void ArmCodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { | 2354 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { |
2688 ASSERT(args->length() == 1); | 2355 ASSERT(args->length() == 1); |
2689 Label leave; | 2356 Label leave; |
2690 Load(args->at(0)); | 2357 Load(args->at(0)); |
2691 __ pop(r0); // r0 contains object. | 2358 __ pop(r0); // r0 contains object. |
2692 // if (object->IsSmi()) return the object. | 2359 // if (object->IsSmi()) return the object. |
2693 __ tst(r0, Operand(kSmiTagMask)); | 2360 __ tst(r0, Operand(kSmiTagMask)); |
2694 __ b(eq, &leave); | 2361 __ b(eq, &leave); |
2695 // It is a heap object - get map. | 2362 // It is a heap object - get map. |
2696 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 2363 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
2697 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); | 2364 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
2698 // if (!object->IsJSValue()) return the object. | 2365 // if (!object->IsJSValue()) return the object. |
2699 __ cmp(r1, Operand(JS_VALUE_TYPE)); | 2366 __ cmp(r1, Operand(JS_VALUE_TYPE)); |
2700 __ b(ne, &leave); | 2367 __ b(ne, &leave); |
2701 // Load the value. | 2368 // Load the value. |
2702 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); | 2369 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); |
2703 __ bind(&leave); | 2370 __ bind(&leave); |
2704 __ push(r0); | 2371 __ push(r0); |
2705 } | 2372 } |
2706 | 2373 |
2707 | 2374 |
2708 void ArmCodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { | 2375 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { |
2709 ASSERT(args->length() == 2); | 2376 ASSERT(args->length() == 2); |
2710 Label leave; | 2377 Label leave; |
2711 Load(args->at(0)); // Load the object. | 2378 Load(args->at(0)); // Load the object. |
2712 Load(args->at(1)); // Load the value. | 2379 Load(args->at(1)); // Load the value. |
2713 __ pop(r0); // r0 contains value | 2380 __ pop(r0); // r0 contains value |
2714 __ pop(r1); // r1 contains object | 2381 __ pop(r1); // r1 contains object |
2715 // if (object->IsSmi()) return object. | 2382 // if (object->IsSmi()) return object. |
2716 __ tst(r1, Operand(kSmiTagMask)); | 2383 __ tst(r1, Operand(kSmiTagMask)); |
2717 __ b(eq, &leave); | 2384 __ b(eq, &leave); |
2718 // It is a heap object - get map. | 2385 // It is a heap object - get map. |
2719 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); | 2386 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); |
2720 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 2387 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
2721 // if (!object->IsJSValue()) return object. | 2388 // if (!object->IsJSValue()) return object. |
2722 __ cmp(r2, Operand(JS_VALUE_TYPE)); | 2389 __ cmp(r2, Operand(JS_VALUE_TYPE)); |
2723 __ b(ne, &leave); | 2390 __ b(ne, &leave); |
2724 // Store the value. | 2391 // Store the value. |
2725 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); | 2392 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); |
2726 // Update the write barrier. | 2393 // Update the write barrier. |
2727 __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag)); | 2394 __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag)); |
2728 __ RecordWrite(r1, r2, r3); | 2395 __ RecordWrite(r1, r2, r3); |
2729 // Leave. | 2396 // Leave. |
2730 __ bind(&leave); | 2397 __ bind(&leave); |
2731 __ push(r0); | 2398 __ push(r0); |
2732 } | 2399 } |
2733 | 2400 |
2734 | 2401 |
2735 void ArmCodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { | 2402 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { |
2736 ASSERT(args->length() == 1); | 2403 ASSERT(args->length() == 1); |
2737 Load(args->at(0)); | 2404 Load(args->at(0)); |
2738 __ pop(r0); | 2405 __ pop(r0); |
2739 __ tst(r0, Operand(kSmiTagMask)); | 2406 __ tst(r0, Operand(kSmiTagMask)); |
2740 cc_reg_ = eq; | 2407 cc_reg_ = eq; |
2741 } | 2408 } |
2742 | 2409 |
2743 | 2410 |
2744 void ArmCodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { | 2411 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { |
2745 ASSERT(args->length() == 1); | 2412 ASSERT(args->length() == 1); |
2746 Load(args->at(0)); | 2413 Load(args->at(0)); |
2747 __ pop(r0); | 2414 __ pop(r0); |
2748 __ tst(r0, Operand(kSmiTagMask | 0x80000000)); | 2415 __ tst(r0, Operand(kSmiTagMask | 0x80000000)); |
2749 cc_reg_ = eq; | 2416 cc_reg_ = eq; |
2750 } | 2417 } |
2751 | 2418 |
2752 | 2419 |
2753 // This should generate code that performs a charCodeAt() call or returns | 2420 // This should generate code that performs a charCodeAt() call or returns |
2754 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. | 2421 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. |
2755 // It is not yet implemented on ARM, so it always goes to the slow case. | 2422 // It is not yet implemented on ARM, so it always goes to the slow case. |
2756 void ArmCodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { | 2423 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { |
2757 ASSERT(args->length() == 2); | 2424 ASSERT(args->length() == 2); |
2758 __ mov(r0, Operand(Factory::undefined_value())); | 2425 __ mov(r0, Operand(Factory::undefined_value())); |
2759 __ push(r0); | 2426 __ push(r0); |
2760 } | 2427 } |
2761 | 2428 |
2762 | 2429 |
2763 void ArmCodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { | 2430 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { |
2764 ASSERT(args->length() == 1); | 2431 ASSERT(args->length() == 1); |
2765 Load(args->at(0)); | 2432 Load(args->at(0)); |
2766 Label answer; | 2433 Label answer; |
2767 // We need the CC bits to come out as not_equal in the case where the | 2434 // We need the CC bits to come out as not_equal in the case where the |
2768 // object is a smi. This can't be done with the usual test opcode so | 2435 // object is a smi. This can't be done with the usual test opcode so |
2769 // we use XOR to get the right CC bits. | 2436 // we use XOR to get the right CC bits. |
2770 __ pop(r0); | 2437 __ pop(r0); |
2771 __ and_(r1, r0, Operand(kSmiTagMask)); | 2438 __ and_(r1, r0, Operand(kSmiTagMask)); |
2772 __ eor(r1, r1, Operand(kSmiTagMask), SetCC); | 2439 __ eor(r1, r1, Operand(kSmiTagMask), SetCC); |
2773 __ b(ne, &answer); | 2440 __ b(ne, &answer); |
2774 // It is a heap object - get the map. | 2441 // It is a heap object - get the map. |
2775 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 2442 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
2776 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); | 2443 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
2777 // Check if the object is a JS array or not. | 2444 // Check if the object is a JS array or not. |
2778 __ cmp(r1, Operand(JS_ARRAY_TYPE)); | 2445 __ cmp(r1, Operand(JS_ARRAY_TYPE)); |
2779 __ bind(&answer); | 2446 __ bind(&answer); |
2780 cc_reg_ = eq; | 2447 cc_reg_ = eq; |
2781 } | 2448 } |
2782 | 2449 |
2783 | 2450 |
2784 void ArmCodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { | 2451 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { |
2785 ASSERT(args->length() == 0); | 2452 ASSERT(args->length() == 0); |
2786 | 2453 |
2787 // Seed the result with the formal parameters count, which will be used | 2454 // Seed the result with the formal parameters count, which will be used |
2788 // in case no arguments adaptor frame is found below the current frame. | 2455 // in case no arguments adaptor frame is found below the current frame. |
2789 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); | 2456 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); |
2790 | 2457 |
2791 // Call the shared stub to get to the arguments.length. | 2458 // Call the shared stub to get to the arguments.length. |
2792 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); | 2459 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); |
2793 __ CallStub(&stub); | 2460 __ CallStub(&stub); |
2794 __ push(r0); | 2461 __ push(r0); |
2795 } | 2462 } |
2796 | 2463 |
2797 | 2464 |
2798 void ArmCodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { | 2465 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { |
2799 ASSERT(args->length() == 1); | 2466 ASSERT(args->length() == 1); |
2800 | 2467 |
2801 // Satisfy contract with ArgumentsAccessStub: | 2468 // Satisfy contract with ArgumentsAccessStub: |
2802 // Load the key into r1 and the formal parameters count into r0. | 2469 // Load the key into r1 and the formal parameters count into r0. |
2803 Load(args->at(0)); | 2470 Load(args->at(0)); |
2804 __ pop(r1); | 2471 __ pop(r1); |
2805 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); | 2472 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); |
2806 | 2473 |
2807 // Call the shared stub to get to arguments[key]. | 2474 // Call the shared stub to get to arguments[key]. |
2808 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); | 2475 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); |
2809 __ CallStub(&stub); | 2476 __ CallStub(&stub); |
2810 __ push(r0); | 2477 __ push(r0); |
2811 } | 2478 } |
2812 | 2479 |
2813 | 2480 |
2814 void ArmCodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { | 2481 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { |
2815 ASSERT(args->length() == 2); | 2482 ASSERT(args->length() == 2); |
2816 | 2483 |
2817 // Load the two objects into registers and perform the comparison. | 2484 // Load the two objects into registers and perform the comparison. |
2818 Load(args->at(0)); | 2485 Load(args->at(0)); |
2819 Load(args->at(1)); | 2486 Load(args->at(1)); |
2820 __ pop(r0); | 2487 __ pop(r0); |
2821 __ pop(r1); | 2488 __ pop(r1); |
2822 __ cmp(r0, Operand(r1)); | 2489 __ cmp(r0, Operand(r1)); |
2823 cc_reg_ = eq; | 2490 cc_reg_ = eq; |
2824 } | 2491 } |
2825 | 2492 |
2826 | 2493 |
2827 void ArmCodeGenerator::VisitCallRuntime(CallRuntime* node) { | 2494 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { |
2828 if (CheckForInlineRuntimeCall(node)) return; | 2495 if (CheckForInlineRuntimeCall(node)) return; |
2829 | 2496 |
2830 ZoneList<Expression*>* args = node->arguments(); | 2497 ZoneList<Expression*>* args = node->arguments(); |
2831 Comment cmnt(masm_, "[ CallRuntime"); | 2498 Comment cmnt(masm_, "[ CallRuntime"); |
2832 Runtime::Function* function = node->function(); | 2499 Runtime::Function* function = node->function(); |
2833 | 2500 |
2834 if (function != NULL) { | 2501 if (function != NULL) { |
2835 // Push the arguments ("left-to-right"). | 2502 // Push the arguments ("left-to-right"). |
2836 for (int i = 0; i < args->length(); i++) Load(args->at(i)); | 2503 for (int i = 0; i < args->length(); i++) Load(args->at(i)); |
2837 | 2504 |
(...skipping 15 matching lines...) Expand all Loading... |
2853 // Call the JS runtime function. | 2520 // Call the JS runtime function. |
2854 Handle<Code> stub = ComputeCallInitialize(args->length()); | 2521 Handle<Code> stub = ComputeCallInitialize(args->length()); |
2855 __ Call(stub, RelocInfo::CODE_TARGET); | 2522 __ Call(stub, RelocInfo::CODE_TARGET); |
2856 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2523 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2857 __ pop(); | 2524 __ pop(); |
2858 __ push(r0); | 2525 __ push(r0); |
2859 } | 2526 } |
2860 } | 2527 } |
2861 | 2528 |
2862 | 2529 |
2863 void ArmCodeGenerator::VisitUnaryOperation(UnaryOperation* node) { | 2530 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { |
2864 Comment cmnt(masm_, "[ UnaryOperation"); | 2531 Comment cmnt(masm_, "[ UnaryOperation"); |
2865 | 2532 |
2866 Token::Value op = node->op(); | 2533 Token::Value op = node->op(); |
2867 | 2534 |
2868 if (op == Token::NOT) { | 2535 if (op == Token::NOT) { |
2869 LoadCondition(node->expression(), | 2536 LoadCondition(node->expression(), |
2870 NOT_INSIDE_TYPEOF, | 2537 NOT_INSIDE_TYPEOF, |
2871 false_target(), | 2538 false_target(), |
2872 true_target(), | 2539 true_target(), |
2873 true); | 2540 true); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2978 break; | 2645 break; |
2979 } | 2646 } |
2980 default: | 2647 default: |
2981 UNREACHABLE(); | 2648 UNREACHABLE(); |
2982 } | 2649 } |
2983 __ push(r0); // r0 has result | 2650 __ push(r0); // r0 has result |
2984 } | 2651 } |
2985 } | 2652 } |
2986 | 2653 |
2987 | 2654 |
2988 void ArmCodeGenerator::VisitCountOperation(CountOperation* node) { | 2655 void CodeGenerator::VisitCountOperation(CountOperation* node) { |
2989 Comment cmnt(masm_, "[ CountOperation"); | 2656 Comment cmnt(masm_, "[ CountOperation"); |
2990 | 2657 |
2991 bool is_postfix = node->is_postfix(); | 2658 bool is_postfix = node->is_postfix(); |
2992 bool is_increment = node->op() == Token::INC; | 2659 bool is_increment = node->op() == Token::INC; |
2993 | 2660 |
2994 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); | 2661 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); |
2995 bool is_const = (var != NULL && var->mode() == Variable::CONST); | 2662 bool is_const = (var != NULL && var->mode() == Variable::CONST); |
2996 | 2663 |
2997 // Postfix: Make room for the result. | 2664 // Postfix: Make room for the result. |
2998 if (is_postfix) { | 2665 if (is_postfix) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3058 __ bind(&exit); | 2725 __ bind(&exit); |
3059 __ push(r0); | 2726 __ push(r0); |
3060 if (!is_const) target.SetValue(NOT_CONST_INIT); | 2727 if (!is_const) target.SetValue(NOT_CONST_INIT); |
3061 } | 2728 } |
3062 | 2729 |
3063 // Postfix: Discard the new value and use the old. | 2730 // Postfix: Discard the new value and use the old. |
3064 if (is_postfix) __ pop(r0); | 2731 if (is_postfix) __ pop(r0); |
3065 } | 2732 } |
3066 | 2733 |
3067 | 2734 |
3068 void ArmCodeGenerator::VisitBinaryOperation(BinaryOperation* node) { | 2735 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { |
3069 Comment cmnt(masm_, "[ BinaryOperation"); | 2736 Comment cmnt(masm_, "[ BinaryOperation"); |
3070 Token::Value op = node->op(); | 2737 Token::Value op = node->op(); |
3071 | 2738 |
3072 // According to ECMA-262 section 11.11, page 58, the binary logical | 2739 // According to ECMA-262 section 11.11, page 58, the binary logical |
3073 // operators must yield the result of one of the two expressions | 2740 // operators must yield the result of one of the two expressions |
3074 // before any ToBoolean() conversions. This means that the value | 2741 // before any ToBoolean() conversions. This means that the value |
3075 // produced by a && or || operator is not necessarily a boolean. | 2742 // produced by a && or || operator is not necessarily a boolean. |
3076 | 2743 |
3077 // NOTE: If the left hand side produces a materialized value (not in | 2744 // NOTE: If the left hand side produces a materialized value (not in |
3078 // the CC register), we force the right hand side to do the | 2745 // the CC register), we force the right hand side to do the |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3180 } else { | 2847 } else { |
3181 Load(node->left()); | 2848 Load(node->left()); |
3182 Load(node->right()); | 2849 Load(node->right()); |
3183 GenericBinaryOperation(node->op()); | 2850 GenericBinaryOperation(node->op()); |
3184 } | 2851 } |
3185 __ push(r0); | 2852 __ push(r0); |
3186 } | 2853 } |
3187 } | 2854 } |
3188 | 2855 |
3189 | 2856 |
3190 void ArmCodeGenerator::VisitThisFunction(ThisFunction* node) { | 2857 void CodeGenerator::VisitThisFunction(ThisFunction* node) { |
3191 __ ldr(r0, FunctionOperand()); | 2858 __ ldr(r0, FunctionOperand()); |
3192 __ push(r0); | 2859 __ push(r0); |
3193 } | 2860 } |
3194 | 2861 |
3195 | 2862 |
3196 void ArmCodeGenerator::VisitCompareOperation(CompareOperation* node) { | 2863 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { |
3197 Comment cmnt(masm_, "[ CompareOperation"); | 2864 Comment cmnt(masm_, "[ CompareOperation"); |
3198 | 2865 |
3199 // Get the expressions from the node. | 2866 // Get the expressions from the node. |
3200 Expression* left = node->left(); | 2867 Expression* left = node->left(); |
3201 Expression* right = node->right(); | 2868 Expression* right = node->right(); |
3202 Token::Value op = node->op(); | 2869 Token::Value op = node->op(); |
3203 | 2870 |
3204 // NOTE: To make null checks efficient, we check if either left or | 2871 // NOTE: To make null checks efficient, we check if either left or |
3205 // right is the literal 'null'. If so, we optimize the code by | 2872 // right is the literal 'null'. If so, we optimize the code by |
3206 // inlining a null check instead of calling the (very) general | 2873 // inlining a null check instead of calling the (very) general |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3381 __ tst(r0, Operand(r0)); | 3048 __ tst(r0, Operand(r0)); |
3382 cc_reg_ = eq; | 3049 cc_reg_ = eq; |
3383 break; | 3050 break; |
3384 | 3051 |
3385 default: | 3052 default: |
3386 UNREACHABLE(); | 3053 UNREACHABLE(); |
3387 } | 3054 } |
3388 } | 3055 } |
3389 | 3056 |
3390 | 3057 |
3391 void ArmCodeGenerator::RecordStatementPosition(Node* node) { | 3058 void CodeGenerator::RecordStatementPosition(Node* node) { |
3392 if (FLAG_debug_info) { | 3059 if (FLAG_debug_info) { |
3393 int statement_pos = node->statement_pos(); | 3060 int statement_pos = node->statement_pos(); |
3394 if (statement_pos == RelocInfo::kNoPosition) return; | 3061 if (statement_pos == RelocInfo::kNoPosition) return; |
3395 __ RecordStatementPosition(statement_pos); | 3062 __ RecordStatementPosition(statement_pos); |
3396 } | 3063 } |
3397 } | 3064 } |
3398 | 3065 |
3399 | 3066 |
3400 void ArmCodeGenerator::EnterJSFrame() { | 3067 void CodeGenerator::EnterJSFrame() { |
3401 #if defined(DEBUG) | 3068 #if defined(DEBUG) |
3402 { Label done, fail; | 3069 { Label done, fail; |
3403 __ tst(r1, Operand(kSmiTagMask)); | 3070 __ tst(r1, Operand(kSmiTagMask)); |
3404 __ b(eq, &fail); | 3071 __ b(eq, &fail); |
3405 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); | 3072 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); |
3406 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 3073 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
3407 __ cmp(r2, Operand(JS_FUNCTION_TYPE)); | 3074 __ cmp(r2, Operand(JS_FUNCTION_TYPE)); |
3408 __ b(eq, &done); | 3075 __ b(eq, &done); |
3409 __ bind(&fail); | 3076 __ bind(&fail); |
3410 __ stop("ArmCodeGenerator::EnterJSFrame - r1 not a function"); | 3077 __ stop("CodeGenerator::EnterJSFrame - r1 not a function"); |
3411 __ bind(&done); | 3078 __ bind(&done); |
3412 } | 3079 } |
3413 #endif // DEBUG | 3080 #endif // DEBUG |
3414 | 3081 |
3415 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); | 3082 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); |
3416 __ add(fp, sp, Operand(2 * kPointerSize)); // Adjust FP to point to saved FP. | 3083 __ add(fp, sp, Operand(2 * kPointerSize)); // Adjust FP to point to saved FP. |
3417 } | 3084 } |
3418 | 3085 |
3419 | 3086 |
3420 void ArmCodeGenerator::ExitJSFrame() { | 3087 void CodeGenerator::ExitJSFrame() { |
3421 // Drop the execution stack down to the frame pointer and restore the caller | 3088 // Drop the execution stack down to the frame pointer and restore the caller |
3422 // frame pointer and return address. | 3089 // frame pointer and return address. |
3423 __ mov(sp, fp); | 3090 __ mov(sp, fp); |
3424 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | 3091 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
3425 } | 3092 } |
3426 | 3093 |
3427 | 3094 |
3428 #undef __ | 3095 #undef __ |
3429 #define __ masm-> | 3096 #define __ masm-> |
3430 | 3097 |
(...skipping 1061 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4492 | 4159 |
4493 // Slow-case: Non-function called. | 4160 // Slow-case: Non-function called. |
4494 __ bind(&slow); | 4161 __ bind(&slow); |
4495 __ mov(r0, Operand(argc_)); // Setup the number of arguments. | 4162 __ mov(r0, Operand(argc_)); // Setup the number of arguments. |
4496 __ InvokeBuiltin(Builtins::CALL_NON_FUNCTION, JUMP_JS); | 4163 __ InvokeBuiltin(Builtins::CALL_NON_FUNCTION, JUMP_JS); |
4497 } | 4164 } |
4498 | 4165 |
4499 | 4166 |
4500 #undef __ | 4167 #undef __ |
4501 | 4168 |
4502 // ----------------------------------------------------------------------------- | |
4503 // CodeGenerator interface | |
4504 | |
4505 // MakeCode() is just a wrapper for CodeGenerator::MakeCode() | |
4506 // so we don't have to expose the entire CodeGenerator class in | |
4507 // the .h file. | |
4508 Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* fun, | |
4509 Handle<Script> script, | |
4510 bool is_eval) { | |
4511 Handle<Code> code = ArmCodeGenerator::MakeCode(fun, script, is_eval); | |
4512 if (!code.is_null()) { | |
4513 Counters::total_compiled_code_size.Increment(code->instruction_size()); | |
4514 } | |
4515 return code; | |
4516 } | |
4517 | |
4518 | |
4519 } } // namespace v8::internal | 4169 } } // namespace v8::internal |
OLD | NEW |