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

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

Issue 6334: Simplify CodeGenerator hierarchy by not using a base class. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/codegen-arm.h ('k') | src/codegen-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/codegen-arm.h ('k') | src/codegen-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698