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

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

Issue 10693: Merged bleeding_edge -r 685:746 into regexp2000. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/regexp2000/
Patch Set: Created 12 years, 1 month 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 17 matching lines...) Expand all
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 "scopes.h" 33 #include "scopes.h"
34 #include "runtime.h" 34 #include "runtime.h"
35 35
36 namespace v8 { namespace internal { 36 namespace v8 { namespace internal {
37 37
38 #define __ masm_->
39
40 // -------------------------------------------------------------------------
41 // VirtualFrame implementation.
42
43 VirtualFrame::VirtualFrame(CodeGenerator* cgen) {
44 ASSERT(cgen->scope() != NULL);
45
46 masm_ = cgen->masm();
47 frame_local_count_ = cgen->scope()->num_stack_slots();
48 parameter_count_ = cgen->scope()->num_parameters();
49 }
50
51
52 void VirtualFrame::Enter() {
53 Comment cmnt(masm_, "[ Enter JS frame");
54 #ifdef DEBUG
55 { Label done, fail;
56 __ tst(r1, Operand(kSmiTagMask));
57 __ b(eq, &fail);
58 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
59 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
60 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
61 __ b(eq, &done);
62 __ bind(&fail);
63 __ stop("CodeGenerator::EnterJSFrame - r1 not a function");
64 __ bind(&done);
65 }
66 #endif // DEBUG
67
68 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
69 // Adjust FP to point to saved FP.
70 __ add(fp, sp, Operand(2 * kPointerSize));
71 }
72
73
74 void VirtualFrame::Exit() {
75 Comment cmnt(masm_, "[ Exit JS frame");
76 // Drop the execution stack down to the frame pointer and restore the caller
77 // frame pointer and return address.
78 __ mov(sp, fp);
79 __ ldm(ia_w, sp, fp.bit() | lr.bit());
80 }
81
82
83 void VirtualFrame::AllocateLocals() {
84 if (frame_local_count_ > 0) {
85 Comment cmnt(masm_, "[ Allocate space for locals");
86 // Initialize stack slots with 'undefined' value.
87 __ mov(ip, Operand(Factory::undefined_value()));
88 for (int i = 0; i < frame_local_count_; i++) {
89 __ push(ip);
90 }
91 }
92 }
93
94
95 void VirtualFrame::Drop(int count) {
96 ASSERT(count >= 0);
97 if (count > 0) {
98 __ add(sp, sp, Operand(count * kPointerSize));
99 }
100 }
101
102
103 void VirtualFrame::Pop() { Drop(1); }
104
105
106 void VirtualFrame::Pop(Register reg) {
107 __ pop(reg);
108 }
109
110
111 void VirtualFrame::Push(Register reg) {
112 __ push(reg);
113 }
114
115
38 // ------------------------------------------------------------------------- 116 // -------------------------------------------------------------------------
39 // CodeGenState implementation. 117 // CodeGenState implementation.
40 118
41 CodeGenState::CodeGenState(CodeGenerator* owner) 119 CodeGenState::CodeGenState(CodeGenerator* owner)
42 : owner_(owner), 120 : owner_(owner),
43 typeof_state_(NOT_INSIDE_TYPEOF), 121 typeof_state_(NOT_INSIDE_TYPEOF),
44 true_target_(NULL), 122 true_target_(NULL),
45 false_target_(NULL), 123 false_target_(NULL),
46 previous_(NULL) { 124 previous_(NULL) {
47 owner_->set_state(this); 125 owner_->set_state(this);
(...skipping 12 matching lines...) Expand all
60 owner_->set_state(this); 138 owner_->set_state(this);
61 } 139 }
62 140
63 141
64 CodeGenState::~CodeGenState() { 142 CodeGenState::~CodeGenState() {
65 ASSERT(owner_->state() == this); 143 ASSERT(owner_->state() == this);
66 owner_->set_state(previous_); 144 owner_->set_state(previous_);
67 } 145 }
68 146
69 147
70 // ----------------------------------------------------------------------------- 148 // -------------------------------------------------------------------------
71 // CodeGenerator implementation 149 // CodeGenerator implementation
72 150
73 #define __ masm_->
74
75 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script, 151 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script,
76 bool is_eval) 152 bool is_eval)
77 : is_eval_(is_eval), 153 : is_eval_(is_eval),
78 script_(script), 154 script_(script),
79 deferred_(8), 155 deferred_(8),
80 masm_(new MacroAssembler(NULL, buffer_size)), 156 masm_(new MacroAssembler(NULL, buffer_size)),
81 scope_(NULL), 157 scope_(NULL),
158 frame_(NULL),
82 cc_reg_(al), 159 cc_reg_(al),
83 state_(NULL), 160 state_(NULL),
84 break_stack_height_(0) { 161 break_stack_height_(0) {
85 } 162 }
86 163
87 164
88 // Calling conventions: 165 // Calling conventions:
89
90 // r0: the number of arguments 166 // r0: the number of arguments
91 // fp: frame pointer 167 // fp: frame pointer
92 // sp: stack pointer 168 // sp: stack pointer
93 // pp: caller's parameter pointer 169 // pp: caller's parameter pointer
94 // cp: callee's context 170 // cp: callee's context
95 171
96 void CodeGenerator::GenCode(FunctionLiteral* fun) { 172 void CodeGenerator::GenCode(FunctionLiteral* fun) {
97 Scope* scope = fun->scope();
98 ZoneList<Statement*>* body = fun->body(); 173 ZoneList<Statement*>* body = fun->body();
99 174
100 // Initialize state. 175 // Initialize state.
101 { CodeGenState state(this); 176 ASSERT(scope_ == NULL);
102 scope_ = scope; 177 scope_ = fun->scope();
103 cc_reg_ = al; 178 ASSERT(frame_ == NULL);
179 VirtualFrame virtual_frame(this);
180 frame_ = &virtual_frame;
181 cc_reg_ = al;
182 {
183 CodeGenState state(this);
104 184
105 // Entry 185 // Entry
106 // stack: function, receiver, arguments, return address 186 // stack: function, receiver, arguments, return address
107 // r0: number of arguments 187 // r0: number of arguments
108 // sp: stack pointer 188 // sp: stack pointer
109 // fp: frame pointer 189 // fp: frame pointer
110 // pp: caller's parameter pointer 190 // pp: caller's parameter pointer
111 // cp: callee's context 191 // cp: callee's context
112 192
113 { Comment cmnt(masm_, "[ enter JS frame"); 193 frame_->Enter();
114 EnterJSFrame();
115 }
116 // tos: code slot 194 // tos: code slot
117 #ifdef DEBUG 195 #ifdef DEBUG
118 if (strlen(FLAG_stop_at) > 0 && 196 if (strlen(FLAG_stop_at) > 0 &&
119 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 197 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
120 __ stop("stop-at"); 198 __ stop("stop-at");
121 } 199 }
122 #endif 200 #endif
123 201
124 // Allocate space for locals and initialize them. 202 // Allocate space for locals and initialize them.
125 if (scope->num_stack_slots() > 0) { 203 frame_->AllocateLocals();
126 Comment cmnt(masm_, "[ allocate space for locals");
127 // Initialize stack slots with 'undefined' value.
128 __ mov(ip, Operand(Factory::undefined_value()));
129 for (int i = 0; i < scope->num_stack_slots(); i++) {
130 __ push(ip);
131 }
132 }
133 204
134 if (scope->num_heap_slots() > 0) { 205 if (scope_->num_heap_slots() > 0) {
135 // Allocate local context. 206 // Allocate local context.
136 // Get outer context and create a new context based on it. 207 // Get outer context and create a new context based on it.
137 __ ldr(r0, FunctionOperand()); 208 __ ldr(r0, frame_->Function());
138 __ push(r0); 209 frame_->Push(r0);
139 __ CallRuntime(Runtime::kNewContext, 1); // r0 holds the result 210 __ CallRuntime(Runtime::kNewContext, 1); // r0 holds the result
140 211
141 if (kDebug) { 212 if (kDebug) {
142 Label verified_true; 213 Label verified_true;
143 __ cmp(r0, Operand(cp)); 214 __ cmp(r0, Operand(cp));
144 __ b(eq, &verified_true); 215 __ b(eq, &verified_true);
145 __ stop("NewContext: r0 is expected to be the same as cp"); 216 __ stop("NewContext: r0 is expected to be the same as cp");
146 __ bind(&verified_true); 217 __ bind(&verified_true);
147 } 218 }
148 // Update context local. 219 // Update context local.
149 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 220 __ str(cp, frame_->Context());
150 } 221 }
151 222
152 // TODO(1241774): Improve this code!!! 223 // TODO(1241774): Improve this code:
153 // 1) only needed if we have a context 224 // 1) only needed if we have a context
154 // 2) no need to recompute context ptr every single time 225 // 2) no need to recompute context ptr every single time
155 // 3) don't copy parameter operand code from SlotOperand! 226 // 3) don't copy parameter operand code from SlotOperand!
156 { 227 {
157 Comment cmnt2(masm_, "[ copy context parameters into .context"); 228 Comment cmnt2(masm_, "[ copy context parameters into .context");
158 229
159 // Note that iteration order is relevant here! If we have the same 230 // Note that iteration order is relevant here! If we have the same
160 // parameter twice (e.g., function (x, y, x)), and that parameter 231 // parameter twice (e.g., function (x, y, x)), and that parameter
161 // needs to be copied into the context, it must be the last argument 232 // needs to be copied into the context, it must be the last argument
162 // passed to the parameter that needs to be copied. This is a rare 233 // passed to the parameter that needs to be copied. This is a rare
163 // case so we don't check for it, instead we rely on the copying 234 // case so we don't check for it, instead we rely on the copying
164 // order: such a parameter is copied repeatedly into the same 235 // order: such a parameter is copied repeatedly into the same
165 // context location and thus the last value is what is seen inside 236 // context location and thus the last value is what is seen inside
166 // the function. 237 // the function.
167 for (int i = 0; i < scope->num_parameters(); i++) { 238 for (int i = 0; i < scope_->num_parameters(); i++) {
168 Variable* par = scope->parameter(i); 239 Variable* par = scope_->parameter(i);
169 Slot* slot = par->slot(); 240 Slot* slot = par->slot();
170 if (slot != NULL && slot->type() == Slot::CONTEXT) { 241 if (slot != NULL && slot->type() == Slot::CONTEXT) {
171 ASSERT(!scope->is_global_scope()); // no parameters in global scope 242 ASSERT(!scope_->is_global_scope()); // no parameters in global scope
172 __ ldr(r1, ParameterOperand(i)); 243 __ ldr(r1, frame_->Parameter(i));
173 // Loads r2 with context; used below in RecordWrite. 244 // Loads r2 with context; used below in RecordWrite.
174 __ str(r1, SlotOperand(slot, r2)); 245 __ str(r1, SlotOperand(slot, r2));
175 // Load the offset into r3. 246 // Load the offset into r3.
176 int slot_offset = 247 int slot_offset =
177 FixedArray::kHeaderSize + slot->index() * kPointerSize; 248 FixedArray::kHeaderSize + slot->index() * kPointerSize;
178 __ mov(r3, Operand(slot_offset)); 249 __ mov(r3, Operand(slot_offset));
179 __ RecordWrite(r2, r3, r1); 250 __ RecordWrite(r2, r3, r1);
180 } 251 }
181 } 252 }
182 } 253 }
183 254
184 // Store the arguments object. 255 // Store the arguments object. This must happen after context
185 // This must happen after context initialization because 256 // initialization because the arguments object may be stored in the
186 // the arguments array may be stored in the context! 257 // context.
187 if (scope->arguments() != NULL) { 258 if (scope_->arguments() != NULL) {
188 ASSERT(scope->arguments_shadow() != NULL); 259 ASSERT(scope_->arguments_shadow() != NULL);
189 Comment cmnt(masm_, "[ allocate arguments object"); 260 Comment cmnt(masm_, "[ allocate arguments object");
190 { Reference shadow_ref(this, scope->arguments_shadow()); 261 { Reference shadow_ref(this, scope_->arguments_shadow());
191 { Reference arguments_ref(this, scope->arguments()); 262 { Reference arguments_ref(this, scope_->arguments());
192 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 263 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
193 __ ldr(r2, FunctionOperand()); 264 __ ldr(r2, frame_->Function());
194 // The receiver is below the arguments, the return address, 265 // The receiver is below the arguments, the return address,
195 // and the frame pointer on the stack. 266 // and the frame pointer on the stack.
196 const int kReceiverDisplacement = 2 + scope->num_parameters(); 267 const int kReceiverDisplacement = 2 + scope_->num_parameters();
197 __ add(r1, fp, Operand(kReceiverDisplacement * kPointerSize)); 268 __ add(r1, fp, Operand(kReceiverDisplacement * kPointerSize));
198 __ mov(r0, Operand(Smi::FromInt(scope->num_parameters()))); 269 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
199 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit()); 270 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit());
200 __ CallStub(&stub); 271 __ CallStub(&stub);
201 __ push(r0); 272 frame_->Push(r0);
202 arguments_ref.SetValue(NOT_CONST_INIT); 273 arguments_ref.SetValue(NOT_CONST_INIT);
203 } 274 }
204 shadow_ref.SetValue(NOT_CONST_INIT); 275 shadow_ref.SetValue(NOT_CONST_INIT);
205 } 276 }
206 __ pop(r0); // Value is no longer needed. 277 frame_->Pop(); // Value is no longer needed.
207 } 278 }
208 279
209 // Generate code to 'execute' declarations and initialize 280 // Generate code to 'execute' declarations and initialize functions
210 // functions (source elements). In case of an illegal 281 // (source elements). In case of an illegal redeclaration we need to
211 // redeclaration we need to handle that instead of processing the 282 // handle that instead of processing the declarations.
212 // declarations. 283 if (scope_->HasIllegalRedeclaration()) {
213 if (scope->HasIllegalRedeclaration()) {
214 Comment cmnt(masm_, "[ illegal redeclarations"); 284 Comment cmnt(masm_, "[ illegal redeclarations");
215 scope->VisitIllegalRedeclaration(this); 285 scope_->VisitIllegalRedeclaration(this);
216 } else { 286 } else {
217 Comment cmnt(masm_, "[ declarations"); 287 Comment cmnt(masm_, "[ declarations");
218 // ProcessDeclarations calls DeclareGlobals indirectly 288 ProcessDeclarations(scope_->declarations());
219 ProcessDeclarations(scope->declarations()); 289 // Bail out if a stack-overflow exception occurred when processing
220 290 // declarations.
221 // Bail out if a stack-overflow exception occurred when
222 // processing declarations.
223 if (HasStackOverflow()) return; 291 if (HasStackOverflow()) return;
224 } 292 }
225 293
226 if (FLAG_trace) { 294 if (FLAG_trace) {
227 // Push a valid value as the parameter. The runtime call only uses
228 // it as the return value to indicate non-failure.
229 __ CallRuntime(Runtime::kTraceEnter, 0); 295 __ CallRuntime(Runtime::kTraceEnter, 0);
296 // Ignore the return value.
230 } 297 }
231 CheckStack(); 298 CheckStack();
232 299
233 // Compile the body of the function in a vanilla state. Don't 300 // Compile the body of the function in a vanilla state. Don't
234 // bother compiling all the code if the scope has an illegal 301 // bother compiling all the code if the scope has an illegal
235 // redeclaration. 302 // redeclaration.
236 if (!scope->HasIllegalRedeclaration()) { 303 if (!scope_->HasIllegalRedeclaration()) {
237 Comment cmnt(masm_, "[ function body"); 304 Comment cmnt(masm_, "[ function body");
238 #ifdef DEBUG 305 #ifdef DEBUG
239 bool is_builtin = Bootstrapper::IsActive(); 306 bool is_builtin = Bootstrapper::IsActive();
240 bool should_trace = 307 bool should_trace =
241 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; 308 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;
242 if (should_trace) { 309 if (should_trace) {
243 __ CallRuntime(Runtime::kDebugTrace, 0); 310 __ CallRuntime(Runtime::kDebugTrace, 0);
311 // Ignore the return value.
244 } 312 }
245 #endif 313 #endif
246 VisitStatements(body); 314 VisitStatements(body);
247 } 315 }
248 } 316 }
249 317
250 // exit 318 // exit
251 // r0: result 319 // r0: result
252 // sp: stack pointer 320 // sp: stack pointer
253 // fp: frame pointer 321 // fp: frame pointer
254 // pp: parameter pointer 322 // pp: parameter pointer
255 // cp: callee's context 323 // cp: callee's context
256 __ mov(r0, Operand(Factory::undefined_value())); 324 __ mov(r0, Operand(Factory::undefined_value()));
257 325
258 __ bind(&function_return_); 326 __ bind(&function_return_);
259 if (FLAG_trace) { 327 if (FLAG_trace) {
260 // Push the return value on the stack as the parameter. 328 // Push the return value on the stack as the parameter.
261 // Runtime::TraceExit returns the parameter as it is. 329 // Runtime::TraceExit returns the parameter as it is.
262 __ push(r0); 330 frame_->Push(r0);
263 __ CallRuntime(Runtime::kTraceExit, 1); 331 __ CallRuntime(Runtime::kTraceExit, 1);
264 } 332 }
265 333
266 // Tear down the frame which will restore the caller's frame pointer and the 334 // Tear down the frame which will restore the caller's frame pointer and the
267 // link register. 335 // link register.
268 ExitJSFrame(); 336 frame_->Exit();
269 337
270 __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize)); 338 __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize));
271 __ mov(pc, lr); 339 __ mov(pc, lr);
272 340
273 // Code generation state must be reset. 341 // Code generation state must be reset.
274 scope_ = NULL; 342 scope_ = NULL;
343 frame_ = NULL;
275 ASSERT(!has_cc()); 344 ASSERT(!has_cc());
276 ASSERT(state_ == NULL); 345 ASSERT(state_ == NULL);
277 } 346 }
278 347
279 348
280 MemOperand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { 349 MemOperand CodeGenerator::SlotOperand(Slot* slot, Register tmp) {
281 // Currently, this assertion will fail if we try to assign to 350 // Currently, this assertion will fail if we try to assign to
282 // a constant variable that is constant because it is read-only 351 // a constant variable that is constant because it is read-only
283 // (such as the variable referring to a named function expression). 352 // (such as the variable referring to a named function expression).
284 // We need to implement assignments to read-only variables. 353 // We need to implement assignments to read-only variables.
285 // Ideally, we should do this during AST generation (by converting 354 // Ideally, we should do this during AST generation (by converting
286 // such assignments into expression statements); however, in general 355 // such assignments into expression statements); however, in general
287 // we may not be able to make the decision until past AST generation, 356 // we may not be able to make the decision until past AST generation,
288 // that is when the entire program is known. 357 // that is when the entire program is known.
289 ASSERT(slot != NULL); 358 ASSERT(slot != NULL);
290 int index = slot->index(); 359 int index = slot->index();
291 switch (slot->type()) { 360 switch (slot->type()) {
292 case Slot::PARAMETER: 361 case Slot::PARAMETER:
293 return ParameterOperand(index); 362 return frame_->Parameter(index);
294 363
295 case Slot::LOCAL: { 364 case Slot::LOCAL:
296 ASSERT(0 <= index && index < scope()->num_stack_slots()); 365 return frame_->Local(index);
297 const int kLocalOffset = JavaScriptFrameConstants::kLocal0Offset;
298 return MemOperand(fp, kLocalOffset - index * kPointerSize);
299 }
300 366
301 case Slot::CONTEXT: { 367 case Slot::CONTEXT: {
302 // Follow the context chain if necessary. 368 // Follow the context chain if necessary.
303 ASSERT(!tmp.is(cp)); // do not overwrite context register 369 ASSERT(!tmp.is(cp)); // do not overwrite context register
304 Register context = cp; 370 Register context = cp;
305 int chain_length = scope()->ContextChainLength(slot->var()->scope()); 371 int chain_length = scope()->ContextChainLength(slot->var()->scope());
306 for (int i = chain_length; i-- > 0;) { 372 for (int i = chain_length; i-- > 0;) {
307 // Load the closure. 373 // Load the closure.
308 // (All contexts, even 'with' contexts, have a closure, 374 // (All contexts, even 'with' contexts, have a closure,
309 // and it is the same for all contexts inside a function. 375 // and it is the same for all contexts inside a function.
(...skipping 14 matching lines...) Expand all
324 return ContextOperand(tmp, index); 390 return ContextOperand(tmp, index);
325 } 391 }
326 392
327 default: 393 default:
328 UNREACHABLE(); 394 UNREACHABLE();
329 return MemOperand(r0, 0); 395 return MemOperand(r0, 0);
330 } 396 }
331 } 397 }
332 398
333 399
334 // Loads a value on the stack. If it is a boolean value, the result may have 400 // Loads a value on TOS. If it is a boolean value, the result may have been
335 // been (partially) translated into branches, or it may have set the condition 401 // (partially) translated into branches, or it may have set the condition
336 // code register. If force_cc is set, the value is forced to set the condition 402 // code register. If force_cc is set, the value is forced to set the
337 // code register and no value is pushed. If the condition code register was set, 403 // condition code register and no value is pushed. If the condition code
338 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. 404 // register was set, has_cc() is true and cc_reg_ contains the condition to
405 // test for 'true'.
339 void CodeGenerator::LoadCondition(Expression* x, 406 void CodeGenerator::LoadCondition(Expression* x,
340 TypeofState typeof_state, 407 TypeofState typeof_state,
341 Label* true_target, 408 Label* true_target,
342 Label* false_target, 409 Label* false_target,
343 bool force_cc) { 410 bool force_cc) {
344 ASSERT(!has_cc()); 411 ASSERT(!has_cc());
345 412
346 { CodeGenState new_state(this, typeof_state, true_target, false_target); 413 { CodeGenState new_state(this, typeof_state, true_target, false_target);
347 Visit(x); 414 Visit(x);
348 } 415 }
349 if (force_cc && !has_cc()) { 416 if (force_cc && !has_cc()) {
350 // Convert the TOS value to a boolean in the condition code register. 417 // Convert the TOS value to a boolean in the condition code register.
418 // Visiting an expression may possibly choose neither (a) to leave a
419 // value in the condition code register nor (b) to leave a value in TOS
420 // (eg, by compiling to only jumps to the targets). In that case the
421 // code generated by ToBoolean is wrong because it assumes the value of
422 // the expression in TOS. So long as there is always a value in TOS or
423 // the condition code register when control falls through to here (there
424 // is), the code generated by ToBoolean is dead and therefore safe.
351 ToBoolean(true_target, false_target); 425 ToBoolean(true_target, false_target);
352 } 426 }
353 ASSERT(has_cc() || !force_cc); 427 ASSERT(has_cc() || !force_cc);
354 } 428 }
355 429
356 430
357 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { 431 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
358 Label true_target; 432 Label true_target;
359 Label false_target; 433 Label false_target;
360 LoadCondition(x, typeof_state, &true_target, &false_target, false); 434 LoadCondition(x, typeof_state, &true_target, &false_target, false);
361 435
362 if (has_cc()) { 436 if (has_cc()) {
363 // convert cc_reg_ into a bool 437 // convert cc_reg_ into a bool
364 Label loaded, materialize_true; 438 Label loaded, materialize_true;
365 __ b(cc_reg_, &materialize_true); 439 __ b(cc_reg_, &materialize_true);
366 __ mov(r0, Operand(Factory::false_value())); 440 __ mov(r0, Operand(Factory::false_value()));
367 __ push(r0); 441 frame_->Push(r0);
368 __ b(&loaded); 442 __ b(&loaded);
369 __ bind(&materialize_true); 443 __ bind(&materialize_true);
370 __ mov(r0, Operand(Factory::true_value())); 444 __ mov(r0, Operand(Factory::true_value()));
371 __ push(r0); 445 frame_->Push(r0);
372 __ bind(&loaded); 446 __ bind(&loaded);
373 cc_reg_ = al; 447 cc_reg_ = al;
374 } 448 }
375 449
376 if (true_target.is_linked() || false_target.is_linked()) { 450 if (true_target.is_linked() || false_target.is_linked()) {
377 // we have at least one condition value 451 // we have at least one condition value
378 // that has been "translated" into a branch, 452 // that has been "translated" into a branch,
379 // thus it needs to be loaded explicitly again 453 // thus it needs to be loaded explicitly again
380 Label loaded; 454 Label loaded;
381 __ b(&loaded); // don't lose current TOS 455 __ b(&loaded); // don't lose current TOS
382 bool both = true_target.is_linked() && false_target.is_linked(); 456 bool both = true_target.is_linked() && false_target.is_linked();
383 // reincarnate "true", if necessary 457 // reincarnate "true", if necessary
384 if (true_target.is_linked()) { 458 if (true_target.is_linked()) {
385 __ bind(&true_target); 459 __ bind(&true_target);
386 __ mov(r0, Operand(Factory::true_value())); 460 __ mov(r0, Operand(Factory::true_value()));
387 __ push(r0); 461 frame_->Push(r0);
388 } 462 }
389 // if both "true" and "false" need to be reincarnated, 463 // if both "true" and "false" need to be reincarnated,
390 // jump across code for "false" 464 // jump across code for "false"
391 if (both) 465 if (both)
392 __ b(&loaded); 466 __ b(&loaded);
393 // reincarnate "false", if necessary 467 // reincarnate "false", if necessary
394 if (false_target.is_linked()) { 468 if (false_target.is_linked()) {
395 __ bind(&false_target); 469 __ bind(&false_target);
396 __ mov(r0, Operand(Factory::false_value())); 470 __ mov(r0, Operand(Factory::false_value()));
397 __ push(r0); 471 frame_->Push(r0);
398 } 472 }
399 // everything is loaded at this point 473 // everything is loaded at this point
400 __ bind(&loaded); 474 __ bind(&loaded);
401 } 475 }
402 ASSERT(!has_cc()); 476 ASSERT(!has_cc());
403 } 477 }
404 478
405 479
406 void CodeGenerator::LoadGlobal() { 480 void CodeGenerator::LoadGlobal() {
407 __ ldr(r0, GlobalObject()); 481 __ ldr(r0, GlobalObject());
408 __ push(r0); 482 frame_->Push(r0);
409 } 483 }
410 484
411 485
412 void CodeGenerator::LoadGlobalReceiver(Register s) { 486 void CodeGenerator::LoadGlobalReceiver(Register scratch) {
413 __ ldr(s, ContextOperand(cp, Context::GLOBAL_INDEX)); 487 __ ldr(scratch, ContextOperand(cp, Context::GLOBAL_INDEX));
414 __ ldr(s, FieldMemOperand(s, GlobalObject::kGlobalReceiverOffset)); 488 __ ldr(scratch,
415 __ push(s); 489 FieldMemOperand(scratch, GlobalObject::kGlobalReceiverOffset));
490 frame_->Push(scratch);
416 } 491 }
417 492
418 493
419 // TODO(1241834): Get rid of this function in favor of just using Load, now 494 // TODO(1241834): Get rid of this function in favor of just using Load, now
420 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global 495 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global
421 // variables w/o reference errors elsewhere. 496 // variables w/o reference errors elsewhere.
422 void CodeGenerator::LoadTypeofExpression(Expression* x) { 497 void CodeGenerator::LoadTypeofExpression(Expression* x) {
423 Variable* variable = x->AsVariableProxy()->AsVariable(); 498 Variable* variable = x->AsVariableProxy()->AsVariable();
424 if (variable != NULL && !variable->is_this() && variable->is_global()) { 499 if (variable != NULL && !variable->is_this() && variable->is_global()) {
425 // NOTE: This is somewhat nasty. We force the compiler to load 500 // NOTE: This is somewhat nasty. We force the compiler to load
(...skipping 17 matching lines...) Expand all
443 } 518 }
444 519
445 520
446 Reference::~Reference() { 521 Reference::~Reference() {
447 cgen_->UnloadReference(this); 522 cgen_->UnloadReference(this);
448 } 523 }
449 524
450 525
451 void CodeGenerator::LoadReference(Reference* ref) { 526 void CodeGenerator::LoadReference(Reference* ref) {
452 Comment cmnt(masm_, "[ LoadReference"); 527 Comment cmnt(masm_, "[ LoadReference");
453
454 Expression* e = ref->expression(); 528 Expression* e = ref->expression();
455 Property* property = e->AsProperty(); 529 Property* property = e->AsProperty();
456 Variable* var = e->AsVariableProxy()->AsVariable(); 530 Variable* var = e->AsVariableProxy()->AsVariable();
457 531
458 if (property != NULL) { 532 if (property != NULL) {
459 // The expression is either a property or a variable proxy that rewrites 533 // The expression is either a property or a variable proxy that rewrites
460 // to a property. 534 // to a property.
461 Load(property->obj()); 535 Load(property->obj());
462 // We use a named reference if the key is a literal symbol, unless it is 536 // We use a named reference if the key is a literal symbol, unless it is
463 // a string that can be legally parsed as an integer. This is because 537 // a string that can be legally parsed as an integer. This is because
(...skipping 21 matching lines...) Expand all
485 } 559 }
486 } else { 560 } else {
487 // Anything else is a runtime error. 561 // Anything else is a runtime error.
488 Load(e); 562 Load(e);
489 __ CallRuntime(Runtime::kThrowReferenceError, 1); 563 __ CallRuntime(Runtime::kThrowReferenceError, 1);
490 } 564 }
491 } 565 }
492 566
493 567
494 void CodeGenerator::UnloadReference(Reference* ref) { 568 void CodeGenerator::UnloadReference(Reference* ref) {
569 // Pop a reference from the stack while preserving TOS.
495 Comment cmnt(masm_, "[ UnloadReference"); 570 Comment cmnt(masm_, "[ UnloadReference");
496
497 int size = ref->size(); 571 int size = ref->size();
498 if (size <= 0) { 572 if (size > 0) {
499 // Do nothing. No popping is necessary. 573 frame_->Pop(r0);
500 } else { 574 frame_->Drop(size);
501 __ pop(r0); 575 frame_->Push(r0);
502 __ add(sp, sp, Operand(size * kPointerSize));
503 __ push(r0);
504 } 576 }
505 } 577 }
506 578
507 579
508 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given 580 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given
509 // register to a boolean in the condition code register. The code 581 // register to a boolean in the condition code register. The code
510 // may jump to 'false_target' in case the register converts to 'false'. 582 // may jump to 'false_target' in case the register converts to 'false'.
511 void CodeGenerator::ToBoolean(Label* true_target, 583 void CodeGenerator::ToBoolean(Label* true_target,
512 Label* false_target) { 584 Label* false_target) {
513 // Note: The generated code snippet does not change stack variables. 585 // Note: The generated code snippet does not change stack variables.
514 // Only the condition code should be set. 586 // Only the condition code should be set.
515 __ pop(r0); 587 frame_->Pop(r0);
516 588
517 // Fast case checks 589 // Fast case checks
518 590
519 // Check if the value is 'false'. 591 // Check if the value is 'false'.
520 __ cmp(r0, Operand(Factory::false_value())); 592 __ cmp(r0, Operand(Factory::false_value()));
521 __ b(eq, false_target); 593 __ b(eq, false_target);
522 594
523 // Check if the value is 'true'. 595 // Check if the value is 'true'.
524 __ cmp(r0, Operand(Factory::true_value())); 596 __ cmp(r0, Operand(Factory::true_value()));
525 __ b(eq, true_target); 597 __ b(eq, true_target);
526 598
527 // Check if the value is 'undefined'. 599 // Check if the value is 'undefined'.
528 __ cmp(r0, Operand(Factory::undefined_value())); 600 __ cmp(r0, Operand(Factory::undefined_value()));
529 __ b(eq, false_target); 601 __ b(eq, false_target);
530 602
531 // Check if the value is a smi. 603 // Check if the value is a smi.
532 __ cmp(r0, Operand(Smi::FromInt(0))); 604 __ cmp(r0, Operand(Smi::FromInt(0)));
533 __ b(eq, false_target); 605 __ b(eq, false_target);
534 __ tst(r0, Operand(kSmiTagMask)); 606 __ tst(r0, Operand(kSmiTagMask));
535 __ b(eq, true_target); 607 __ b(eq, true_target);
536 608
537 // Slow case: call the runtime. 609 // Slow case: call the runtime.
538 __ push(r0); 610 frame_->Push(r0);
539 __ CallRuntime(Runtime::kToBool, 1); 611 __ CallRuntime(Runtime::kToBool, 1);
540 612 // Convert the result (r0) to a condition code.
541 // Convert result (r0) to condition code
542 __ cmp(r0, Operand(Factory::false_value())); 613 __ cmp(r0, Operand(Factory::false_value()));
543 614
544 cc_reg_ = ne; 615 cc_reg_ = ne;
545 } 616 }
546 617
547 618
548 class GetPropertyStub : public CodeStub { 619 class GetPropertyStub : public CodeStub {
549 public: 620 public:
550 GetPropertyStub() { } 621 GetPropertyStub() { }
551 622
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 switch (op) { 703 switch (op) {
633 case Token::ADD: // fall through. 704 case Token::ADD: // fall through.
634 case Token::SUB: // fall through. 705 case Token::SUB: // fall through.
635 case Token::MUL: 706 case Token::MUL:
636 case Token::BIT_OR: 707 case Token::BIT_OR:
637 case Token::BIT_AND: 708 case Token::BIT_AND:
638 case Token::BIT_XOR: 709 case Token::BIT_XOR:
639 case Token::SHL: 710 case Token::SHL:
640 case Token::SHR: 711 case Token::SHR:
641 case Token::SAR: { 712 case Token::SAR: {
642 __ pop(r0); // r0 : y 713 frame_->Pop(r0); // r0 : y
643 __ pop(r1); // r1 : x 714 frame_->Pop(r1); // r1 : x
644 GenericBinaryOpStub stub(op); 715 GenericBinaryOpStub stub(op);
645 __ CallStub(&stub); 716 __ CallStub(&stub);
646 break; 717 break;
647 } 718 }
648 719
649 case Token::DIV: { 720 case Token::DIV: {
650 __ mov(r0, Operand(1)); 721 __ mov(r0, Operand(1));
651 __ InvokeBuiltin(Builtins::DIV, CALL_JS); 722 __ InvokeBuiltin(Builtins::DIV, CALL_JS);
652 break; 723 break;
653 } 724 }
654 725
655 case Token::MOD: { 726 case Token::MOD: {
656 __ mov(r0, Operand(1)); 727 __ mov(r0, Operand(1));
657 __ InvokeBuiltin(Builtins::MOD, CALL_JS); 728 __ InvokeBuiltin(Builtins::MOD, CALL_JS);
658 break; 729 break;
659 } 730 }
660 731
661 case Token::COMMA: 732 case Token::COMMA:
662 __ pop(r0); 733 frame_->Pop(r0);
663 // simply discard left value 734 // simply discard left value
664 __ pop(); 735 frame_->Pop();
665 break; 736 break;
666 737
667 default: 738 default:
668 // Other cases should have been handled before this point. 739 // Other cases should have been handled before this point.
669 UNREACHABLE(); 740 UNREACHABLE();
670 break; 741 break;
671 } 742 }
672 } 743 }
673 744
674 745
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
742 } 813 }
743 814
744 private: 815 private:
745 Token::Value op_; 816 Token::Value op_;
746 int value_; 817 int value_;
747 bool reversed_; 818 bool reversed_;
748 }; 819 };
749 820
750 821
751 void CodeGenerator::SmiOperation(Token::Value op, 822 void CodeGenerator::SmiOperation(Token::Value op,
752 Handle<Object> value, 823 Handle<Object> value,
753 bool reversed) { 824 bool reversed) {
754 // NOTE: This is an attempt to inline (a bit) more of the code for 825 // NOTE: This is an attempt to inline (a bit) more of the code for
755 // some possible smi operations (like + and -) when (at least) one 826 // some possible smi operations (like + and -) when (at least) one
756 // of the operands is a literal smi. With this optimization, the 827 // of the operands is a literal smi. With this optimization, the
757 // performance of the system is increased by ~15%, and the generated 828 // performance of the system is increased by ~15%, and the generated
758 // code size is increased by ~1% (measured on a combination of 829 // code size is increased by ~1% (measured on a combination of
759 // different benchmarks). 830 // different benchmarks).
760 831
761 // sp[0] : operand 832 // sp[0] : operand
762 833
763 int int_value = Smi::cast(*value)->value(); 834 int int_value = Smi::cast(*value)->value();
764 835
765 Label exit; 836 Label exit;
766 __ pop(r0); 837 frame_->Pop(r0);
767 838
768 switch (op) { 839 switch (op) {
769 case Token::ADD: { 840 case Token::ADD: {
770 DeferredCode* deferred = 841 DeferredCode* deferred =
771 new DeferredInlinedSmiOperation(this, op, int_value, reversed); 842 new DeferredInlinedSmiOperation(this, op, int_value, reversed);
772 843
773 __ add(r0, r0, Operand(value), SetCC); 844 __ add(r0, r0, Operand(value), SetCC);
774 __ b(vs, deferred->enter()); 845 __ b(vs, deferred->enter());
775 __ tst(r0, Operand(kSmiTagMask)); 846 __ tst(r0, Operand(kSmiTagMask));
776 __ b(ne, deferred->enter()); 847 __ b(ne, deferred->enter());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
809 } 880 }
810 __ bind(deferred->exit()); 881 __ bind(deferred->exit());
811 break; 882 break;
812 } 883 }
813 884
814 case Token::SHL: 885 case Token::SHL:
815 case Token::SHR: 886 case Token::SHR:
816 case Token::SAR: { 887 case Token::SAR: {
817 if (reversed) { 888 if (reversed) {
818 __ mov(ip, Operand(value)); 889 __ mov(ip, Operand(value));
819 __ push(ip); 890 frame_->Push(ip);
820 __ push(r0); 891 frame_->Push(r0);
821 GenericBinaryOperation(op); 892 GenericBinaryOperation(op);
822 893
823 } else { 894 } else {
824 int shift_value = int_value & 0x1f; // least significant 5 bits 895 int shift_value = int_value & 0x1f; // least significant 5 bits
825 DeferredCode* deferred = 896 DeferredCode* deferred =
826 new DeferredInlinedSmiOperation(this, op, shift_value, false); 897 new DeferredInlinedSmiOperation(this, op, shift_value, false);
827 __ tst(r0, Operand(kSmiTagMask)); 898 __ tst(r0, Operand(kSmiTagMask));
828 __ b(ne, deferred->enter()); 899 __ b(ne, deferred->enter());
829 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); // remove tags 900 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); // remove tags
830 switch (op) { 901 switch (op) {
(...skipping 29 matching lines...) Expand all
860 default: UNREACHABLE(); 931 default: UNREACHABLE();
861 } 932 }
862 __ mov(r0, Operand(r2, LSL, kSmiTagSize)); 933 __ mov(r0, Operand(r2, LSL, kSmiTagSize));
863 __ bind(deferred->exit()); 934 __ bind(deferred->exit());
864 } 935 }
865 break; 936 break;
866 } 937 }
867 938
868 default: 939 default:
869 if (!reversed) { 940 if (!reversed) {
870 __ push(r0); 941 frame_->Push(r0);
871 __ mov(r0, Operand(value)); 942 __ mov(r0, Operand(value));
872 __ push(r0); 943 frame_->Push(r0);
873 } else { 944 } else {
874 __ mov(ip, Operand(value)); 945 __ mov(ip, Operand(value));
875 __ push(ip); 946 frame_->Push(ip);
876 __ push(r0); 947 frame_->Push(r0);
877 } 948 }
878 GenericBinaryOperation(op); 949 GenericBinaryOperation(op);
879 break; 950 break;
880 } 951 }
881 952
882 __ bind(&exit); 953 __ bind(&exit);
883 } 954 }
884 955
885 956
886 void CodeGenerator::Comparison(Condition cc, bool strict) { 957 void CodeGenerator::Comparison(Condition cc, bool strict) {
887 // sp[0] : y 958 // sp[0] : y
888 // sp[1] : x 959 // sp[1] : x
889 // result : cc register 960 // result : cc register
890 961
891 // Strict only makes sense for equality comparisons. 962 // Strict only makes sense for equality comparisons.
892 ASSERT(!strict || cc == eq); 963 ASSERT(!strict || cc == eq);
893 964
894 Label exit, smi; 965 Label exit, smi;
895 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. 966 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
896 if (cc == gt || cc == le) { 967 if (cc == gt || cc == le) {
897 cc = ReverseCondition(cc); 968 cc = ReverseCondition(cc);
898 __ pop(r1); 969 frame_->Pop(r1);
899 __ pop(r0); 970 frame_->Pop(r0);
900 } else { 971 } else {
901 __ pop(r0); 972 frame_->Pop(r0);
902 __ pop(r1); 973 frame_->Pop(r1);
903 } 974 }
904 __ orr(r2, r0, Operand(r1)); 975 __ orr(r2, r0, Operand(r1));
905 __ tst(r2, Operand(kSmiTagMask)); 976 __ tst(r2, Operand(kSmiTagMask));
906 __ b(eq, &smi); 977 __ b(eq, &smi);
907 978
908 // Perform non-smi comparison by runtime call. 979 // Perform non-smi comparison by runtime call.
909 __ push(r1); 980 frame_->Push(r1);
910 981
911 // Figure out which native to call and setup the arguments. 982 // Figure out which native to call and setup the arguments.
912 Builtins::JavaScript native; 983 Builtins::JavaScript native;
913 int argc; 984 int argc;
914 if (cc == eq) { 985 if (cc == eq) {
915 native = strict ? Builtins::STRICT_EQUALS : Builtins::EQUALS; 986 native = strict ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
916 argc = 1; 987 argc = 1;
917 } else { 988 } else {
918 native = Builtins::COMPARE; 989 native = Builtins::COMPARE;
919 int ncr; // NaN compare result 990 int ncr; // NaN compare result
920 if (cc == lt || cc == le) { 991 if (cc == lt || cc == le) {
921 ncr = GREATER; 992 ncr = GREATER;
922 } else { 993 } else {
923 ASSERT(cc == gt || cc == ge); // remaining cases 994 ASSERT(cc == gt || cc == ge); // remaining cases
924 ncr = LESS; 995 ncr = LESS;
925 } 996 }
926 __ push(r0); 997 frame_->Push(r0);
927 __ mov(r0, Operand(Smi::FromInt(ncr))); 998 __ mov(r0, Operand(Smi::FromInt(ncr)));
928 argc = 2; 999 argc = 2;
929 } 1000 }
930 1001
931 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 1002 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
932 // tagged as a small integer. 1003 // tagged as a small integer.
933 __ push(r0); 1004 frame_->Push(r0);
934 __ mov(r0, Operand(argc)); 1005 __ mov(r0, Operand(argc));
935 __ InvokeBuiltin(native, CALL_JS); 1006 __ InvokeBuiltin(native, CALL_JS);
936 __ cmp(r0, Operand(0)); 1007 __ cmp(r0, Operand(0));
937 __ b(&exit); 1008 __ b(&exit);
938 1009
939 // test smi equality by pointer comparison. 1010 // test smi equality by pointer comparison.
940 __ bind(&smi); 1011 __ bind(&smi);
941 __ cmp(r1, Operand(r0)); 1012 __ cmp(r1, Operand(r0));
942 1013
943 __ bind(&exit); 1014 __ bind(&exit);
(...skipping 28 matching lines...) Expand all
972 } 1043 }
973 1044
974 // Record the position for debugging purposes. 1045 // Record the position for debugging purposes.
975 __ RecordPosition(position); 1046 __ RecordPosition(position);
976 1047
977 // Use the shared code stub to call the function. 1048 // Use the shared code stub to call the function.
978 CallFunctionStub call_function(args->length()); 1049 CallFunctionStub call_function(args->length());
979 __ CallStub(&call_function); 1050 __ CallStub(&call_function);
980 1051
981 // Restore context and pop function from the stack. 1052 // Restore context and pop function from the stack.
982 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1053 __ ldr(cp, frame_->Context());
983 __ pop(); // discard the TOS 1054 frame_->Pop(); // discard the TOS
984 } 1055 }
985 1056
986 1057
987 void CodeGenerator::Branch(bool if_true, Label* L) { 1058 void CodeGenerator::Branch(bool if_true, Label* L) {
988 ASSERT(has_cc()); 1059 ASSERT(has_cc());
989 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); 1060 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_);
990 __ b(cc, L); 1061 __ b(cc, L);
991 cc_reg_ = al; 1062 cc_reg_ = al;
992 } 1063 }
993 1064
(...skipping 11 matching lines...) Expand all
1005 Comment cmnt(masm_, "[ Block"); 1076 Comment cmnt(masm_, "[ Block");
1006 if (FLAG_debug_info) RecordStatementPosition(node); 1077 if (FLAG_debug_info) RecordStatementPosition(node);
1007 node->set_break_stack_height(break_stack_height_); 1078 node->set_break_stack_height(break_stack_height_);
1008 VisitStatements(node->statements()); 1079 VisitStatements(node->statements());
1009 __ bind(node->break_target()); 1080 __ bind(node->break_target());
1010 } 1081 }
1011 1082
1012 1083
1013 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1084 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
1014 __ mov(r0, Operand(pairs)); 1085 __ mov(r0, Operand(pairs));
1015 __ push(r0); 1086 frame_->Push(r0);
1016 __ push(cp); 1087 frame_->Push(cp);
1017 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); 1088 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
1018 __ push(r0); 1089 frame_->Push(r0);
1019 __ CallRuntime(Runtime::kDeclareGlobals, 3); 1090 __ CallRuntime(Runtime::kDeclareGlobals, 3);
1020 // The result is discarded. 1091 // The result is discarded.
1021 } 1092 }
1022 1093
1023 1094
1024 void CodeGenerator::VisitDeclaration(Declaration* node) { 1095 void CodeGenerator::VisitDeclaration(Declaration* node) {
1025 Comment cmnt(masm_, "[ Declaration"); 1096 Comment cmnt(masm_, "[ Declaration");
1026 Variable* var = node->proxy()->var(); 1097 Variable* var = node->proxy()->var();
1027 ASSERT(var != NULL); // must have been resolved 1098 ASSERT(var != NULL); // must have been resolved
1028 Slot* slot = var->slot(); 1099 Slot* slot = var->slot();
1029 1100
1030 // If it was not possible to allocate the variable at compile time, 1101 // If it was not possible to allocate the variable at compile time,
1031 // we need to "declare" it at runtime to make sure it actually 1102 // we need to "declare" it at runtime to make sure it actually
1032 // exists in the local context. 1103 // exists in the local context.
1033 if (slot != NULL && slot->type() == Slot::LOOKUP) { 1104 if (slot != NULL && slot->type() == Slot::LOOKUP) {
1034 // Variables with a "LOOKUP" slot were introduced as non-locals 1105 // Variables with a "LOOKUP" slot were introduced as non-locals
1035 // during variable resolution and must have mode DYNAMIC. 1106 // during variable resolution and must have mode DYNAMIC.
1036 ASSERT(var->mode() == Variable::DYNAMIC); 1107 ASSERT(var->mode() == Variable::DYNAMIC);
1037 // For now, just do a runtime call. 1108 // For now, just do a runtime call.
1038 __ push(cp); 1109 frame_->Push(cp);
1039 __ mov(r0, Operand(var->name())); 1110 __ mov(r0, Operand(var->name()));
1040 __ push(r0); 1111 frame_->Push(r0);
1041 // Declaration nodes are always declared in only two modes. 1112 // Declaration nodes are always declared in only two modes.
1042 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST); 1113 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST);
1043 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY; 1114 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY;
1044 __ mov(r0, Operand(Smi::FromInt(attr))); 1115 __ mov(r0, Operand(Smi::FromInt(attr)));
1045 __ push(r0); 1116 frame_->Push(r0);
1046 // Push initial value, if any. 1117 // Push initial value, if any.
1047 // Note: For variables we must not push an initial value (such as 1118 // Note: For variables we must not push an initial value (such as
1048 // 'undefined') because we may have a (legal) redeclaration and we 1119 // 'undefined') because we may have a (legal) redeclaration and we
1049 // must not destroy the current value. 1120 // must not destroy the current value.
1050 if (node->mode() == Variable::CONST) { 1121 if (node->mode() == Variable::CONST) {
1051 __ mov(r0, Operand(Factory::the_hole_value())); 1122 __ mov(r0, Operand(Factory::the_hole_value()));
1052 __ push(r0); 1123 frame_->Push(r0);
1053 } else if (node->fun() != NULL) { 1124 } else if (node->fun() != NULL) {
1054 Load(node->fun()); 1125 Load(node->fun());
1055 } else { 1126 } else {
1056 __ mov(r0, Operand(0)); // no initial value! 1127 __ mov(r0, Operand(0)); // no initial value!
1057 __ push(r0); 1128 frame_->Push(r0);
1058 } 1129 }
1059 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 1130 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
1060 // Ignore the return value (declarations are statements). 1131 // Ignore the return value (declarations are statements).
1061 return; 1132 return;
1062 } 1133 }
1063 1134
1064 ASSERT(!var->is_global()); 1135 ASSERT(!var->is_global());
1065 1136
1066 // If we have a function or a constant, we need to initialize the variable. 1137 // If we have a function or a constant, we need to initialize the variable.
1067 Expression* val = NULL; 1138 Expression* val = NULL;
1068 if (node->mode() == Variable::CONST) { 1139 if (node->mode() == Variable::CONST) {
1069 val = new Literal(Factory::the_hole_value()); 1140 val = new Literal(Factory::the_hole_value());
1070 } else { 1141 } else {
1071 val = node->fun(); // NULL if we don't have a function 1142 val = node->fun(); // NULL if we don't have a function
1072 } 1143 }
1073 1144
1074 if (val != NULL) { 1145 if (val != NULL) {
1075 // Set initial value. 1146 // Set initial value.
1076 Reference target(this, node->proxy()); 1147 Reference target(this, node->proxy());
1077 ASSERT(target.is_slot()); 1148 ASSERT(target.is_slot());
1078 Load(val); 1149 Load(val);
1079 target.SetValue(NOT_CONST_INIT); 1150 target.SetValue(NOT_CONST_INIT);
1080 // Get rid of the assigned value (declarations are statements). It's 1151 // Get rid of the assigned value (declarations are statements). It's
1081 // safe to pop the value lying on top of the reference before unloading 1152 // safe to pop the value lying on top of the reference before unloading
1082 // the reference itself (which preserves the top of stack) because we 1153 // the reference itself (which preserves the top of stack) because we
1083 // know it is a zero-sized reference. 1154 // know it is a zero-sized reference.
1084 __ pop(); 1155 frame_->Pop();
1085 } 1156 }
1086 } 1157 }
1087 1158
1088 1159
1089 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { 1160 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
1090 Comment cmnt(masm_, "[ ExpressionStatement"); 1161 Comment cmnt(masm_, "[ ExpressionStatement");
1091 if (FLAG_debug_info) RecordStatementPosition(node); 1162 if (FLAG_debug_info) RecordStatementPosition(node);
1092 Expression* expression = node->expression(); 1163 Expression* expression = node->expression();
1093 expression->MarkAsStatement(); 1164 expression->MarkAsStatement();
1094 Load(expression); 1165 Load(expression);
1095 __ pop(); 1166 frame_->Pop();
1096 } 1167 }
1097 1168
1098 1169
1099 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { 1170 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
1100 Comment cmnt(masm_, "// EmptyStatement"); 1171 Comment cmnt(masm_, "// EmptyStatement");
1101 // nothing to do 1172 // nothing to do
1102 } 1173 }
1103 1174
1104 1175
1105 void CodeGenerator::VisitIfStatement(IfStatement* node) { 1176 void CodeGenerator::VisitIfStatement(IfStatement* node) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1150 Visit(node->else_statement()); 1221 Visit(node->else_statement());
1151 1222
1152 } else { 1223 } else {
1153 Comment cmnt(masm_, "[ If"); 1224 Comment cmnt(masm_, "[ If");
1154 ASSERT(!has_then_stm && !has_else_stm); 1225 ASSERT(!has_then_stm && !has_else_stm);
1155 // if (cond) 1226 // if (cond)
1156 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false); 1227 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false);
1157 if (has_cc()) { 1228 if (has_cc()) {
1158 cc_reg_ = al; 1229 cc_reg_ = al;
1159 } else { 1230 } else {
1160 __ pop(r0); // __ Pop(no_reg) 1231 frame_->Pop();
1161 } 1232 }
1162 } 1233 }
1163 1234
1164 // end 1235 // end
1165 __ bind(&exit); 1236 __ bind(&exit);
1166 } 1237 }
1167 1238
1168 1239
1169 void CodeGenerator::CleanStack(int num_bytes) { 1240 void CodeGenerator::CleanStack(int num_bytes) {
1170 ASSERT(num_bytes >= 0); 1241 ASSERT(num_bytes % kPointerSize == 0);
1171 if (num_bytes > 0) { 1242 frame_->Drop(num_bytes / kPointerSize);
1172 __ add(sp, sp, Operand(num_bytes));
1173 }
1174 } 1243 }
1175 1244
1176 1245
1177 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { 1246 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) {
1178 Comment cmnt(masm_, "[ ContinueStatement"); 1247 Comment cmnt(masm_, "[ ContinueStatement");
1179 if (FLAG_debug_info) RecordStatementPosition(node); 1248 if (FLAG_debug_info) RecordStatementPosition(node);
1180 CleanStack(break_stack_height_ - node->target()->break_stack_height()); 1249 CleanStack(break_stack_height_ - node->target()->break_stack_height());
1181 __ b(node->target()->continue_target()); 1250 __ b(node->target()->continue_target());
1182 } 1251 }
1183 1252
1184 1253
1185 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { 1254 void CodeGenerator::VisitBreakStatement(BreakStatement* node) {
1186 Comment cmnt(masm_, "[ BreakStatement"); 1255 Comment cmnt(masm_, "[ BreakStatement");
1187 if (FLAG_debug_info) RecordStatementPosition(node); 1256 if (FLAG_debug_info) RecordStatementPosition(node);
1188 CleanStack(break_stack_height_ - node->target()->break_stack_height()); 1257 CleanStack(break_stack_height_ - node->target()->break_stack_height());
1189 __ b(node->target()->break_target()); 1258 __ b(node->target()->break_target());
1190 } 1259 }
1191 1260
1192 1261
1193 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { 1262 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
1194 Comment cmnt(masm_, "[ ReturnStatement"); 1263 Comment cmnt(masm_, "[ ReturnStatement");
1195 if (FLAG_debug_info) RecordStatementPosition(node); 1264 if (FLAG_debug_info) RecordStatementPosition(node);
1196 Load(node->expression()); 1265 Load(node->expression());
1197 // Move the function result into r0. 1266 // Move the function result into r0.
1198 __ pop(r0); 1267 frame_->Pop(r0);
1199 1268
1200 __ b(&function_return_); 1269 __ b(&function_return_);
1201 } 1270 }
1202 1271
1203 1272
1204 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { 1273 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
1205 Comment cmnt(masm_, "[ WithEnterStatement"); 1274 Comment cmnt(masm_, "[ WithEnterStatement");
1206 if (FLAG_debug_info) RecordStatementPosition(node); 1275 if (FLAG_debug_info) RecordStatementPosition(node);
1207 Load(node->expression()); 1276 Load(node->expression());
1208 __ CallRuntime(Runtime::kPushContext, 1); 1277 __ CallRuntime(Runtime::kPushContext, 1);
1209 if (kDebug) { 1278 if (kDebug) {
1210 Label verified_true; 1279 Label verified_true;
1211 __ cmp(r0, Operand(cp)); 1280 __ cmp(r0, Operand(cp));
1212 __ b(eq, &verified_true); 1281 __ b(eq, &verified_true);
1213 __ stop("PushContext: r0 is expected to be the same as cp"); 1282 __ stop("PushContext: r0 is expected to be the same as cp");
1214 __ bind(&verified_true); 1283 __ bind(&verified_true);
1215 } 1284 }
1216 // Update context local. 1285 // Update context local.
1217 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1286 __ str(cp, frame_->Context());
1218 } 1287 }
1219 1288
1220 1289
1221 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { 1290 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) {
1222 Comment cmnt(masm_, "[ WithExitStatement"); 1291 Comment cmnt(masm_, "[ WithExitStatement");
1223 // Pop context. 1292 // Pop context.
1224 __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX)); 1293 __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX));
1225 // Update context local. 1294 // Update context local.
1226 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1295 __ str(cp, frame_->Context());
1227 } 1296 }
1228 1297
1229 1298
1230 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { 1299 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() {
1231 return kFastSwitchMaxOverheadFactor; 1300 return kFastSwitchMaxOverheadFactor;
1232 } 1301 }
1233 1302
1234 int CodeGenerator::FastCaseSwitchMinCaseCount() { 1303 int CodeGenerator::FastCaseSwitchMinCaseCount() {
1235 return kFastSwitchMinCaseCount; 1304 return kFastSwitchMinCaseCount;
1236 } 1305 }
1237 1306
1238 1307
1239 void CodeGenerator::GenerateFastCaseSwitchJumpTable( 1308 void CodeGenerator::GenerateFastCaseSwitchJumpTable(
1240 SwitchStatement* node, 1309 SwitchStatement* node,
1241 int min_index, 1310 int min_index,
1242 int range, 1311 int range,
1243 Label* fail_label, 1312 Label* fail_label,
1244 Vector<Label*> case_targets, 1313 Vector<Label*> case_targets,
1245 Vector<Label> case_labels) { 1314 Vector<Label> case_labels) {
1246 1315
1247 ASSERT(kSmiTag == 0 && kSmiTagSize <= 2); 1316 ASSERT(kSmiTag == 0 && kSmiTagSize <= 2);
1248 1317
1249 __ pop(r0); 1318 frame_->Pop(r0);
1250 1319
1251 // Test for a Smi value in a HeapNumber. 1320 // Test for a Smi value in a HeapNumber.
1252 Label is_smi; 1321 Label is_smi;
1253 __ tst(r0, Operand(kSmiTagMask)); 1322 __ tst(r0, Operand(kSmiTagMask));
1254 __ b(eq, &is_smi); 1323 __ b(eq, &is_smi);
1255 __ ldr(r1, MemOperand(r0, HeapObject::kMapOffset - kHeapObjectTag)); 1324 __ ldr(r1, MemOperand(r0, HeapObject::kMapOffset - kHeapObjectTag));
1256 __ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag)); 1325 __ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag));
1257 __ cmp(r1, Operand(HEAP_NUMBER_TYPE)); 1326 __ cmp(r1, Operand(HEAP_NUMBER_TYPE));
1258 __ b(ne, fail_label); 1327 __ b(ne, fail_label);
1259 __ push(r0); 1328 frame_->Push(r0);
1260 __ CallRuntime(Runtime::kNumberToSmi, 1); 1329 __ CallRuntime(Runtime::kNumberToSmi, 1);
1261 __ bind(&is_smi); 1330 __ bind(&is_smi);
1262 1331
1263 if (min_index != 0) { 1332 if (min_index != 0) {
1264 // Small positive numbers can be immediate operands. 1333 // Small positive numbers can be immediate operands.
1265 if (min_index < 0) { 1334 if (min_index < 0) {
1266 // If min_index is Smi::kMinValue, -min_index is not a Smi. 1335 // If min_index is Smi::kMinValue, -min_index is not a Smi.
1267 if (Smi::IsValid(-min_index)) { 1336 if (Smi::IsValid(-min_index)) {
1268 __ add(r0, r0, Operand(Smi::FromInt(-min_index))); 1337 __ add(r0, r0, Operand(Smi::FromInt(-min_index)));
1269 } else { 1338 } else {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1317 // statements if it does not match any of the cases. 1386 // statements if it does not match any of the cases.
1318 __ b(&next); 1387 __ b(&next);
1319 1388
1320 // Bind the default case label, so we can branch to it when we 1389 // Bind the default case label, so we can branch to it when we
1321 // have compared against all other cases. 1390 // have compared against all other cases.
1322 ASSERT(default_case.is_unused()); // at most one default clause 1391 ASSERT(default_case.is_unused()); // at most one default clause
1323 __ bind(&default_case); 1392 __ bind(&default_case);
1324 } else { 1393 } else {
1325 __ bind(&next); 1394 __ bind(&next);
1326 next.Unuse(); 1395 next.Unuse();
1327 __ ldr(r0, MemOperand(sp, 0)); 1396 __ ldr(r0, frame_->Top());
1328 __ push(r0); // duplicate TOS 1397 frame_->Push(r0); // duplicate TOS
1329 Load(clause->label()); 1398 Load(clause->label());
1330 Comparison(eq, true); 1399 Comparison(eq, true);
1331 Branch(false, &next); 1400 Branch(false, &next);
1332 } 1401 }
1333 1402
1334 // Entering the case statement for the first time. Remove the switch value 1403 // Entering the case statement for the first time. Remove the switch value
1335 // from the stack. 1404 // from the stack.
1336 __ pop(r0); 1405 frame_->Pop();
1337 1406
1338 // Generate code for the body. 1407 // Generate code for the body.
1339 // This is also the target for the fall through from the previous case's 1408 // This is also the target for the fall through from the previous case's
1340 // statements which has to skip over the matching code and the popping of 1409 // statements which has to skip over the matching code and the popping of
1341 // the switch value. 1410 // the switch value.
1342 __ bind(&fall_through); 1411 __ bind(&fall_through);
1343 fall_through.Unuse(); 1412 fall_through.Unuse();
1344 VisitStatements(clause->statements()); 1413 VisitStatements(clause->statements());
1345 __ b(&fall_through); 1414 __ b(&fall_through);
1346 } 1415 }
1347 1416
1348 __ bind(&next); 1417 __ bind(&next);
1349 // Reached the end of the case statements without matching any of the cases. 1418 // Reached the end of the case statements without matching any of the cases.
1350 if (default_case.is_bound()) { 1419 if (default_case.is_bound()) {
1351 // A default case exists -> execute its statements. 1420 // A default case exists -> execute its statements.
1352 __ b(&default_case); 1421 __ b(&default_case);
1353 } else { 1422 } else {
1354 // Remove the switch value from the stack. 1423 // Remove the switch value from the stack.
1355 __ pop(r0); 1424 frame_->Pop();
1356 } 1425 }
1357 1426
1358 __ bind(&fall_through); 1427 __ bind(&fall_through);
1359 __ bind(node->break_target()); 1428 __ bind(node->break_target());
1360 } 1429 }
1361 1430
1362 1431
1363 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { 1432 void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
1364 Comment cmnt(masm_, "[ LoopStatement"); 1433 Comment cmnt(masm_, "[ LoopStatement");
1365 if (FLAG_debug_info) RecordStatementPosition(node); 1434 if (FLAG_debug_info) RecordStatementPosition(node);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1441 // can restore the stack. 1510 // can restore the stack.
1442 const int kForInStackSize = 5 * kPointerSize; 1511 const int kForInStackSize = 5 * kPointerSize;
1443 break_stack_height_ += kForInStackSize; 1512 break_stack_height_ += kForInStackSize;
1444 node->set_break_stack_height(break_stack_height_); 1513 node->set_break_stack_height(break_stack_height_);
1445 1514
1446 Label loop, next, entry, cleanup, exit, primitive, jsobject; 1515 Label loop, next, entry, cleanup, exit, primitive, jsobject;
1447 Label filter_key, end_del_check, fixed_array, non_string; 1516 Label filter_key, end_del_check, fixed_array, non_string;
1448 1517
1449 // Get the object to enumerate over (converted to JSObject). 1518 // Get the object to enumerate over (converted to JSObject).
1450 Load(node->enumerable()); 1519 Load(node->enumerable());
1451 __ pop(r0); 1520 frame_->Pop(r0);
1452 1521
1453 // Both SpiderMonkey and kjs ignore null and undefined in contrast 1522 // Both SpiderMonkey and kjs ignore null and undefined in contrast
1454 // to the specification. 12.6.4 mandates a call to ToObject. 1523 // to the specification. 12.6.4 mandates a call to ToObject.
1455 __ cmp(r0, Operand(Factory::undefined_value())); 1524 __ cmp(r0, Operand(Factory::undefined_value()));
1456 __ b(eq, &exit); 1525 __ b(eq, &exit);
1457 __ cmp(r0, Operand(Factory::null_value())); 1526 __ cmp(r0, Operand(Factory::null_value()));
1458 __ b(eq, &exit); 1527 __ b(eq, &exit);
1459 1528
1460 // Stack layout in body: 1529 // Stack layout in body:
1461 // [iteration counter (Smi)] 1530 // [iteration counter (Smi)]
1462 // [length of array] 1531 // [length of array]
1463 // [FixedArray] 1532 // [FixedArray]
1464 // [Map or 0] 1533 // [Map or 0]
1465 // [Object] 1534 // [Object]
1466 1535
1467 // Check if enumerable is already a JSObject 1536 // Check if enumerable is already a JSObject
1468 __ tst(r0, Operand(kSmiTagMask)); 1537 __ tst(r0, Operand(kSmiTagMask));
1469 __ b(eq, &primitive); 1538 __ b(eq, &primitive);
1470 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 1539 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
1471 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 1540 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
1472 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); 1541 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
1473 __ b(hs, &jsobject); 1542 __ b(hs, &jsobject);
1474 1543
1475 __ bind(&primitive); 1544 __ bind(&primitive);
1476 __ push(r0); 1545 frame_->Push(r0);
1477 __ mov(r0, Operand(0)); 1546 __ mov(r0, Operand(0));
1478 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); 1547 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
1479 1548
1480 1549
1481 __ bind(&jsobject); 1550 __ bind(&jsobject);
1482 1551
1483 // Get the set of properties (as a FixedArray or Map). 1552 // Get the set of properties (as a FixedArray or Map).
1484 __ push(r0); // duplicate the object being enumerated 1553 frame_->Push(r0); // duplicate the object being enumerated
1485 __ push(r0); 1554 frame_->Push(r0);
1486 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 1555 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1487 1556
1488 // If we got a Map, we can do a fast modification check. 1557 // If we got a Map, we can do a fast modification check.
1489 // Otherwise, we got a FixedArray, and we have to do a slow check. 1558 // Otherwise, we got a FixedArray, and we have to do a slow check.
1490 __ mov(r2, Operand(r0)); 1559 __ mov(r2, Operand(r0));
1491 __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset)); 1560 __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));
1492 __ cmp(r1, Operand(Factory::meta_map())); 1561 __ cmp(r1, Operand(Factory::meta_map()));
1493 __ b(ne, &fixed_array); 1562 __ b(ne, &fixed_array);
1494 1563
1495 // Get enum cache 1564 // Get enum cache
1496 __ mov(r1, Operand(r0)); 1565 __ mov(r1, Operand(r0));
1497 __ ldr(r1, FieldMemOperand(r1, Map::kInstanceDescriptorsOffset)); 1566 __ ldr(r1, FieldMemOperand(r1, Map::kInstanceDescriptorsOffset));
1498 __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset)); 1567 __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset));
1499 __ ldr(r2, 1568 __ ldr(r2,
1500 FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1569 FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));
1501 1570
1502 __ push(r0); // map 1571 frame_->Push(r0); // map
1503 __ push(r2); // enum cache bridge cache 1572 frame_->Push(r2); // enum cache bridge cache
1504 __ ldr(r0, FieldMemOperand(r2, FixedArray::kLengthOffset)); 1573 __ ldr(r0, FieldMemOperand(r2, FixedArray::kLengthOffset));
1505 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 1574 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
1506 __ push(r0); 1575 frame_->Push(r0);
1507 __ mov(r0, Operand(Smi::FromInt(0))); 1576 __ mov(r0, Operand(Smi::FromInt(0)));
1508 __ push(r0); 1577 frame_->Push(r0);
1509 __ b(&entry); 1578 __ b(&entry);
1510 1579
1511 1580
1512 __ bind(&fixed_array); 1581 __ bind(&fixed_array);
1513 1582
1514 __ mov(r1, Operand(Smi::FromInt(0))); 1583 __ mov(r1, Operand(Smi::FromInt(0)));
1515 __ push(r1); // insert 0 in place of Map 1584 frame_->Push(r1); // insert 0 in place of Map
1516 __ push(r0); 1585 frame_->Push(r0);
1517 1586
1518 // Push the length of the array and the initial index onto the stack. 1587 // Push the length of the array and the initial index onto the stack.
1519 __ ldr(r0, FieldMemOperand(r0, FixedArray::kLengthOffset)); 1588 __ ldr(r0, FieldMemOperand(r0, FixedArray::kLengthOffset));
1520 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 1589 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
1521 __ push(r0); 1590 frame_->Push(r0);
1522 __ mov(r0, Operand(Smi::FromInt(0))); // init index 1591 __ mov(r0, Operand(Smi::FromInt(0))); // init index
1523 __ push(r0); 1592 frame_->Push(r0);
1524 1593
1525 __ b(&entry); 1594 __ b(&entry);
1526 1595
1527 // Body. 1596 // Body.
1528 __ bind(&loop); 1597 __ bind(&loop);
1529 Visit(node->body()); 1598 Visit(node->body());
1530 1599
1531 // Next. 1600 // Next.
1532 __ bind(node->continue_target()); 1601 __ bind(node->continue_target());
1533 __ bind(&next); 1602 __ bind(&next);
1534 __ pop(r0); 1603 frame_->Pop(r0);
1535 __ add(r0, r0, Operand(Smi::FromInt(1))); 1604 __ add(r0, r0, Operand(Smi::FromInt(1)));
1536 __ push(r0); 1605 frame_->Push(r0);
1537 1606
1538 // Condition. 1607 // Condition.
1539 __ bind(&entry); 1608 __ bind(&entry);
1540 1609
1541 // sp[0] : index 1610 // sp[0] : index
1542 // sp[1] : array/enum cache length 1611 // sp[1] : array/enum cache length
1543 // sp[2] : array or enum cache 1612 // sp[2] : array or enum cache
1544 // sp[3] : 0 or map 1613 // sp[3] : 0 or map
1545 // sp[4] : enumerable 1614 // sp[4] : enumerable
1546 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); // load the current count 1615 __ ldr(r0, frame_->Element(0)); // load the current count
1547 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); // load the length 1616 __ ldr(r1, frame_->Element(1)); // load the length
1548 __ cmp(r0, Operand(r1)); // compare to the array length 1617 __ cmp(r0, Operand(r1)); // compare to the array length
1549 __ b(hs, &cleanup); 1618 __ b(hs, &cleanup);
1550 1619
1551 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); 1620 __ ldr(r0, frame_->Element(0));
1552 1621
1553 // Get the i'th entry of the array. 1622 // Get the i'th entry of the array.
1554 __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); 1623 __ ldr(r2, frame_->Element(2));
1555 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 1624 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1556 __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 1625 __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1557 1626
1558 // Get Map or 0. 1627 // Get Map or 0.
1559 __ ldr(r2, MemOperand(sp, 3 * kPointerSize)); 1628 __ ldr(r2, frame_->Element(3));
1560 // Check if this (still) matches the map of the enumerable. 1629 // Check if this (still) matches the map of the enumerable.
1561 // If not, we have to filter the key. 1630 // If not, we have to filter the key.
1562 __ ldr(r1, MemOperand(sp, 4 * kPointerSize)); 1631 __ ldr(r1, frame_->Element(4));
1563 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 1632 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
1564 __ cmp(r1, Operand(r2)); 1633 __ cmp(r1, Operand(r2));
1565 __ b(eq, &end_del_check); 1634 __ b(eq, &end_del_check);
1566 1635
1567 // Convert the entry to a string (or null if it isn't a property anymore). 1636 // Convert the entry to a string (or null if it isn't a property anymore).
1568 __ ldr(r0, MemOperand(sp, 4 * kPointerSize)); // push enumerable 1637 __ ldr(r0, frame_->Element(4)); // push enumerable
1569 __ push(r0); 1638 frame_->Push(r0);
1570 __ push(r3); // push entry 1639 frame_->Push(r3); // push entry
1571 __ mov(r0, Operand(1)); 1640 __ mov(r0, Operand(1));
1572 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS); 1641 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS);
1573 __ mov(r3, Operand(r0)); 1642 __ mov(r3, Operand(r0));
1574 1643
1575 // If the property has been removed while iterating, we just skip it. 1644 // If the property has been removed while iterating, we just skip it.
1576 __ cmp(r3, Operand(Factory::null_value())); 1645 __ cmp(r3, Operand(Factory::null_value()));
1577 __ b(eq, &next); 1646 __ b(eq, &next);
1578 1647
1579 1648
1580 __ bind(&end_del_check); 1649 __ bind(&end_del_check);
1581 1650
1582 // Store the entry in the 'each' expression and take another spin in the loop. 1651 // Store the entry in the 'each' expression and take another spin in the loop.
1583 // r3: i'th entry of the enum cache (or string there of) 1652 // r3: i'th entry of the enum cache (or string there of)
1584 __ push(r3); // push entry 1653 frame_->Push(r3); // push entry
1585 { Reference each(this, node->each()); 1654 { Reference each(this, node->each());
1586 if (!each.is_illegal()) { 1655 if (!each.is_illegal()) {
1587 if (each.size() > 0) { 1656 if (each.size() > 0) {
1588 __ ldr(r0, MemOperand(sp, kPointerSize * each.size())); 1657 __ ldr(r0, frame_->Element(each.size()));
1589 __ push(r0); 1658 frame_->Push(r0);
1590 } 1659 }
1591 // If the reference was to a slot we rely on the convenient property 1660 // If the reference was to a slot we rely on the convenient property
1592 // that it doesn't matter whether a value (eg, r3 pushed above) is 1661 // that it doesn't matter whether a value (eg, r3 pushed above) is
1593 // right on top of or right underneath a zero-sized reference. 1662 // right on top of or right underneath a zero-sized reference.
1594 each.SetValue(NOT_CONST_INIT); 1663 each.SetValue(NOT_CONST_INIT);
1595 if (each.size() > 0) { 1664 if (each.size() > 0) {
1596 // It's safe to pop the value lying on top of the reference before 1665 // It's safe to pop the value lying on top of the reference before
1597 // unloading the reference itself (which preserves the top of stack, 1666 // unloading the reference itself (which preserves the top of stack,
1598 // ie, now the topmost value of the non-zero sized reference), since 1667 // ie, now the topmost value of the non-zero sized reference), since
1599 // we will discard the top of stack after unloading the reference 1668 // we will discard the top of stack after unloading the reference
1600 // anyway. 1669 // anyway.
1601 __ pop(r0); 1670 frame_->Pop(r0);
1602 } 1671 }
1603 } 1672 }
1604 } 1673 }
1605 // Discard the i'th entry pushed above or else the remainder of the 1674 // Discard the i'th entry pushed above or else the remainder of the
1606 // reference, whichever is currently on top of the stack. 1675 // reference, whichever is currently on top of the stack.
1607 __ pop(); 1676 frame_->Pop();
1608 CheckStack(); // TODO(1222600): ignore if body contains calls. 1677 CheckStack(); // TODO(1222600): ignore if body contains calls.
1609 __ jmp(&loop); 1678 __ jmp(&loop);
1610 1679
1611 // Cleanup. 1680 // Cleanup.
1612 __ bind(&cleanup); 1681 __ bind(&cleanup);
1613 __ bind(node->break_target()); 1682 __ bind(node->break_target());
1614 __ add(sp, sp, Operand(5 * kPointerSize)); 1683 frame_->Drop(5);
1615 1684
1616 // Exit. 1685 // Exit.
1617 __ bind(&exit); 1686 __ bind(&exit);
1618 1687
1619 break_stack_height_ -= kForInStackSize; 1688 break_stack_height_ -= kForInStackSize;
1620 } 1689 }
1621 1690
1622 1691
1623 void CodeGenerator::VisitTryCatch(TryCatch* node) { 1692 void CodeGenerator::VisitTryCatch(TryCatch* node) {
1624 Comment cmnt(masm_, "[ TryCatch"); 1693 Comment cmnt(masm_, "[ TryCatch");
1625 1694
1626 Label try_block, exit; 1695 Label try_block, exit;
1627 1696
1628 __ bl(&try_block); 1697 __ bl(&try_block);
1629
1630 // --- Catch block --- 1698 // --- Catch block ---
1699 frame_->Push(r0);
1631 1700
1632 // Store the caught exception in the catch variable. 1701 // Store the caught exception in the catch variable.
1633 __ push(r0);
1634 { Reference ref(this, node->catch_var()); 1702 { Reference ref(this, node->catch_var());
1635 ASSERT(ref.is_slot()); 1703 ASSERT(ref.is_slot());
1636 // Here we make use of the convenient property that it doesn't matter 1704 // Here we make use of the convenient property that it doesn't matter
1637 // whether a value is immediately on top of or underneath a zero-sized 1705 // whether a value is immediately on top of or underneath a zero-sized
1638 // reference. 1706 // reference.
1639 ref.SetValue(NOT_CONST_INIT); 1707 ref.SetValue(NOT_CONST_INIT);
1640 } 1708 }
1641 1709
1642 // Remove the exception from the stack. 1710 // Remove the exception from the stack.
1643 __ pop(); 1711 frame_->Pop();
1644 1712
1645 VisitStatements(node->catch_block()->statements()); 1713 VisitStatements(node->catch_block()->statements());
1646 __ b(&exit); 1714 __ b(&exit);
1647 1715
1648 1716
1649 // --- Try block --- 1717 // --- Try block ---
1650 __ bind(&try_block); 1718 __ bind(&try_block);
1651 1719
1652 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER); 1720 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER);
1653 1721
1654 // Shadow the labels for all escapes from the try block, including 1722 // Shadow the labels for all escapes from the try block, including
1655 // returns. During shadowing, the original label is hidden as the 1723 // returns. During shadowing, the original label is hidden as the
1656 // LabelShadow and operations on the original actually affect the 1724 // LabelShadow and operations on the original actually affect the
1657 // shadowing label. 1725 // shadowing label.
1658 // 1726 //
1659 // We should probably try to unify the escaping labels and the return 1727 // We should probably try to unify the escaping labels and the return
1660 // label. 1728 // label.
1661 int nof_escapes = node->escaping_labels()->length(); 1729 int nof_escapes = node->escaping_labels()->length();
1662 List<LabelShadow*> shadows(1 + nof_escapes); 1730 List<LabelShadow*> shadows(1 + nof_escapes);
1663 shadows.Add(new LabelShadow(&function_return_)); 1731 shadows.Add(new LabelShadow(&function_return_));
1664 for (int i = 0; i < nof_escapes; i++) { 1732 for (int i = 0; i < nof_escapes; i++) {
1665 shadows.Add(new LabelShadow(node->escaping_labels()->at(i))); 1733 shadows.Add(new LabelShadow(node->escaping_labels()->at(i)));
1666 } 1734 }
1667 1735
1668 // Generate code for the statements in the try block. 1736 // Generate code for the statements in the try block.
1669 VisitStatements(node->try_block()->statements()); 1737 VisitStatements(node->try_block()->statements());
1670 __ pop(r0); // Discard the result. 1738 frame_->Pop(); // Discard the result.
1671 1739
1672 // Stop the introduced shadowing and count the number of required unlinks. 1740 // Stop the introduced shadowing and count the number of required unlinks.
1673 // After shadowing stops, the original labels are unshadowed and the 1741 // After shadowing stops, the original labels are unshadowed and the
1674 // LabelShadows represent the formerly shadowing labels. 1742 // LabelShadows represent the formerly shadowing labels.
1675 int nof_unlinks = 0; 1743 int nof_unlinks = 0;
1676 for (int i = 0; i <= nof_escapes; i++) { 1744 for (int i = 0; i <= nof_escapes; i++) {
1677 shadows[i]->StopShadowing(); 1745 shadows[i]->StopShadowing();
1678 if (shadows[i]->is_linked()) nof_unlinks++; 1746 if (shadows[i]->is_linked()) nof_unlinks++;
1679 } 1747 }
1680 1748
1681 // Unlink from try chain. 1749 // Unlink from try chain.
1682 // TOS contains code slot 1750 // TOS contains code slot
1683 const int kNextOffset = StackHandlerConstants::kNextOffset + 1751 const int kNextIndex = (StackHandlerConstants::kNextOffset
1684 StackHandlerConstants::kAddressDisplacement; 1752 + StackHandlerConstants::kAddressDisplacement)
1685 __ ldr(r1, MemOperand(sp, kNextOffset)); // read next_sp 1753 / kPointerSize;
1754 __ ldr(r1, frame_->Element(kNextIndex)); // read next_sp
1686 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); 1755 __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
1687 __ str(r1, MemOperand(r3)); 1756 __ str(r1, MemOperand(r3));
1688 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code 1757 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
1689 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); 1758 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
1690 // Code slot popped. 1759 // Code slot popped.
1691 if (nof_unlinks > 0) __ b(&exit); 1760 if (nof_unlinks > 0) __ b(&exit);
1692 1761
1693 // Generate unlink code for the (formerly) shadowing labels that have been 1762 // Generate unlink code for the (formerly) shadowing labels that have been
1694 // jumped to. 1763 // jumped to.
1695 for (int i = 0; i <= nof_escapes; i++) { 1764 for (int i = 0; i <= nof_escapes; i++) {
1696 if (shadows[i]->is_linked()) { 1765 if (shadows[i]->is_linked()) {
1697 // Unlink from try chain; 1766 // Unlink from try chain;
1698 __ bind(shadows[i]); 1767 __ bind(shadows[i]);
1699 1768
1700 // Reload sp from the top handler, because some statements that we 1769 // Reload sp from the top handler, because some statements that we
1701 // break from (eg, for...in) may have left stuff on the stack. 1770 // break from (eg, for...in) may have left stuff on the stack.
1702 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); 1771 __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
1703 __ ldr(sp, MemOperand(r3)); 1772 __ ldr(sp, MemOperand(r3));
1704 1773
1705 __ ldr(r1, MemOperand(sp, kNextOffset)); 1774 __ ldr(r1, frame_->Element(kNextIndex));
1706 __ str(r1, MemOperand(r3)); 1775 __ str(r1, MemOperand(r3));
1707 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code 1776 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
1708 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); 1777 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
1709 // Code slot popped. 1778 // Code slot popped.
1710 1779
1711 __ b(shadows[i]->original_label()); 1780 __ b(shadows[i]->original_label());
1712 } 1781 }
1713 } 1782 }
1714 1783
1715 __ bind(&exit); 1784 __ bind(&exit);
1716 } 1785 }
1717 1786
1718 1787
1719 void CodeGenerator::VisitTryFinally(TryFinally* node) { 1788 void CodeGenerator::VisitTryFinally(TryFinally* node) {
1720 Comment cmnt(masm_, "[ TryFinally"); 1789 Comment cmnt(masm_, "[ TryFinally");
1721 1790
1722 // State: Used to keep track of reason for entering the finally 1791 // State: Used to keep track of reason for entering the finally
1723 // block. Should probably be extended to hold information for 1792 // block. Should probably be extended to hold information for
1724 // break/continue from within the try block. 1793 // break/continue from within the try block.
1725 enum { FALLING, THROWING, JUMPING }; 1794 enum { FALLING, THROWING, JUMPING };
1726 1795
1727 Label exit, unlink, try_block, finally_block; 1796 Label exit, unlink, try_block, finally_block;
1728 1797
1729 __ bl(&try_block); 1798 __ bl(&try_block);
1730 1799
1731 __ push(r0); // save exception object on the stack 1800 frame_->Push(r0); // save exception object on the stack
1732 // In case of thrown exceptions, this is where we continue. 1801 // In case of thrown exceptions, this is where we continue.
1733 __ mov(r2, Operand(Smi::FromInt(THROWING))); 1802 __ mov(r2, Operand(Smi::FromInt(THROWING)));
1734 __ b(&finally_block); 1803 __ b(&finally_block);
1735 1804
1736 1805
1737 // --- Try block --- 1806 // --- Try block ---
1738 __ bind(&try_block); 1807 __ bind(&try_block);
1739 1808
1740 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER); 1809 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER);
1741 1810
(...skipping 17 matching lines...) Expand all
1759 // After shadowing stops, the original labels are unshadowed and the 1828 // After shadowing stops, the original labels are unshadowed and the
1760 // LabelShadows represent the formerly shadowing labels. 1829 // LabelShadows represent the formerly shadowing labels.
1761 int nof_unlinks = 0; 1830 int nof_unlinks = 0;
1762 for (int i = 0; i <= nof_escapes; i++) { 1831 for (int i = 0; i <= nof_escapes; i++) {
1763 shadows[i]->StopShadowing(); 1832 shadows[i]->StopShadowing();
1764 if (shadows[i]->is_linked()) nof_unlinks++; 1833 if (shadows[i]->is_linked()) nof_unlinks++;
1765 } 1834 }
1766 1835
1767 // Set the state on the stack to FALLING. 1836 // Set the state on the stack to FALLING.
1768 __ mov(r0, Operand(Factory::undefined_value())); // fake TOS 1837 __ mov(r0, Operand(Factory::undefined_value())); // fake TOS
1769 __ push(r0); 1838 frame_->Push(r0);
1770 __ mov(r2, Operand(Smi::FromInt(FALLING))); 1839 __ mov(r2, Operand(Smi::FromInt(FALLING)));
1771 if (nof_unlinks > 0) __ b(&unlink); 1840 if (nof_unlinks > 0) __ b(&unlink);
1772 1841
1773 // Generate code to set the state for the (formerly) shadowing labels that 1842 // Generate code to set the state for the (formerly) shadowing labels that
1774 // have been jumped to. 1843 // have been jumped to.
1775 for (int i = 0; i <= nof_escapes; i++) { 1844 for (int i = 0; i <= nof_escapes; i++) {
1776 if (shadows[i]->is_linked()) { 1845 if (shadows[i]->is_linked()) {
1777 __ bind(shadows[i]); 1846 __ bind(shadows[i]);
1778 if (shadows[i]->original_label() == &function_return_) { 1847 if (shadows[i]->original_label() == &function_return_) {
1779 // If this label shadowed the function return, materialize the 1848 // If this label shadowed the function return, materialize the
1780 // return value on the stack. 1849 // return value on the stack.
1781 __ push(r0); 1850 frame_->Push(r0);
1782 } else { 1851 } else {
1783 // Fake TOS for labels that shadowed breaks and continues. 1852 // Fake TOS for labels that shadowed breaks and continues.
1784 __ mov(r0, Operand(Factory::undefined_value())); 1853 __ mov(r0, Operand(Factory::undefined_value()));
1785 __ push(r0); 1854 frame_->Push(r0);
1786 } 1855 }
1787 __ mov(r2, Operand(Smi::FromInt(JUMPING + i))); 1856 __ mov(r2, Operand(Smi::FromInt(JUMPING + i)));
1788 __ b(&unlink); 1857 __ b(&unlink);
1789 } 1858 }
1790 } 1859 }
1791 1860
1792 // Unlink from try chain; 1861 // Unlink from try chain;
1793 __ bind(&unlink); 1862 __ bind(&unlink);
1794 1863
1795 __ pop(r0); // Store TOS in r0 across stack manipulation 1864 frame_->Pop(r0); // Store TOS in r0 across stack manipulation
1796 // Reload sp from the top handler, because some statements that we 1865 // Reload sp from the top handler, because some statements that we
1797 // break from (eg, for...in) may have left stuff on the stack. 1866 // break from (eg, for...in) may have left stuff on the stack.
1798 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); 1867 __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
1799 __ ldr(sp, MemOperand(r3)); 1868 __ ldr(sp, MemOperand(r3));
1800 const int kNextOffset = StackHandlerConstants::kNextOffset + 1869 const int kNextIndex = (StackHandlerConstants::kNextOffset
1801 StackHandlerConstants::kAddressDisplacement; 1870 + StackHandlerConstants::kAddressDisplacement)
1802 __ ldr(r1, MemOperand(sp, kNextOffset)); 1871 / kPointerSize;
1872 __ ldr(r1, frame_->Element(kNextIndex));
1803 __ str(r1, MemOperand(r3)); 1873 __ str(r1, MemOperand(r3));
1804 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code 1874 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
1805 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); 1875 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
1806 // Code slot popped. 1876 // Code slot popped.
1807 __ push(r0); 1877 frame_->Push(r0);
1808 1878
1809 // --- Finally block --- 1879 // --- Finally block ---
1810 __ bind(&finally_block); 1880 __ bind(&finally_block);
1811 1881
1812 // Push the state on the stack. 1882 // Push the state on the stack.
1813 __ push(r2); 1883 frame_->Push(r2);
1814 1884
1815 // We keep two elements on the stack - the (possibly faked) result 1885 // We keep two elements on the stack - the (possibly faked) result
1816 // and the state - while evaluating the finally block. Record it, so 1886 // and the state - while evaluating the finally block. Record it, so
1817 // that a break/continue crossing this statement can restore the 1887 // that a break/continue crossing this statement can restore the
1818 // stack. 1888 // stack.
1819 const int kFinallyStackSize = 2 * kPointerSize; 1889 const int kFinallyStackSize = 2 * kPointerSize;
1820 break_stack_height_ += kFinallyStackSize; 1890 break_stack_height_ += kFinallyStackSize;
1821 1891
1822 // Generate code for the statements in the finally block. 1892 // Generate code for the statements in the finally block.
1823 VisitStatements(node->finally_block()->statements()); 1893 VisitStatements(node->finally_block()->statements());
1824 1894
1825 // Restore state and return value or faked TOS. 1895 // Restore state and return value or faked TOS.
1826 __ pop(r2); 1896 frame_->Pop(r2);
1827 __ pop(r0); 1897 frame_->Pop(r0);
1828 break_stack_height_ -= kFinallyStackSize; 1898 break_stack_height_ -= kFinallyStackSize;
1829 1899
1830 // Generate code to jump to the right destination for all used (formerly) 1900 // Generate code to jump to the right destination for all used (formerly)
1831 // shadowing labels. 1901 // shadowing labels.
1832 for (int i = 0; i <= nof_escapes; i++) { 1902 for (int i = 0; i <= nof_escapes; i++) {
1833 if (shadows[i]->is_bound()) { 1903 if (shadows[i]->is_bound()) {
1834 __ cmp(r2, Operand(Smi::FromInt(JUMPING + i))); 1904 __ cmp(r2, Operand(Smi::FromInt(JUMPING + i)));
1835 if (shadows[i]->original_label() != &function_return_) { 1905 if (shadows[i]->original_label() != &function_return_) {
1836 Label next; 1906 Label next;
1837 __ b(ne, &next); 1907 __ b(ne, &next);
1838 __ b(shadows[i]->original_label()); 1908 __ b(shadows[i]->original_label());
1839 __ bind(&next); 1909 __ bind(&next);
1840 } else { 1910 } else {
1841 __ b(eq, shadows[i]->original_label()); 1911 __ b(eq, shadows[i]->original_label());
1842 } 1912 }
1843 } 1913 }
1844 } 1914 }
1845 1915
1846 // Check if we need to rethrow the exception. 1916 // Check if we need to rethrow the exception.
1847 __ cmp(r2, Operand(Smi::FromInt(THROWING))); 1917 __ cmp(r2, Operand(Smi::FromInt(THROWING)));
1848 __ b(ne, &exit); 1918 __ b(ne, &exit);
1849 1919
1850 // Rethrow exception. 1920 // Rethrow exception.
1851 __ push(r0); 1921 frame_->Push(r0);
1852 __ CallRuntime(Runtime::kReThrow, 1); 1922 __ CallRuntime(Runtime::kReThrow, 1);
1853 1923
1854 // Done. 1924 // Done.
1855 __ bind(&exit); 1925 __ bind(&exit);
1856 } 1926 }
1857 1927
1858 1928
1859 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { 1929 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
1860 Comment cmnt(masm_, "[ DebuggerStatament"); 1930 Comment cmnt(masm_, "[ DebuggerStatament");
1861 if (FLAG_debug_info) RecordStatementPosition(node); 1931 if (FLAG_debug_info) RecordStatementPosition(node);
1862 __ CallRuntime(Runtime::kDebugBreak, 0); 1932 __ CallRuntime(Runtime::kDebugBreak, 0);
1863 // Ignore the return value. 1933 // Ignore the return value.
1864 } 1934 }
1865 1935
1866 1936
1867 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { 1937 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) {
1868 ASSERT(boilerplate->IsBoilerplate()); 1938 ASSERT(boilerplate->IsBoilerplate());
1869 1939
1870 // Push the boilerplate on the stack. 1940 // Push the boilerplate on the stack.
1871 __ mov(r0, Operand(boilerplate)); 1941 __ mov(r0, Operand(boilerplate));
1872 __ push(r0); 1942 frame_->Push(r0);
1873 1943
1874 // Create a new closure. 1944 // Create a new closure.
1875 __ push(cp); 1945 frame_->Push(cp);
1876 __ CallRuntime(Runtime::kNewClosure, 2); 1946 __ CallRuntime(Runtime::kNewClosure, 2);
1877 __ push(r0); 1947 frame_->Push(r0);
1878 } 1948 }
1879 1949
1880 1950
1881 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { 1951 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
1882 Comment cmnt(masm_, "[ FunctionLiteral"); 1952 Comment cmnt(masm_, "[ FunctionLiteral");
1883 1953
1884 // Build the function boilerplate and instantiate it. 1954 // Build the function boilerplate and instantiate it.
1885 Handle<JSFunction> boilerplate = BuildBoilerplate(node); 1955 Handle<JSFunction> boilerplate = BuildBoilerplate(node);
1886 // Check for stack-overflow exception. 1956 // Check for stack-overflow exception.
1887 if (HasStackOverflow()) return; 1957 if (HasStackOverflow()) return;
(...skipping 20 matching lines...) Expand all
1908 Load(node->else_expression(), typeof_state()); 1978 Load(node->else_expression(), typeof_state());
1909 __ bind(&exit); 1979 __ bind(&exit);
1910 } 1980 }
1911 1981
1912 1982
1913 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 1983 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
1914 if (slot->type() == Slot::LOOKUP) { 1984 if (slot->type() == Slot::LOOKUP) {
1915 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 1985 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
1916 1986
1917 // For now, just do a runtime call. 1987 // For now, just do a runtime call.
1918 __ push(cp); 1988 frame_->Push(cp);
1919 __ mov(r0, Operand(slot->var()->name())); 1989 __ mov(r0, Operand(slot->var()->name()));
1920 __ push(r0); 1990 frame_->Push(r0);
1921 1991
1922 if (typeof_state == INSIDE_TYPEOF) { 1992 if (typeof_state == INSIDE_TYPEOF) {
1923 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 1993 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
1924 } else { 1994 } else {
1925 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1995 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1926 } 1996 }
1927 __ push(r0); 1997 frame_->Push(r0);
1928 1998
1929 } else { 1999 } else {
1930 // Note: We would like to keep the assert below, but it fires because of 2000 // Note: We would like to keep the assert below, but it fires because of
1931 // some nasty code in LoadTypeofExpression() which should be removed... 2001 // some nasty code in LoadTypeofExpression() which should be removed...
1932 // ASSERT(slot->var()->mode() != Variable::DYNAMIC); 2002 // ASSERT(slot->var()->mode() != Variable::DYNAMIC);
1933 2003
1934 // Special handling for locals allocated in registers. 2004 // Special handling for locals allocated in registers.
1935 __ ldr(r0, SlotOperand(slot, r2)); 2005 __ ldr(r0, SlotOperand(slot, r2));
1936 __ push(r0); 2006 frame_->Push(r0);
1937 if (slot->var()->mode() == Variable::CONST) { 2007 if (slot->var()->mode() == Variable::CONST) {
1938 // Const slots may contain 'the hole' value (the constant hasn't been 2008 // Const slots may contain 'the hole' value (the constant hasn't been
1939 // initialized yet) which needs to be converted into the 'undefined' 2009 // initialized yet) which needs to be converted into the 'undefined'
1940 // value. 2010 // value.
1941 Comment cmnt(masm_, "[ Unhole const"); 2011 Comment cmnt(masm_, "[ Unhole const");
1942 __ pop(r0); 2012 frame_->Pop(r0);
1943 __ cmp(r0, Operand(Factory::the_hole_value())); 2013 __ cmp(r0, Operand(Factory::the_hole_value()));
1944 __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq); 2014 __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq);
1945 __ push(r0); 2015 frame_->Push(r0);
1946 } 2016 }
1947 } 2017 }
1948 } 2018 }
1949 2019
1950 2020
1951 void CodeGenerator::VisitSlot(Slot* node) { 2021 void CodeGenerator::VisitSlot(Slot* node) {
1952 Comment cmnt(masm_, "[ Slot"); 2022 Comment cmnt(masm_, "[ Slot");
1953 LoadFromSlot(node, typeof_state()); 2023 LoadFromSlot(node, typeof_state());
1954 } 2024 }
1955 2025
1956 2026
1957 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { 2027 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
1958 Comment cmnt(masm_, "[ VariableProxy"); 2028 Comment cmnt(masm_, "[ VariableProxy");
1959 2029
1960 Variable* var = node->var(); 2030 Variable* var = node->var();
1961 Expression* expr = var->rewrite(); 2031 Expression* expr = var->rewrite();
1962 if (expr != NULL) { 2032 if (expr != NULL) {
1963 Visit(expr); 2033 Visit(expr);
1964 } else { 2034 } else {
1965 ASSERT(var->is_global()); 2035 ASSERT(var->is_global());
1966 Reference ref(this, node); 2036 Reference ref(this, node);
1967 ref.GetValue(typeof_state()); 2037 ref.GetValue(typeof_state());
1968 } 2038 }
1969 } 2039 }
1970 2040
1971 2041
1972 void CodeGenerator::VisitLiteral(Literal* node) { 2042 void CodeGenerator::VisitLiteral(Literal* node) {
1973 Comment cmnt(masm_, "[ Literal"); 2043 Comment cmnt(masm_, "[ Literal");
1974 __ mov(r0, Operand(node->handle())); 2044 __ mov(r0, Operand(node->handle()));
1975 __ push(r0); 2045 frame_->Push(r0);
1976 } 2046 }
1977 2047
1978 2048
1979 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { 2049 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
1980 Comment cmnt(masm_, "[ RexExp Literal"); 2050 Comment cmnt(masm_, "[ RexExp Literal");
1981 2051
1982 // Retrieve the literal array and check the allocated entry. 2052 // Retrieve the literal array and check the allocated entry.
1983 2053
1984 // Load the function of this activation. 2054 // Load the function of this activation.
1985 __ ldr(r1, FunctionOperand()); 2055 __ ldr(r1, frame_->Function());
1986 2056
1987 // Load the literals array of the function. 2057 // Load the literals array of the function.
1988 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); 2058 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset));
1989 2059
1990 // Load the literal at the ast saved index. 2060 // Load the literal at the ast saved index.
1991 int literal_offset = 2061 int literal_offset =
1992 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; 2062 FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
1993 __ ldr(r2, FieldMemOperand(r1, literal_offset)); 2063 __ ldr(r2, FieldMemOperand(r1, literal_offset));
1994 2064
1995 Label done; 2065 Label done;
1996 __ cmp(r2, Operand(Factory::undefined_value())); 2066 __ cmp(r2, Operand(Factory::undefined_value()));
1997 __ b(ne, &done); 2067 __ b(ne, &done);
1998 2068
1999 // If the entry is undefined we call the runtime system to computed 2069 // If the entry is undefined we call the runtime system to computed
2000 // the literal. 2070 // the literal.
2001 __ push(r1); // literal array (0) 2071 frame_->Push(r1); // literal array (0)
2002 __ mov(r0, Operand(Smi::FromInt(node->literal_index()))); 2072 __ mov(r0, Operand(Smi::FromInt(node->literal_index())));
2003 __ push(r0); // literal index (1) 2073 frame_->Push(r0); // literal index (1)
2004 __ mov(r0, Operand(node->pattern())); // RegExp pattern (2) 2074 __ mov(r0, Operand(node->pattern())); // RegExp pattern (2)
2005 __ push(r0); 2075 frame_->Push(r0);
2006 __ mov(r0, Operand(node->flags())); // RegExp flags (3) 2076 __ mov(r0, Operand(node->flags())); // RegExp flags (3)
2007 __ push(r0); 2077 frame_->Push(r0);
2008 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 2078 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
2009 __ mov(r2, Operand(r0)); 2079 __ mov(r2, Operand(r0));
2010 2080
2011 __ bind(&done); 2081 __ bind(&done);
2012 // Push the literal. 2082 // Push the literal.
2013 __ push(r2); 2083 frame_->Push(r2);
2014 } 2084 }
2015 2085
2016 2086
2017 // This deferred code stub will be used for creating the boilerplate 2087 // This deferred code stub will be used for creating the boilerplate
2018 // by calling Runtime_CreateObjectLiteral. 2088 // by calling Runtime_CreateObjectLiteral.
2019 // Each created boilerplate is stored in the JSFunction and they are 2089 // Each created boilerplate is stored in the JSFunction and they are
2020 // therefore context dependent. 2090 // therefore context dependent.
2021 class ObjectLiteralDeferred: public DeferredCode { 2091 class ObjectLiteralDeferred: public DeferredCode {
2022 public: 2092 public:
2023 ObjectLiteralDeferred(CodeGenerator* generator, ObjectLiteral* node) 2093 ObjectLiteralDeferred(CodeGenerator* generator, ObjectLiteral* node)
(...skipping 24 matching lines...) Expand all
2048 2118
2049 2119
2050 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { 2120 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
2051 Comment cmnt(masm_, "[ ObjectLiteral"); 2121 Comment cmnt(masm_, "[ ObjectLiteral");
2052 2122
2053 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); 2123 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node);
2054 2124
2055 // Retrieve the literal array and check the allocated entry. 2125 // Retrieve the literal array and check the allocated entry.
2056 2126
2057 // Load the function of this activation. 2127 // Load the function of this activation.
2058 __ ldr(r1, FunctionOperand()); 2128 __ ldr(r1, frame_->Function());
2059 2129
2060 // Load the literals array of the function. 2130 // Load the literals array of the function.
2061 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); 2131 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset));
2062 2132
2063 // Load the literal at the ast saved index. 2133 // Load the literal at the ast saved index.
2064 int literal_offset = 2134 int literal_offset =
2065 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; 2135 FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
2066 __ ldr(r2, FieldMemOperand(r1, literal_offset)); 2136 __ ldr(r2, FieldMemOperand(r1, literal_offset));
2067 2137
2068 // Check whether we need to materialize the object literal boilerplate. 2138 // Check whether we need to materialize the object literal boilerplate.
2069 // If so, jump to the deferred code. 2139 // If so, jump to the deferred code.
2070 __ cmp(r2, Operand(Factory::undefined_value())); 2140 __ cmp(r2, Operand(Factory::undefined_value()));
2071 __ b(eq, deferred->enter()); 2141 __ b(eq, deferred->enter());
2072 __ bind(deferred->exit()); 2142 __ bind(deferred->exit());
2073 2143
2074 // Push the object literal boilerplate. 2144 // Push the object literal boilerplate.
2075 __ push(r2); 2145 frame_->Push(r2);
2076 2146
2077 // Clone the boilerplate object. 2147 // Clone the boilerplate object.
2078 __ CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1); 2148 __ CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1);
2079 __ push(r0); // save the result 2149 frame_->Push(r0); // save the result
2080 // r0: cloned object literal 2150 // r0: cloned object literal
2081 2151
2082 for (int i = 0; i < node->properties()->length(); i++) { 2152 for (int i = 0; i < node->properties()->length(); i++) {
2083 ObjectLiteral::Property* property = node->properties()->at(i); 2153 ObjectLiteral::Property* property = node->properties()->at(i);
2084 Literal* key = property->key(); 2154 Literal* key = property->key();
2085 Expression* value = property->value(); 2155 Expression* value = property->value();
2086 switch (property->kind()) { 2156 switch (property->kind()) {
2087 case ObjectLiteral::Property::CONSTANT: break; 2157 case ObjectLiteral::Property::CONSTANT: break;
2088 case ObjectLiteral::Property::COMPUTED: // fall through 2158 case ObjectLiteral::Property::COMPUTED: // fall through
2089 case ObjectLiteral::Property::PROTOTYPE: { 2159 case ObjectLiteral::Property::PROTOTYPE: {
2090 __ push(r0); // dup the result 2160 frame_->Push(r0); // dup the result
2091 Load(key); 2161 Load(key);
2092 Load(value); 2162 Load(value);
2093 __ CallRuntime(Runtime::kSetProperty, 3); 2163 __ CallRuntime(Runtime::kSetProperty, 3);
2094 // restore r0 2164 // restore r0
2095 __ ldr(r0, MemOperand(sp, 0)); 2165 __ ldr(r0, frame_->Top());
2096 break; 2166 break;
2097 } 2167 }
2098 case ObjectLiteral::Property::SETTER: { 2168 case ObjectLiteral::Property::SETTER: {
2099 __ push(r0); 2169 frame_->Push(r0);
2100 Load(key); 2170 Load(key);
2101 __ mov(r0, Operand(Smi::FromInt(1))); 2171 __ mov(r0, Operand(Smi::FromInt(1)));
2102 __ push(r0); 2172 frame_->Push(r0);
2103 Load(value); 2173 Load(value);
2104 __ CallRuntime(Runtime::kDefineAccessor, 4); 2174 __ CallRuntime(Runtime::kDefineAccessor, 4);
2105 __ ldr(r0, MemOperand(sp, 0)); 2175 __ ldr(r0, frame_->Top());
2106 break; 2176 break;
2107 } 2177 }
2108 case ObjectLiteral::Property::GETTER: { 2178 case ObjectLiteral::Property::GETTER: {
2109 __ push(r0); 2179 frame_->Push(r0);
2110 Load(key); 2180 Load(key);
2111 __ mov(r0, Operand(Smi::FromInt(0))); 2181 __ mov(r0, Operand(Smi::FromInt(0)));
2112 __ push(r0); 2182 frame_->Push(r0);
2113 Load(value); 2183 Load(value);
2114 __ CallRuntime(Runtime::kDefineAccessor, 4); 2184 __ CallRuntime(Runtime::kDefineAccessor, 4);
2115 __ ldr(r0, MemOperand(sp, 0)); 2185 __ ldr(r0, frame_->Top());
2116 break; 2186 break;
2117 } 2187 }
2118 } 2188 }
2119 } 2189 }
2120 } 2190 }
2121 2191
2122 2192
2123 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 2193 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
2124 Comment cmnt(masm_, "[ ArrayLiteral"); 2194 Comment cmnt(masm_, "[ ArrayLiteral");
2125 2195
2126 // Call runtime to create the array literal. 2196 // Call runtime to create the array literal.
2127 __ mov(r0, Operand(node->literals())); 2197 __ mov(r0, Operand(node->literals()));
2128 __ push(r0); 2198 frame_->Push(r0);
2129 // Load the function of this frame. 2199 // Load the function of this frame.
2130 __ ldr(r0, FunctionOperand()); 2200 __ ldr(r0, frame_->Function());
2131 __ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); 2201 __ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
2132 __ push(r0); 2202 frame_->Push(r0);
2133 __ CallRuntime(Runtime::kCreateArrayLiteral, 2); 2203 __ CallRuntime(Runtime::kCreateArrayLiteral, 2);
2134 2204
2135 // Push the resulting array literal on the stack. 2205 // Push the resulting array literal on the stack.
2136 __ push(r0); 2206 frame_->Push(r0);
2137 2207
2138 // Generate code to set the elements in the array that are not 2208 // Generate code to set the elements in the array that are not
2139 // literals. 2209 // literals.
2140 for (int i = 0; i < node->values()->length(); i++) { 2210 for (int i = 0; i < node->values()->length(); i++) {
2141 Expression* value = node->values()->at(i); 2211 Expression* value = node->values()->at(i);
2142 2212
2143 // If value is literal the property value is already 2213 // If value is literal the property value is already
2144 // set in the boilerplate object. 2214 // set in the boilerplate object.
2145 if (value->AsLiteral() == NULL) { 2215 if (value->AsLiteral() == NULL) {
2146 // The property must be set by generated code. 2216 // The property must be set by generated code.
2147 Load(value); 2217 Load(value);
2148 __ pop(r0); 2218 frame_->Pop(r0);
2149 2219
2150 // Fetch the object literal 2220 // Fetch the object literal
2151 __ ldr(r1, MemOperand(sp, 0)); 2221 __ ldr(r1, frame_->Top());
2152 // Get the elements array. 2222 // Get the elements array.
2153 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); 2223 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
2154 2224
2155 // Write to the indexed properties array. 2225 // Write to the indexed properties array.
2156 int offset = i * kPointerSize + Array::kHeaderSize; 2226 int offset = i * kPointerSize + Array::kHeaderSize;
2157 __ str(r0, FieldMemOperand(r1, offset)); 2227 __ str(r0, FieldMemOperand(r1, offset));
2158 2228
2159 // Update the write barrier for the array address. 2229 // Update the write barrier for the array address.
2160 __ mov(r3, Operand(offset)); 2230 __ mov(r3, Operand(offset));
2161 __ RecordWrite(r1, r3, r2); 2231 __ RecordWrite(r1, r3, r2);
(...skipping 12 matching lines...) Expand all
2174 if (node->op() == Token::ASSIGN || 2244 if (node->op() == Token::ASSIGN ||
2175 node->op() == Token::INIT_VAR || 2245 node->op() == Token::INIT_VAR ||
2176 node->op() == Token::INIT_CONST) { 2246 node->op() == Token::INIT_CONST) {
2177 Load(node->value()); 2247 Load(node->value());
2178 2248
2179 } else { 2249 } else {
2180 target.GetValue(NOT_INSIDE_TYPEOF); 2250 target.GetValue(NOT_INSIDE_TYPEOF);
2181 Literal* literal = node->value()->AsLiteral(); 2251 Literal* literal = node->value()->AsLiteral();
2182 if (literal != NULL && literal->handle()->IsSmi()) { 2252 if (literal != NULL && literal->handle()->IsSmi()) {
2183 SmiOperation(node->binary_op(), literal->handle(), false); 2253 SmiOperation(node->binary_op(), literal->handle(), false);
2184 __ push(r0); 2254 frame_->Push(r0);
2185 2255
2186 } else { 2256 } else {
2187 Load(node->value()); 2257 Load(node->value());
2188 GenericBinaryOperation(node->binary_op()); 2258 GenericBinaryOperation(node->binary_op());
2189 __ push(r0); 2259 frame_->Push(r0);
2190 } 2260 }
2191 } 2261 }
2192 2262
2193 Variable* var = node->target()->AsVariableProxy()->AsVariable(); 2263 Variable* var = node->target()->AsVariableProxy()->AsVariable();
2194 if (var != NULL && 2264 if (var != NULL &&
2195 (var->mode() == Variable::CONST) && 2265 (var->mode() == Variable::CONST) &&
2196 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { 2266 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
2197 // Assignment ignored - leave the value on the stack. 2267 // Assignment ignored - leave the value on the stack.
2198 2268
2199 } else { 2269 } else {
2200 __ RecordPosition(node->position()); 2270 __ RecordPosition(node->position());
2201 if (node->op() == Token::INIT_CONST) { 2271 if (node->op() == Token::INIT_CONST) {
2202 // Dynamic constant initializations must use the function context 2272 // Dynamic constant initializations must use the function context
2203 // and initialize the actual constant declared. Dynamic variable 2273 // and initialize the actual constant declared. Dynamic variable
2204 // initializations are simply assignments and use SetValue. 2274 // initializations are simply assignments and use SetValue.
2205 target.SetValue(CONST_INIT); 2275 target.SetValue(CONST_INIT);
2206 } else { 2276 } else {
2207 target.SetValue(NOT_CONST_INIT); 2277 target.SetValue(NOT_CONST_INIT);
2208 } 2278 }
2209 } 2279 }
2210 } 2280 }
2211 2281
2212 2282
2213 void CodeGenerator::VisitThrow(Throw* node) { 2283 void CodeGenerator::VisitThrow(Throw* node) {
2214 Comment cmnt(masm_, "[ Throw"); 2284 Comment cmnt(masm_, "[ Throw");
2215 2285
2216 Load(node->exception()); 2286 Load(node->exception());
2217 __ RecordPosition(node->position()); 2287 __ RecordPosition(node->position());
2218 __ CallRuntime(Runtime::kThrow, 1); 2288 __ CallRuntime(Runtime::kThrow, 1);
2219 __ push(r0); 2289 frame_->Push(r0);
2220 } 2290 }
2221 2291
2222 2292
2223 void CodeGenerator::VisitProperty(Property* node) { 2293 void CodeGenerator::VisitProperty(Property* node) {
2224 Comment cmnt(masm_, "[ Property"); 2294 Comment cmnt(masm_, "[ Property");
2225 2295
2226 Reference property(this, node); 2296 Reference property(this, node);
2227 property.GetValue(typeof_state()); 2297 property.GetValue(typeof_state());
2228 } 2298 }
2229 2299
(...skipping 20 matching lines...) Expand all
2250 // is resolved in cache misses (this also holds for megamorphic calls). 2320 // is resolved in cache misses (this also holds for megamorphic calls).
2251 // ------------------------------------------------------------------------ 2321 // ------------------------------------------------------------------------
2252 2322
2253 if (var != NULL && !var->is_this() && var->is_global()) { 2323 if (var != NULL && !var->is_this() && var->is_global()) {
2254 // ---------------------------------- 2324 // ----------------------------------
2255 // JavaScript example: 'foo(1, 2, 3)' // foo is global 2325 // JavaScript example: 'foo(1, 2, 3)' // foo is global
2256 // ---------------------------------- 2326 // ----------------------------------
2257 2327
2258 // Push the name of the function and the receiver onto the stack. 2328 // Push the name of the function and the receiver onto the stack.
2259 __ mov(r0, Operand(var->name())); 2329 __ mov(r0, Operand(var->name()));
2260 __ push(r0); 2330 frame_->Push(r0);
2261 2331
2262 // Pass the global object as the receiver and let the IC stub 2332 // Pass the global object as the receiver and let the IC stub
2263 // patch the stack to use the global proxy as 'this' in the 2333 // patch the stack to use the global proxy as 'this' in the
2264 // invoked function. 2334 // invoked function.
2265 LoadGlobal(); 2335 LoadGlobal();
2266 2336
2267 // Load the arguments. 2337 // Load the arguments.
2268 for (int i = 0; i < args->length(); i++) Load(args->at(i)); 2338 for (int i = 0; i < args->length(); i++) Load(args->at(i));
2269 2339
2270 // Setup the receiver register and call the IC initialization code. 2340 // Setup the receiver register and call the IC initialization code.
2271 Handle<Code> stub = ComputeCallInitialize(args->length()); 2341 Handle<Code> stub = ComputeCallInitialize(args->length());
2272 __ RecordPosition(node->position()); 2342 __ RecordPosition(node->position());
2273 __ Call(stub, RelocInfo::CODE_TARGET_CONTEXT); 2343 __ Call(stub, RelocInfo::CODE_TARGET_CONTEXT);
2274 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2344 __ ldr(cp, frame_->Context());
2275 // Remove the function from the stack. 2345 // Remove the function from the stack.
2276 __ pop(); 2346 frame_->Pop();
2277 __ push(r0); 2347 frame_->Push(r0);
2278 2348
2279 } else if (var != NULL && var->slot() != NULL && 2349 } else if (var != NULL && var->slot() != NULL &&
2280 var->slot()->type() == Slot::LOOKUP) { 2350 var->slot()->type() == Slot::LOOKUP) {
2281 // ---------------------------------- 2351 // ----------------------------------
2282 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj 2352 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj
2283 // ---------------------------------- 2353 // ----------------------------------
2284 2354
2285 // Load the function 2355 // Load the function
2286 __ push(cp); 2356 frame_->Push(cp);
2287 __ mov(r0, Operand(var->name())); 2357 __ mov(r0, Operand(var->name()));
2288 __ push(r0); 2358 frame_->Push(r0);
2289 __ CallRuntime(Runtime::kLoadContextSlot, 2); 2359 __ CallRuntime(Runtime::kLoadContextSlot, 2);
2290 // r0: slot value; r1: receiver 2360 // r0: slot value; r1: receiver
2291 2361
2292 // Load the receiver. 2362 // Load the receiver.
2293 __ push(r0); // function 2363 frame_->Push(r0); // function
2294 __ push(r1); // receiver 2364 frame_->Push(r1); // receiver
2295 2365
2296 // Call the function. 2366 // Call the function.
2297 CallWithArguments(args, node->position()); 2367 CallWithArguments(args, node->position());
2298 __ push(r0); 2368 frame_->Push(r0);
2299 2369
2300 } else if (property != NULL) { 2370 } else if (property != NULL) {
2301 // Check if the key is a literal string. 2371 // Check if the key is a literal string.
2302 Literal* literal = property->key()->AsLiteral(); 2372 Literal* literal = property->key()->AsLiteral();
2303 2373
2304 if (literal != NULL && literal->handle()->IsSymbol()) { 2374 if (literal != NULL && literal->handle()->IsSymbol()) {
2305 // ------------------------------------------------------------------ 2375 // ------------------------------------------------------------------
2306 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' 2376 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
2307 // ------------------------------------------------------------------ 2377 // ------------------------------------------------------------------
2308 2378
2309 // Push the name of the function and the receiver onto the stack. 2379 // Push the name of the function and the receiver onto the stack.
2310 __ mov(r0, Operand(literal->handle())); 2380 __ mov(r0, Operand(literal->handle()));
2311 __ push(r0); 2381 frame_->Push(r0);
2312 Load(property->obj()); 2382 Load(property->obj());
2313 2383
2314 // Load the arguments. 2384 // Load the arguments.
2315 for (int i = 0; i < args->length(); i++) Load(args->at(i)); 2385 for (int i = 0; i < args->length(); i++) Load(args->at(i));
2316 2386
2317 // Set the receiver register and call the IC initialization code. 2387 // Set the receiver register and call the IC initialization code.
2318 Handle<Code> stub = ComputeCallInitialize(args->length()); 2388 Handle<Code> stub = ComputeCallInitialize(args->length());
2319 __ RecordPosition(node->position()); 2389 __ RecordPosition(node->position());
2320 __ Call(stub, RelocInfo::CODE_TARGET); 2390 __ Call(stub, RelocInfo::CODE_TARGET);
2321 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2391 __ ldr(cp, frame_->Context());
2322 2392
2323 // Remove the function from the stack. 2393 // Remove the function from the stack.
2324 __ pop(); 2394 frame_->Pop();
2325 2395
2326 __ push(r0); // push after get rid of function from the stack 2396 frame_->Push(r0); // push after get rid of function from the stack
2327 2397
2328 } else { 2398 } else {
2329 // ------------------------------------------- 2399 // -------------------------------------------
2330 // JavaScript example: 'array[index](1, 2, 3)' 2400 // JavaScript example: 'array[index](1, 2, 3)'
2331 // ------------------------------------------- 2401 // -------------------------------------------
2332 2402
2333 // Load the function to call from the property through a reference. 2403 // Load the function to call from the property through a reference.
2334 Reference ref(this, property); 2404 Reference ref(this, property);
2335 ref.GetValue(NOT_INSIDE_TYPEOF); // receiver 2405 ref.GetValue(NOT_INSIDE_TYPEOF); // receiver
2336 2406
2337 // Pass receiver to called function. 2407 // Pass receiver to called function.
2338 __ ldr(r0, MemOperand(sp, ref.size() * kPointerSize)); 2408 __ ldr(r0, frame_->Element(ref.size()));
2339 __ push(r0); 2409 frame_->Push(r0);
2340 // Call the function. 2410 // Call the function.
2341 CallWithArguments(args, node->position()); 2411 CallWithArguments(args, node->position());
2342 __ push(r0); 2412 frame_->Push(r0);
2343 } 2413 }
2344 2414
2345 } else { 2415 } else {
2346 // ---------------------------------- 2416 // ----------------------------------
2347 // JavaScript example: 'foo(1, 2, 3)' // foo is not global 2417 // JavaScript example: 'foo(1, 2, 3)' // foo is not global
2348 // ---------------------------------- 2418 // ----------------------------------
2349 2419
2350 // Load the function. 2420 // Load the function.
2351 Load(function); 2421 Load(function);
2352 2422
2353 // Pass the global proxy as the receiver. 2423 // Pass the global proxy as the receiver.
2354 LoadGlobalReceiver(r0); 2424 LoadGlobalReceiver(r0);
2355 2425
2356 // Call the function. 2426 // Call the function.
2357 CallWithArguments(args, node->position()); 2427 CallWithArguments(args, node->position());
2358 __ push(r0); 2428 frame_->Push(r0);
2359 } 2429 }
2360 } 2430 }
2361 2431
2362 2432
2363 void CodeGenerator::VisitCallNew(CallNew* node) { 2433 void CodeGenerator::VisitCallNew(CallNew* node) {
2364 Comment cmnt(masm_, "[ CallNew"); 2434 Comment cmnt(masm_, "[ CallNew");
2365 2435
2366 // According to ECMA-262, section 11.2.2, page 44, the function 2436 // According to ECMA-262, section 11.2.2, page 44, the function
2367 // expression in new calls must be evaluated before the 2437 // expression in new calls must be evaluated before the
2368 // arguments. This is different from ordinary calls, where the 2438 // arguments. This is different from ordinary calls, where the
2369 // actual function to call is resolved after the arguments have been 2439 // actual function to call is resolved after the arguments have been
2370 // evaluated. 2440 // evaluated.
2371 2441
2372 // Compute function to call and use the global object as the 2442 // Compute function to call and use the global object as the
2373 // receiver. There is no need to use the global proxy here because 2443 // receiver. There is no need to use the global proxy here because
2374 // it will always be replaced with a newly allocated object. 2444 // it will always be replaced with a newly allocated object.
2375 Load(node->expression()); 2445 Load(node->expression());
2376 LoadGlobal(); 2446 LoadGlobal();
2377 2447
2378 // Push the arguments ("left-to-right") on the stack. 2448 // Push the arguments ("left-to-right") on the stack.
2379 ZoneList<Expression*>* args = node->arguments(); 2449 ZoneList<Expression*>* args = node->arguments();
2380 for (int i = 0; i < args->length(); i++) Load(args->at(i)); 2450 for (int i = 0; i < args->length(); i++) Load(args->at(i));
2381 2451
2382 // r0: the number of arguments. 2452 // r0: the number of arguments.
2383 __ mov(r0, Operand(args->length())); 2453 __ mov(r0, Operand(args->length()));
2384 2454
2385 // Load the function into r1 as per calling convention. 2455 // Load the function into r1 as per calling convention.
2386 __ ldr(r1, MemOperand(sp, (args->length() + 1) * kPointerSize)); 2456 __ ldr(r1, frame_->Element(args->length() + 1));
2387 2457
2388 // Call the construct call builtin that handles allocation and 2458 // Call the construct call builtin that handles allocation and
2389 // constructor invocation. 2459 // constructor invocation.
2390 __ RecordPosition(RelocInfo::POSITION); 2460 __ RecordPosition(RelocInfo::POSITION);
2391 __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), 2461 __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
2392 RelocInfo::CONSTRUCT_CALL); 2462 RelocInfo::CONSTRUCT_CALL);
2393 2463
2394 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). 2464 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)).
2395 __ str(r0, MemOperand(sp, 0 * kPointerSize)); 2465 __ str(r0, frame_->Top());
2396 } 2466 }
2397 2467
2398 2468
2399 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { 2469 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
2400 ASSERT(args->length() == 1); 2470 ASSERT(args->length() == 1);
2401 Label leave; 2471 Label leave;
2402 Load(args->at(0)); 2472 Load(args->at(0));
2403 __ pop(r0); // r0 contains object. 2473 frame_->Pop(r0); // r0 contains object.
2404 // if (object->IsSmi()) return the object. 2474 // if (object->IsSmi()) return the object.
2405 __ tst(r0, Operand(kSmiTagMask)); 2475 __ tst(r0, Operand(kSmiTagMask));
2406 __ b(eq, &leave); 2476 __ b(eq, &leave);
2407 // It is a heap object - get map. 2477 // It is a heap object - get map.
2408 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2478 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2409 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 2479 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
2410 // if (!object->IsJSValue()) return the object. 2480 // if (!object->IsJSValue()) return the object.
2411 __ cmp(r1, Operand(JS_VALUE_TYPE)); 2481 __ cmp(r1, Operand(JS_VALUE_TYPE));
2412 __ b(ne, &leave); 2482 __ b(ne, &leave);
2413 // Load the value. 2483 // Load the value.
2414 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); 2484 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
2415 __ bind(&leave); 2485 __ bind(&leave);
2416 __ push(r0); 2486 frame_->Push(r0);
2417 } 2487 }
2418 2488
2419 2489
2420 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { 2490 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
2421 ASSERT(args->length() == 2); 2491 ASSERT(args->length() == 2);
2422 Label leave; 2492 Label leave;
2423 Load(args->at(0)); // Load the object. 2493 Load(args->at(0)); // Load the object.
2424 Load(args->at(1)); // Load the value. 2494 Load(args->at(1)); // Load the value.
2425 __ pop(r0); // r0 contains value 2495 frame_->Pop(r0); // r0 contains value
2426 __ pop(r1); // r1 contains object 2496 frame_->Pop(r1); // r1 contains object
2427 // if (object->IsSmi()) return object. 2497 // if (object->IsSmi()) return object.
2428 __ tst(r1, Operand(kSmiTagMask)); 2498 __ tst(r1, Operand(kSmiTagMask));
2429 __ b(eq, &leave); 2499 __ b(eq, &leave);
2430 // It is a heap object - get map. 2500 // It is a heap object - get map.
2431 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 2501 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
2432 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 2502 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
2433 // if (!object->IsJSValue()) return object. 2503 // if (!object->IsJSValue()) return object.
2434 __ cmp(r2, Operand(JS_VALUE_TYPE)); 2504 __ cmp(r2, Operand(JS_VALUE_TYPE));
2435 __ b(ne, &leave); 2505 __ b(ne, &leave);
2436 // Store the value. 2506 // Store the value.
2437 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); 2507 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
2438 // Update the write barrier. 2508 // Update the write barrier.
2439 __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag)); 2509 __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag));
2440 __ RecordWrite(r1, r2, r3); 2510 __ RecordWrite(r1, r2, r3);
2441 // Leave. 2511 // Leave.
2442 __ bind(&leave); 2512 __ bind(&leave);
2443 __ push(r0); 2513 frame_->Push(r0);
2444 } 2514 }
2445 2515
2446 2516
2447 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { 2517 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
2448 ASSERT(args->length() == 1); 2518 ASSERT(args->length() == 1);
2449 Load(args->at(0)); 2519 Load(args->at(0));
2450 __ pop(r0); 2520 frame_->Pop(r0);
2451 __ tst(r0, Operand(kSmiTagMask)); 2521 __ tst(r0, Operand(kSmiTagMask));
2452 cc_reg_ = eq; 2522 cc_reg_ = eq;
2453 } 2523 }
2454 2524
2455 2525
2456 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 2526 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
2457 ASSERT(args->length() == 1); 2527 ASSERT(args->length() == 1);
2458 Load(args->at(0)); 2528 Load(args->at(0));
2459 __ pop(r0); 2529 frame_->Pop(r0);
2460 __ tst(r0, Operand(kSmiTagMask | 0x80000000)); 2530 __ tst(r0, Operand(kSmiTagMask | 0x80000000));
2461 cc_reg_ = eq; 2531 cc_reg_ = eq;
2462 } 2532 }
2463 2533
2464 2534
2465 // This should generate code that performs a charCodeAt() call or returns 2535 // This should generate code that performs a charCodeAt() call or returns
2466 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 2536 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
2467 // It is not yet implemented on ARM, so it always goes to the slow case. 2537 // It is not yet implemented on ARM, so it always goes to the slow case.
2468 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 2538 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
2469 ASSERT(args->length() == 2); 2539 ASSERT(args->length() == 2);
2470 __ mov(r0, Operand(Factory::undefined_value())); 2540 __ mov(r0, Operand(Factory::undefined_value()));
2471 __ push(r0); 2541 frame_->Push(r0);
2472 } 2542 }
2473 2543
2474 2544
2475 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 2545 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
2476 ASSERT(args->length() == 1); 2546 ASSERT(args->length() == 1);
2477 Load(args->at(0)); 2547 Load(args->at(0));
2478 Label answer; 2548 Label answer;
2479 // We need the CC bits to come out as not_equal in the case where the 2549 // We need the CC bits to come out as not_equal in the case where the
2480 // object is a smi. This can't be done with the usual test opcode so 2550 // object is a smi. This can't be done with the usual test opcode so
2481 // we use XOR to get the right CC bits. 2551 // we use XOR to get the right CC bits.
2482 __ pop(r0); 2552 frame_->Pop(r0);
2483 __ and_(r1, r0, Operand(kSmiTagMask)); 2553 __ and_(r1, r0, Operand(kSmiTagMask));
2484 __ eor(r1, r1, Operand(kSmiTagMask), SetCC); 2554 __ eor(r1, r1, Operand(kSmiTagMask), SetCC);
2485 __ b(ne, &answer); 2555 __ b(ne, &answer);
2486 // It is a heap object - get the map. 2556 // It is a heap object - get the map.
2487 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2557 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2488 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 2558 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
2489 // Check if the object is a JS array or not. 2559 // Check if the object is a JS array or not.
2490 __ cmp(r1, Operand(JS_ARRAY_TYPE)); 2560 __ cmp(r1, Operand(JS_ARRAY_TYPE));
2491 __ bind(&answer); 2561 __ bind(&answer);
2492 cc_reg_ = eq; 2562 cc_reg_ = eq;
2493 } 2563 }
2494 2564
2495 2565
2496 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { 2566 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
2497 ASSERT(args->length() == 0); 2567 ASSERT(args->length() == 0);
2498 2568
2499 // Seed the result with the formal parameters count, which will be used 2569 // Seed the result with the formal parameters count, which will be used
2500 // in case no arguments adaptor frame is found below the current frame. 2570 // in case no arguments adaptor frame is found below the current frame.
2501 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); 2571 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
2502 2572
2503 // Call the shared stub to get to the arguments.length. 2573 // Call the shared stub to get to the arguments.length.
2504 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); 2574 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
2505 __ CallStub(&stub); 2575 __ CallStub(&stub);
2506 __ push(r0); 2576 frame_->Push(r0);
2507 } 2577 }
2508 2578
2509 2579
2510 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { 2580 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
2511 ASSERT(args->length() == 1); 2581 ASSERT(args->length() == 1);
2512 2582
2513 // Satisfy contract with ArgumentsAccessStub: 2583 // Satisfy contract with ArgumentsAccessStub:
2514 // Load the key into r1 and the formal parameters count into r0. 2584 // Load the key into r1 and the formal parameters count into r0.
2515 Load(args->at(0)); 2585 Load(args->at(0));
2516 __ pop(r1); 2586 frame_->Pop(r1);
2517 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); 2587 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
2518 2588
2519 // Call the shared stub to get to arguments[key]. 2589 // Call the shared stub to get to arguments[key].
2520 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2590 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2521 __ CallStub(&stub); 2591 __ CallStub(&stub);
2522 __ push(r0); 2592 frame_->Push(r0);
2523 } 2593 }
2524 2594
2525 2595
2526 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { 2596 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
2527 ASSERT(args->length() == 2); 2597 ASSERT(args->length() == 2);
2528 2598
2529 // Load the two objects into registers and perform the comparison. 2599 // Load the two objects into registers and perform the comparison.
2530 Load(args->at(0)); 2600 Load(args->at(0));
2531 Load(args->at(1)); 2601 Load(args->at(1));
2532 __ pop(r0); 2602 frame_->Pop(r0);
2533 __ pop(r1); 2603 frame_->Pop(r1);
2534 __ cmp(r0, Operand(r1)); 2604 __ cmp(r0, Operand(r1));
2535 cc_reg_ = eq; 2605 cc_reg_ = eq;
2536 } 2606 }
2537 2607
2538 2608
2539 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { 2609 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
2540 if (CheckForInlineRuntimeCall(node)) return; 2610 if (CheckForInlineRuntimeCall(node)) return;
2541 2611
2542 ZoneList<Expression*>* args = node->arguments(); 2612 ZoneList<Expression*>* args = node->arguments();
2543 Comment cmnt(masm_, "[ CallRuntime"); 2613 Comment cmnt(masm_, "[ CallRuntime");
2544 Runtime::Function* function = node->function(); 2614 Runtime::Function* function = node->function();
2545 2615
2546 if (function != NULL) { 2616 if (function != NULL) {
2547 // Push the arguments ("left-to-right"). 2617 // Push the arguments ("left-to-right").
2548 for (int i = 0; i < args->length(); i++) Load(args->at(i)); 2618 for (int i = 0; i < args->length(); i++) Load(args->at(i));
2549 2619
2550 // Call the C runtime function. 2620 // Call the C runtime function.
2551 __ CallRuntime(function, args->length()); 2621 __ CallRuntime(function, args->length());
2552 __ push(r0); 2622 frame_->Push(r0);
2553 2623
2554 } else { 2624 } else {
2555 // Prepare stack for calling JS runtime function. 2625 // Prepare stack for calling JS runtime function.
2556 __ mov(r0, Operand(node->name())); 2626 __ mov(r0, Operand(node->name()));
2557 __ push(r0); 2627 frame_->Push(r0);
2558 // Push the builtins object found in the current global object. 2628 // Push the builtins object found in the current global object.
2559 __ ldr(r1, GlobalObject()); 2629 __ ldr(r1, GlobalObject());
2560 __ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset)); 2630 __ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset));
2561 __ push(r0); 2631 frame_->Push(r0);
2562 2632
2563 for (int i = 0; i < args->length(); i++) Load(args->at(i)); 2633 for (int i = 0; i < args->length(); i++) Load(args->at(i));
2564 2634
2565 // Call the JS runtime function. 2635 // Call the JS runtime function.
2566 Handle<Code> stub = ComputeCallInitialize(args->length()); 2636 Handle<Code> stub = ComputeCallInitialize(args->length());
2567 __ Call(stub, RelocInfo::CODE_TARGET); 2637 __ Call(stub, RelocInfo::CODE_TARGET);
2568 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2638 __ ldr(cp, frame_->Context());
2569 __ pop(); 2639 frame_->Pop();
2570 __ push(r0); 2640 frame_->Push(r0);
2571 } 2641 }
2572 } 2642 }
2573 2643
2574 2644
2575 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { 2645 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
2576 Comment cmnt(masm_, "[ UnaryOperation"); 2646 Comment cmnt(masm_, "[ UnaryOperation");
2577 2647
2578 Token::Value op = node->op(); 2648 Token::Value op = node->op();
2579 2649
2580 if (op == Token::NOT) { 2650 if (op == Token::NOT) {
(...skipping 11 matching lines...) Expand all
2592 Load(property->obj()); 2662 Load(property->obj());
2593 Load(property->key()); 2663 Load(property->key());
2594 __ mov(r0, Operand(1)); // not counting receiver 2664 __ mov(r0, Operand(1)); // not counting receiver
2595 __ InvokeBuiltin(Builtins::DELETE, CALL_JS); 2665 __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
2596 2666
2597 } else if (variable != NULL) { 2667 } else if (variable != NULL) {
2598 Slot* slot = variable->slot(); 2668 Slot* slot = variable->slot();
2599 if (variable->is_global()) { 2669 if (variable->is_global()) {
2600 LoadGlobal(); 2670 LoadGlobal();
2601 __ mov(r0, Operand(variable->name())); 2671 __ mov(r0, Operand(variable->name()));
2602 __ push(r0); 2672 frame_->Push(r0);
2603 __ mov(r0, Operand(1)); // not counting receiver 2673 __ mov(r0, Operand(1)); // not counting receiver
2604 __ InvokeBuiltin(Builtins::DELETE, CALL_JS); 2674 __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
2605 2675
2606 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 2676 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
2607 // lookup the context holding the named variable 2677 // lookup the context holding the named variable
2608 __ push(cp); 2678 frame_->Push(cp);
2609 __ mov(r0, Operand(variable->name())); 2679 __ mov(r0, Operand(variable->name()));
2610 __ push(r0); 2680 frame_->Push(r0);
2611 __ CallRuntime(Runtime::kLookupContext, 2); 2681 __ CallRuntime(Runtime::kLookupContext, 2);
2612 // r0: context 2682 // r0: context
2613 __ push(r0); 2683 frame_->Push(r0);
2614 __ mov(r0, Operand(variable->name())); 2684 __ mov(r0, Operand(variable->name()));
2615 __ push(r0); 2685 frame_->Push(r0);
2616 __ mov(r0, Operand(1)); // not counting receiver 2686 __ mov(r0, Operand(1)); // not counting receiver
2617 __ InvokeBuiltin(Builtins::DELETE, CALL_JS); 2687 __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
2618 2688
2619 } else { 2689 } else {
2620 // Default: Result of deleting non-global, not dynamically 2690 // Default: Result of deleting non-global, not dynamically
2621 // introduced variables is false. 2691 // introduced variables is false.
2622 __ mov(r0, Operand(Factory::false_value())); 2692 __ mov(r0, Operand(Factory::false_value()));
2623 } 2693 }
2624 2694
2625 } else { 2695 } else {
2626 // Default: Result of deleting expressions is true. 2696 // Default: Result of deleting expressions is true.
2627 Load(node->expression()); // may have side-effects 2697 Load(node->expression()); // may have side-effects
2628 __ pop(); 2698 frame_->Pop();
2629 __ mov(r0, Operand(Factory::true_value())); 2699 __ mov(r0, Operand(Factory::true_value()));
2630 } 2700 }
2631 __ push(r0); 2701 frame_->Push(r0);
2632 2702
2633 } else if (op == Token::TYPEOF) { 2703 } else if (op == Token::TYPEOF) {
2634 // Special case for loading the typeof expression; see comment on 2704 // Special case for loading the typeof expression; see comment on
2635 // LoadTypeofExpression(). 2705 // LoadTypeofExpression().
2636 LoadTypeofExpression(node->expression()); 2706 LoadTypeofExpression(node->expression());
2637 __ CallRuntime(Runtime::kTypeof, 1); 2707 __ CallRuntime(Runtime::kTypeof, 1);
2638 __ push(r0); // r0 has result 2708 frame_->Push(r0); // r0 has result
2639 2709
2640 } else { 2710 } else {
2641 Load(node->expression()); 2711 Load(node->expression());
2642 __ pop(r0); 2712 frame_->Pop(r0);
2643 switch (op) { 2713 switch (op) {
2644 case Token::NOT: 2714 case Token::NOT:
2645 case Token::DELETE: 2715 case Token::DELETE:
2646 case Token::TYPEOF: 2716 case Token::TYPEOF:
2647 UNREACHABLE(); // handled above 2717 UNREACHABLE(); // handled above
2648 break; 2718 break;
2649 2719
2650 case Token::SUB: { 2720 case Token::SUB: {
2651 UnarySubStub stub; 2721 UnarySubStub stub;
2652 __ CallStub(&stub); 2722 __ CallStub(&stub);
2653 break; 2723 break;
2654 } 2724 }
2655 2725
2656 case Token::BIT_NOT: { 2726 case Token::BIT_NOT: {
2657 // smi check 2727 // smi check
2658 Label smi_label; 2728 Label smi_label;
2659 Label continue_label; 2729 Label continue_label;
2660 __ tst(r0, Operand(kSmiTagMask)); 2730 __ tst(r0, Operand(kSmiTagMask));
2661 __ b(eq, &smi_label); 2731 __ b(eq, &smi_label);
2662 2732
2663 __ push(r0); 2733 frame_->Push(r0);
2664 __ mov(r0, Operand(0)); // not counting receiver 2734 __ mov(r0, Operand(0)); // not counting receiver
2665 __ InvokeBuiltin(Builtins::BIT_NOT, CALL_JS); 2735 __ InvokeBuiltin(Builtins::BIT_NOT, CALL_JS);
2666 2736
2667 __ b(&continue_label); 2737 __ b(&continue_label);
2668 __ bind(&smi_label); 2738 __ bind(&smi_label);
2669 __ mvn(r0, Operand(r0)); 2739 __ mvn(r0, Operand(r0));
2670 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag 2740 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag
2671 __ bind(&continue_label); 2741 __ bind(&continue_label);
2672 break; 2742 break;
2673 } 2743 }
2674 2744
2675 case Token::VOID: 2745 case Token::VOID:
2676 // since the stack top is cached in r0, popping and then 2746 // since the stack top is cached in r0, popping and then
2677 // pushing a value can be done by just writing to r0. 2747 // pushing a value can be done by just writing to r0.
2678 __ mov(r0, Operand(Factory::undefined_value())); 2748 __ mov(r0, Operand(Factory::undefined_value()));
2679 break; 2749 break;
2680 2750
2681 case Token::ADD: { 2751 case Token::ADD: {
2682 // Smi check. 2752 // Smi check.
2683 Label continue_label; 2753 Label continue_label;
2684 __ tst(r0, Operand(kSmiTagMask)); 2754 __ tst(r0, Operand(kSmiTagMask));
2685 __ b(eq, &continue_label); 2755 __ b(eq, &continue_label);
2686 __ push(r0); 2756 frame_->Push(r0);
2687 __ mov(r0, Operand(0)); // not counting receiver 2757 __ mov(r0, Operand(0)); // not counting receiver
2688 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); 2758 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
2689 __ bind(&continue_label); 2759 __ bind(&continue_label);
2690 break; 2760 break;
2691 } 2761 }
2692 default: 2762 default:
2693 UNREACHABLE(); 2763 UNREACHABLE();
2694 } 2764 }
2695 __ push(r0); // r0 has result 2765 frame_->Push(r0); // r0 has result
2696 } 2766 }
2697 } 2767 }
2698 2768
2699 2769
2700 void CodeGenerator::VisitCountOperation(CountOperation* node) { 2770 void CodeGenerator::VisitCountOperation(CountOperation* node) {
2701 Comment cmnt(masm_, "[ CountOperation"); 2771 Comment cmnt(masm_, "[ CountOperation");
2702 2772
2703 bool is_postfix = node->is_postfix(); 2773 bool is_postfix = node->is_postfix();
2704 bool is_increment = node->op() == Token::INC; 2774 bool is_increment = node->op() == Token::INC;
2705 2775
2706 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); 2776 Variable* var = node->expression()->AsVariableProxy()->AsVariable();
2707 bool is_const = (var != NULL && var->mode() == Variable::CONST); 2777 bool is_const = (var != NULL && var->mode() == Variable::CONST);
2708 2778
2709 // Postfix: Make room for the result. 2779 // Postfix: Make room for the result.
2710 if (is_postfix) { 2780 if (is_postfix) {
2711 __ mov(r0, Operand(0)); 2781 __ mov(r0, Operand(0));
2712 __ push(r0); 2782 frame_->Push(r0);
2713 } 2783 }
2714 2784
2715 { Reference target(this, node->expression()); 2785 { Reference target(this, node->expression());
2716 if (target.is_illegal()) return; 2786 if (target.is_illegal()) return;
2717 target.GetValue(NOT_INSIDE_TYPEOF); 2787 target.GetValue(NOT_INSIDE_TYPEOF);
2718 __ pop(r0); 2788 frame_->Pop(r0);
2719 2789
2720 Label slow, exit; 2790 Label slow, exit;
2721 2791
2722 // Load the value (1) into register r1. 2792 // Load the value (1) into register r1.
2723 __ mov(r1, Operand(Smi::FromInt(1))); 2793 __ mov(r1, Operand(Smi::FromInt(1)));
2724 2794
2725 // Check for smi operand. 2795 // Check for smi operand.
2726 __ tst(r0, Operand(kSmiTagMask)); 2796 __ tst(r0, Operand(kSmiTagMask));
2727 __ b(ne, &slow); 2797 __ b(ne, &slow);
2728 2798
2729 // Postfix: Store the old value as the result. 2799 // Postfix: Store the old value as the result.
2730 if (is_postfix) __ str(r0, MemOperand(sp, target.size() * kPointerSize)); 2800 if (is_postfix) {
2801 __ str(r0, frame_->Element(target.size()));
2802 }
2731 2803
2732 // Perform optimistic increment/decrement. 2804 // Perform optimistic increment/decrement.
2733 if (is_increment) { 2805 if (is_increment) {
2734 __ add(r0, r0, Operand(r1), SetCC); 2806 __ add(r0, r0, Operand(r1), SetCC);
2735 } else { 2807 } else {
2736 __ sub(r0, r0, Operand(r1), SetCC); 2808 __ sub(r0, r0, Operand(r1), SetCC);
2737 } 2809 }
2738 2810
2739 // If the increment/decrement didn't overflow, we're done. 2811 // If the increment/decrement didn't overflow, we're done.
2740 __ b(vc, &exit); 2812 __ b(vc, &exit);
2741 2813
2742 // Revert optimistic increment/decrement. 2814 // Revert optimistic increment/decrement.
2743 if (is_increment) { 2815 if (is_increment) {
2744 __ sub(r0, r0, Operand(r1)); 2816 __ sub(r0, r0, Operand(r1));
2745 } else { 2817 } else {
2746 __ add(r0, r0, Operand(r1)); 2818 __ add(r0, r0, Operand(r1));
2747 } 2819 }
2748 2820
2749 // Slow case: Convert to number. 2821 // Slow case: Convert to number.
2750 __ bind(&slow); 2822 __ bind(&slow);
2751 2823
2752 // Postfix: Convert the operand to a number and store it as the result. 2824 // Postfix: Convert the operand to a number and store it as the result.
2753 if (is_postfix) { 2825 if (is_postfix) {
2754 InvokeBuiltinStub stub(InvokeBuiltinStub::ToNumber, 2); 2826 InvokeBuiltinStub stub(InvokeBuiltinStub::ToNumber, 2);
2755 __ CallStub(&stub); 2827 __ CallStub(&stub);
2756 // Store to result (on the stack). 2828 // Store to result (on the stack).
2757 __ str(r0, MemOperand(sp, target.size() * kPointerSize)); 2829 __ str(r0, frame_->Element(target.size()));
2758 } 2830 }
2759 2831
2760 // Compute the new value by calling the right JavaScript native. 2832 // Compute the new value by calling the right JavaScript native.
2761 if (is_increment) { 2833 if (is_increment) {
2762 InvokeBuiltinStub stub(InvokeBuiltinStub::Inc, 1); 2834 InvokeBuiltinStub stub(InvokeBuiltinStub::Inc, 1);
2763 __ CallStub(&stub); 2835 __ CallStub(&stub);
2764 } else { 2836 } else {
2765 InvokeBuiltinStub stub(InvokeBuiltinStub::Dec, 1); 2837 InvokeBuiltinStub stub(InvokeBuiltinStub::Dec, 1);
2766 __ CallStub(&stub); 2838 __ CallStub(&stub);
2767 } 2839 }
2768 2840
2769 // Store the new value in the target if not const. 2841 // Store the new value in the target if not const.
2770 __ bind(&exit); 2842 __ bind(&exit);
2771 __ push(r0); 2843 frame_->Push(r0);
2772 if (!is_const) target.SetValue(NOT_CONST_INIT); 2844 if (!is_const) target.SetValue(NOT_CONST_INIT);
2773 } 2845 }
2774 2846
2775 // Postfix: Discard the new value and use the old. 2847 // Postfix: Discard the new value and use the old.
2776 if (is_postfix) __ pop(r0); 2848 if (is_postfix) frame_->Pop(r0);
2777 } 2849 }
2778 2850
2779 2851
2780 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { 2852 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
2781 Comment cmnt(masm_, "[ BinaryOperation"); 2853 Comment cmnt(masm_, "[ BinaryOperation");
2782 Token::Value op = node->op(); 2854 Token::Value op = node->op();
2783 2855
2784 // According to ECMA-262 section 11.11, page 58, the binary logical 2856 // According to ECMA-262 section 11.11, page 58, the binary logical
2785 // operators must yield the result of one of the two expressions 2857 // operators must yield the result of one of the two expressions
2786 // before any ToBoolean() conversions. This means that the value 2858 // before any ToBoolean() conversions. This means that the value
(...skipping 20 matching lines...) Expand all
2807 __ bind(&is_true); 2879 __ bind(&is_true);
2808 LoadCondition(node->right(), 2880 LoadCondition(node->right(),
2809 NOT_INSIDE_TYPEOF, 2881 NOT_INSIDE_TYPEOF,
2810 true_target(), 2882 true_target(),
2811 false_target(), 2883 false_target(),
2812 false); 2884 false);
2813 2885
2814 } else { 2886 } else {
2815 Label pop_and_continue, exit; 2887 Label pop_and_continue, exit;
2816 2888
2817 __ ldr(r0, MemOperand(sp, 0)); // dup the stack top 2889 __ ldr(r0, frame_->Top()); // dup the stack top
2818 __ push(r0); 2890 frame_->Push(r0);
2819 // Avoid popping the result if it converts to 'false' using the 2891 // Avoid popping the result if it converts to 'false' using the
2820 // standard ToBoolean() conversion as described in ECMA-262, 2892 // standard ToBoolean() conversion as described in ECMA-262,
2821 // section 9.2, page 30. 2893 // section 9.2, page 30.
2822 ToBoolean(&pop_and_continue, &exit); 2894 ToBoolean(&pop_and_continue, &exit);
2823 Branch(false, &exit); 2895 Branch(false, &exit);
2824 2896
2825 // Pop the result of evaluating the first part. 2897 // Pop the result of evaluating the first part.
2826 __ bind(&pop_and_continue); 2898 __ bind(&pop_and_continue);
2827 __ pop(r0); 2899 frame_->Pop(r0);
2828 2900
2829 // Evaluate right side expression. 2901 // Evaluate right side expression.
2830 __ bind(&is_true); 2902 __ bind(&is_true);
2831 Load(node->right()); 2903 Load(node->right());
2832 2904
2833 // Exit (always with a materialized value). 2905 // Exit (always with a materialized value).
2834 __ bind(&exit); 2906 __ bind(&exit);
2835 } 2907 }
2836 2908
2837 } else if (op == Token::OR) { 2909 } else if (op == Token::OR) {
(...skipping 10 matching lines...) Expand all
2848 __ bind(&is_false); 2920 __ bind(&is_false);
2849 LoadCondition(node->right(), 2921 LoadCondition(node->right(),
2850 NOT_INSIDE_TYPEOF, 2922 NOT_INSIDE_TYPEOF,
2851 true_target(), 2923 true_target(),
2852 false_target(), 2924 false_target(),
2853 false); 2925 false);
2854 2926
2855 } else { 2927 } else {
2856 Label pop_and_continue, exit; 2928 Label pop_and_continue, exit;
2857 2929
2858 __ ldr(r0, MemOperand(sp, 0)); 2930 __ ldr(r0, frame_->Top());
2859 __ push(r0); 2931 frame_->Push(r0);
2860 // Avoid popping the result if it converts to 'true' using the 2932 // Avoid popping the result if it converts to 'true' using the
2861 // standard ToBoolean() conversion as described in ECMA-262, 2933 // standard ToBoolean() conversion as described in ECMA-262,
2862 // section 9.2, page 30. 2934 // section 9.2, page 30.
2863 ToBoolean(&exit, &pop_and_continue); 2935 ToBoolean(&exit, &pop_and_continue);
2864 Branch(true, &exit); 2936 Branch(true, &exit);
2865 2937
2866 // Pop the result of evaluating the first part. 2938 // Pop the result of evaluating the first part.
2867 __ bind(&pop_and_continue); 2939 __ bind(&pop_and_continue);
2868 __ pop(r0); 2940 frame_->Pop(r0);
2869 2941
2870 // Evaluate right side expression. 2942 // Evaluate right side expression.
2871 __ bind(&is_false); 2943 __ bind(&is_false);
2872 Load(node->right()); 2944 Load(node->right());
2873 2945
2874 // Exit (always with a materialized value). 2946 // Exit (always with a materialized value).
2875 __ bind(&exit); 2947 __ bind(&exit);
2876 } 2948 }
2877 2949
2878 } else { 2950 } else {
2879 // Optimize for the case where (at least) one of the expressions 2951 // Optimize for the case where (at least) one of the expressions
2880 // is a literal small integer. 2952 // is a literal small integer.
2881 Literal* lliteral = node->left()->AsLiteral(); 2953 Literal* lliteral = node->left()->AsLiteral();
2882 Literal* rliteral = node->right()->AsLiteral(); 2954 Literal* rliteral = node->right()->AsLiteral();
2883 2955
2884 if (rliteral != NULL && rliteral->handle()->IsSmi()) { 2956 if (rliteral != NULL && rliteral->handle()->IsSmi()) {
2885 Load(node->left()); 2957 Load(node->left());
2886 SmiOperation(node->op(), rliteral->handle(), false); 2958 SmiOperation(node->op(), rliteral->handle(), false);
2887 2959
2888 } else if (lliteral != NULL && lliteral->handle()->IsSmi()) { 2960 } else if (lliteral != NULL && lliteral->handle()->IsSmi()) {
2889 Load(node->right()); 2961 Load(node->right());
2890 SmiOperation(node->op(), lliteral->handle(), true); 2962 SmiOperation(node->op(), lliteral->handle(), true);
2891 2963
2892 } else { 2964 } else {
2893 Load(node->left()); 2965 Load(node->left());
2894 Load(node->right()); 2966 Load(node->right());
2895 GenericBinaryOperation(node->op()); 2967 GenericBinaryOperation(node->op());
2896 } 2968 }
2897 __ push(r0); 2969 frame_->Push(r0);
2898 } 2970 }
2899 } 2971 }
2900 2972
2901 2973
2902 void CodeGenerator::VisitThisFunction(ThisFunction* node) { 2974 void CodeGenerator::VisitThisFunction(ThisFunction* node) {
2903 __ ldr(r0, FunctionOperand()); 2975 __ ldr(r0, frame_->Function());
2904 __ push(r0); 2976 frame_->Push(r0);
2905 } 2977 }
2906 2978
2907 2979
2908 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { 2980 void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
2909 Comment cmnt(masm_, "[ CompareOperation"); 2981 Comment cmnt(masm_, "[ CompareOperation");
2910 2982
2911 // Get the expressions from the node. 2983 // Get the expressions from the node.
2912 Expression* left = node->left(); 2984 Expression* left = node->left();
2913 Expression* right = node->right(); 2985 Expression* right = node->right();
2914 Token::Value op = node->op(); 2986 Token::Value op = node->op();
2915 2987
2916 // NOTE: To make null checks efficient, we check if either left or 2988 // To make null checks efficient, we check if either left or right is the
2917 // right is the literal 'null'. If so, we optimize the code by 2989 // literal 'null'. If so, we optimize the code by inlining a null check
2918 // inlining a null check instead of calling the (very) general 2990 // instead of calling the (very) general runtime routine for checking
2919 // runtime routine for checking equality. 2991 // equality.
2920
2921 if (op == Token::EQ || op == Token::EQ_STRICT) { 2992 if (op == Token::EQ || op == Token::EQ_STRICT) {
2922 bool left_is_null = 2993 bool left_is_null =
2923 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); 2994 left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
2924 bool right_is_null = 2995 bool right_is_null =
2925 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); 2996 right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
2926 // The 'null' value is only equal to 'null' or 'undefined'. 2997 // The 'null' value can only be equal to 'null' or 'undefined'.
2927 if (left_is_null || right_is_null) { 2998 if (left_is_null || right_is_null) {
2928 Load(left_is_null ? right : left); 2999 Load(left_is_null ? right : left);
2929 Label exit, undetectable; 3000 frame_->Pop(r0);
2930 __ pop(r0);
2931 __ cmp(r0, Operand(Factory::null_value())); 3001 __ cmp(r0, Operand(Factory::null_value()));
2932 3002
2933 // The 'null' value is only equal to 'undefined' if using 3003 // The 'null' value is only equal to 'undefined' if using non-strict
2934 // non-strict comparisons. 3004 // comparisons.
2935 if (op != Token::EQ_STRICT) { 3005 if (op != Token::EQ_STRICT) {
2936 __ b(eq, &exit); 3006 __ b(eq, true_target());
3007
2937 __ cmp(r0, Operand(Factory::undefined_value())); 3008 __ cmp(r0, Operand(Factory::undefined_value()));
3009 __ b(eq, true_target());
2938 3010
2939 // NOTE: it can be undetectable object.
2940 __ b(eq, &exit);
2941 __ tst(r0, Operand(kSmiTagMask)); 3011 __ tst(r0, Operand(kSmiTagMask));
3012 __ b(eq, false_target());
2942 3013
2943 __ b(ne, &undetectable); 3014 // It can be an undetectable object.
2944 __ b(false_target()); 3015 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
2945 3016 __ ldrb(r0, FieldMemOperand(r0, Map::kBitFieldOffset));
2946 __ bind(&undetectable); 3017 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable));
2947 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 3018 __ cmp(r0, Operand(1 << Map::kIsUndetectable));
2948 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
2949 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
2950 __ cmp(r2, Operand(1 << Map::kIsUndetectable));
2951 } 3019 }
2952 3020
2953 __ bind(&exit);
2954
2955 cc_reg_ = eq; 3021 cc_reg_ = eq;
2956 return; 3022 return;
2957 } 3023 }
2958 } 3024 }
2959 3025
2960 3026 // To make typeof testing for natives implemented in JavaScript really
2961 // NOTE: To make typeof testing for natives implemented in 3027 // efficient, we generate special code for expressions of the form:
2962 // JavaScript really efficient, we generate special code for 3028 // 'typeof <expression> == <string>'.
2963 // expressions of the form: 'typeof <expression> == <string>'.
2964
2965 UnaryOperation* operation = left->AsUnaryOperation(); 3029 UnaryOperation* operation = left->AsUnaryOperation();
2966 if ((op == Token::EQ || op == Token::EQ_STRICT) && 3030 if ((op == Token::EQ || op == Token::EQ_STRICT) &&
2967 (operation != NULL && operation->op() == Token::TYPEOF) && 3031 (operation != NULL && operation->op() == Token::TYPEOF) &&
2968 (right->AsLiteral() != NULL && 3032 (right->AsLiteral() != NULL &&
2969 right->AsLiteral()->handle()->IsString())) { 3033 right->AsLiteral()->handle()->IsString())) {
2970 Handle<String> check(String::cast(*right->AsLiteral()->handle())); 3034 Handle<String> check(String::cast(*right->AsLiteral()->handle()));
2971 3035
2972 // Load the operand, move it to register r1. 3036 // Load the operand, move it to register r1.
2973 LoadTypeofExpression(operation->expression()); 3037 LoadTypeofExpression(operation->expression());
2974 __ pop(r1); 3038 frame_->Pop(r1);
2975 3039
2976 if (check->Equals(Heap::number_symbol())) { 3040 if (check->Equals(Heap::number_symbol())) {
2977 __ tst(r1, Operand(kSmiTagMask)); 3041 __ tst(r1, Operand(kSmiTagMask));
2978 __ b(eq, true_target()); 3042 __ b(eq, true_target());
2979 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 3043 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
2980 __ cmp(r1, Operand(Factory::heap_number_map())); 3044 __ cmp(r1, Operand(Factory::heap_number_map()));
2981 cc_reg_ = eq; 3045 cc_reg_ = eq;
2982 3046
2983 } else if (check->Equals(Heap::string_symbol())) { 3047 } else if (check->Equals(Heap::string_symbol())) {
2984 __ tst(r1, Operand(kSmiTagMask)); 3048 __ tst(r1, Operand(kSmiTagMask));
2985 __ b(eq, false_target()); 3049 __ b(eq, false_target());
2986 3050
2987 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 3051 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
2988 3052
2989 // NOTE: it might be an undetectable string object 3053 // It can be an undetectable string object.
2990 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset)); 3054 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
2991 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable)); 3055 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
2992 __ cmp(r2, Operand(1 << Map::kIsUndetectable)); 3056 __ cmp(r2, Operand(1 << Map::kIsUndetectable));
2993 __ b(eq, false_target()); 3057 __ b(eq, false_target());
2994 3058
2995 __ ldrb(r2, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 3059 __ ldrb(r2, FieldMemOperand(r1, Map::kInstanceTypeOffset));
2996 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE)); 3060 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE));
2997 cc_reg_ = lt; 3061 cc_reg_ = lt;
2998 3062
2999 } else if (check->Equals(Heap::boolean_symbol())) { 3063 } else if (check->Equals(Heap::boolean_symbol())) {
3000 __ cmp(r1, Operand(Factory::true_value())); 3064 __ cmp(r1, Operand(Factory::true_value()));
3001 __ b(eq, true_target()); 3065 __ b(eq, true_target());
3002 __ cmp(r1, Operand(Factory::false_value())); 3066 __ cmp(r1, Operand(Factory::false_value()));
3003 cc_reg_ = eq; 3067 cc_reg_ = eq;
3004 3068
3005 } else if (check->Equals(Heap::undefined_symbol())) { 3069 } else if (check->Equals(Heap::undefined_symbol())) {
3006 __ cmp(r1, Operand(Factory::undefined_value())); 3070 __ cmp(r1, Operand(Factory::undefined_value()));
3007 __ b(eq, true_target()); 3071 __ b(eq, true_target());
3008 3072
3009 __ tst(r1, Operand(kSmiTagMask)); 3073 __ tst(r1, Operand(kSmiTagMask));
3010 __ b(eq, false_target()); 3074 __ b(eq, false_target());
3011 3075
3012 // NOTE: it can be undetectable object. 3076 // It can be an undetectable object.
3013 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 3077 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
3014 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset)); 3078 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
3015 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable)); 3079 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
3016 __ cmp(r2, Operand(1 << Map::kIsUndetectable)); 3080 __ cmp(r2, Operand(1 << Map::kIsUndetectable));
3017 3081
3018 cc_reg_ = eq; 3082 cc_reg_ = eq;
3019 3083
3020 } else if (check->Equals(Heap::function_symbol())) { 3084 } else if (check->Equals(Heap::function_symbol())) {
3021 __ tst(r1, Operand(kSmiTagMask)); 3085 __ tst(r1, Operand(kSmiTagMask));
3022 __ b(eq, false_target()); 3086 __ b(eq, false_target());
3023 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 3087 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
3024 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 3088 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
3025 __ cmp(r1, Operand(JS_FUNCTION_TYPE)); 3089 __ cmp(r1, Operand(JS_FUNCTION_TYPE));
3026 cc_reg_ = eq; 3090 cc_reg_ = eq;
3027 3091
3028 } else if (check->Equals(Heap::object_symbol())) { 3092 } else if (check->Equals(Heap::object_symbol())) {
3029 __ tst(r1, Operand(kSmiTagMask)); 3093 __ tst(r1, Operand(kSmiTagMask));
3030 __ b(eq, false_target()); 3094 __ b(eq, false_target());
3031 3095
3032 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 3096 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
3033 __ cmp(r1, Operand(Factory::null_value())); 3097 __ cmp(r1, Operand(Factory::null_value()));
3034 __ b(eq, true_target()); 3098 __ b(eq, true_target());
3035 3099
3036 // NOTE: it might be an undetectable object. 3100 // It can be an undetectable object.
3037 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); 3101 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
3038 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); 3102 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
3039 __ cmp(r1, Operand(1 << Map::kIsUndetectable)); 3103 __ cmp(r1, Operand(1 << Map::kIsUndetectable));
3040 __ b(eq, false_target()); 3104 __ b(eq, false_target());
3041 3105
3042 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 3106 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
3043 __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE)); 3107 __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE));
3044 __ b(lt, false_target()); 3108 __ b(lt, false_target());
3045 __ cmp(r2, Operand(LAST_JS_OBJECT_TYPE)); 3109 __ cmp(r2, Operand(LAST_JS_OBJECT_TYPE));
3046 cc_reg_ = le; 3110 cc_reg_ = le;
3047 3111
3048 } else { 3112 } else {
3049 // Uncommon case: Typeof testing against a string literal that 3113 // Uncommon case: typeof testing against a string literal that is
3050 // is never returned from the typeof operator. 3114 // never returned from the typeof operator.
3051 __ b(false_target()); 3115 __ b(false_target());
3052 } 3116 }
3053 return; 3117 return;
3054 } 3118 }
3055 3119
3056 Load(left); 3120 Load(left);
3057 Load(right); 3121 Load(right);
3058 switch (op) { 3122 switch (op) {
3059 case Token::EQ: 3123 case Token::EQ:
3060 Comparison(eq, false); 3124 Comparison(eq, false);
(...skipping 15 matching lines...) Expand all
3076 Comparison(ge); 3140 Comparison(ge);
3077 break; 3141 break;
3078 3142
3079 case Token::EQ_STRICT: 3143 case Token::EQ_STRICT:
3080 Comparison(eq, true); 3144 Comparison(eq, true);
3081 break; 3145 break;
3082 3146
3083 case Token::IN: 3147 case Token::IN:
3084 __ mov(r0, Operand(1)); // not counting receiver 3148 __ mov(r0, Operand(1)); // not counting receiver
3085 __ InvokeBuiltin(Builtins::IN, CALL_JS); 3149 __ InvokeBuiltin(Builtins::IN, CALL_JS);
3086 __ push(r0); 3150 frame_->Push(r0);
3087 break; 3151 break;
3088 3152
3089 case Token::INSTANCEOF: 3153 case Token::INSTANCEOF:
3090 __ mov(r0, Operand(1)); // not counting receiver 3154 __ mov(r0, Operand(1)); // not counting receiver
3091 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_JS); 3155 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_JS);
3092 __ tst(r0, Operand(r0)); 3156 __ tst(r0, Operand(r0));
3093 cc_reg_ = eq; 3157 cc_reg_ = eq;
3094 break; 3158 break;
3095 3159
3096 default: 3160 default:
3097 UNREACHABLE(); 3161 UNREACHABLE();
3098 } 3162 }
3099 } 3163 }
3100 3164
3101 3165
3102 void CodeGenerator::RecordStatementPosition(Node* node) { 3166 void CodeGenerator::RecordStatementPosition(Node* node) {
3103 if (FLAG_debug_info) { 3167 if (FLAG_debug_info) {
3104 int statement_pos = node->statement_pos(); 3168 int statement_pos = node->statement_pos();
3105 if (statement_pos == RelocInfo::kNoPosition) return; 3169 if (statement_pos == RelocInfo::kNoPosition) return;
3106 __ RecordStatementPosition(statement_pos); 3170 __ RecordStatementPosition(statement_pos);
3107 } 3171 }
3108 } 3172 }
3109 3173
3110 3174
3111 void CodeGenerator::EnterJSFrame() {
3112 #if defined(DEBUG)
3113 { Label done, fail;
3114 __ tst(r1, Operand(kSmiTagMask));
3115 __ b(eq, &fail);
3116 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
3117 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
3118 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
3119 __ b(eq, &done);
3120 __ bind(&fail);
3121 __ stop("CodeGenerator::EnterJSFrame - r1 not a function");
3122 __ bind(&done);
3123 }
3124 #endif // DEBUG
3125
3126 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
3127 __ add(fp, sp, Operand(2 * kPointerSize)); // Adjust FP to point to saved FP.
3128 }
3129
3130
3131 void CodeGenerator::ExitJSFrame() {
3132 // Drop the execution stack down to the frame pointer and restore the caller
3133 // frame pointer and return address.
3134 __ mov(sp, fp);
3135 __ ldm(ia_w, sp, fp.bit() | lr.bit());
3136 }
3137
3138
3139 #undef __ 3175 #undef __
3140 #define __ masm-> 3176 #define __ masm->
3141 3177
3142 Handle<String> Reference::GetName() { 3178 Handle<String> Reference::GetName() {
3143 ASSERT(type_ == NAMED); 3179 ASSERT(type_ == NAMED);
3144 Property* property = expression_->AsProperty(); 3180 Property* property = expression_->AsProperty();
3145 if (property == NULL) { 3181 if (property == NULL) {
3146 // Global variable reference treated as a named property reference. 3182 // Global variable reference treated as a named property reference.
3147 VariableProxy* proxy = expression_->AsVariableProxy(); 3183 VariableProxy* proxy = expression_->AsVariableProxy();
3148 ASSERT(proxy->AsVariable() != NULL); 3184 ASSERT(proxy->AsVariable() != NULL);
3149 ASSERT(proxy->AsVariable()->is_global()); 3185 ASSERT(proxy->AsVariable()->is_global());
3150 return proxy->name(); 3186 return proxy->name();
3151 } else { 3187 } else {
3152 Literal* raw_name = property->key()->AsLiteral(); 3188 Literal* raw_name = property->key()->AsLiteral();
3153 ASSERT(raw_name != NULL); 3189 ASSERT(raw_name != NULL);
3154 return Handle<String>(String::cast(*raw_name->handle())); 3190 return Handle<String>(String::cast(*raw_name->handle()));
3155 } 3191 }
3156 } 3192 }
3157 3193
3158 3194
3159 void Reference::GetValue(TypeofState typeof_state) { 3195 void Reference::GetValue(TypeofState typeof_state) {
3160 ASSERT(!is_illegal()); 3196 ASSERT(!is_illegal());
3161 ASSERT(!cgen_->has_cc()); 3197 ASSERT(!cgen_->has_cc());
3162 MacroAssembler* masm = cgen_->masm(); 3198 MacroAssembler* masm = cgen_->masm();
3199 VirtualFrame* frame = cgen_->frame();
3163 Property* property = expression_->AsProperty(); 3200 Property* property = expression_->AsProperty();
3164 if (property != NULL) { 3201 if (property != NULL) {
3165 __ RecordPosition(property->position()); 3202 __ RecordPosition(property->position());
3166 } 3203 }
3167 3204
3168 switch (type_) { 3205 switch (type_) {
3169 case SLOT: { 3206 case SLOT: {
3170 Comment cmnt(masm, "[ Load from Slot"); 3207 Comment cmnt(masm, "[ Load from Slot");
3171 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 3208 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
3172 ASSERT(slot != NULL); 3209 ASSERT(slot != NULL);
(...skipping 13 matching lines...) Expand all
3186 __ mov(r2, Operand(name)); 3223 __ mov(r2, Operand(name));
3187 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 3224 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
3188 3225
3189 Variable* var = expression_->AsVariableProxy()->AsVariable(); 3226 Variable* var = expression_->AsVariableProxy()->AsVariable();
3190 if (var != NULL) { 3227 if (var != NULL) {
3191 ASSERT(var->is_global()); 3228 ASSERT(var->is_global());
3192 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); 3229 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
3193 } else { 3230 } else {
3194 __ Call(ic, RelocInfo::CODE_TARGET); 3231 __ Call(ic, RelocInfo::CODE_TARGET);
3195 } 3232 }
3196 __ push(r0); 3233 frame->Push(r0);
3197 break; 3234 break;
3198 } 3235 }
3199 3236
3200 case KEYED: { 3237 case KEYED: {
3201 // TODO(1241834): Make sure that this it is safe to ignore the 3238 // TODO(1241834): Make sure that this it is safe to ignore the
3202 // distinction between expressions in a typeof and not in a typeof. 3239 // distinction between expressions in a typeof and not in a typeof.
3203 Comment cmnt(masm, "[ Load from keyed Property"); 3240 Comment cmnt(masm, "[ Load from keyed Property");
3204 ASSERT(property != NULL); 3241 ASSERT(property != NULL);
3205 // TODO(1224671): Implement inline caching for keyed loads as on ia32. 3242 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
3206 GetPropertyStub stub; 3243
3207 __ CallStub(&stub); 3244 Variable* var = expression_->AsVariableProxy()->AsVariable();
3208 __ push(r0); 3245 if (var != NULL) {
3246 ASSERT(var->is_global());
3247 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
3248 } else {
3249 __ Call(ic, RelocInfo::CODE_TARGET);
3250 }
3251 frame->Push(r0);
3209 break; 3252 break;
3210 } 3253 }
3211 3254
3212 default: 3255 default:
3213 UNREACHABLE(); 3256 UNREACHABLE();
3214 } 3257 }
3215 } 3258 }
3216 3259
3217 3260
3218 void Reference::SetValue(InitState init_state) { 3261 void Reference::SetValue(InitState init_state) {
3219 ASSERT(!is_illegal()); 3262 ASSERT(!is_illegal());
3220 ASSERT(!cgen_->has_cc()); 3263 ASSERT(!cgen_->has_cc());
3221 MacroAssembler* masm = cgen_->masm(); 3264 MacroAssembler* masm = cgen_->masm();
3265 VirtualFrame* frame = cgen_->frame();
3222 Property* property = expression_->AsProperty(); 3266 Property* property = expression_->AsProperty();
3223 if (property != NULL) { 3267 if (property != NULL) {
3224 __ RecordPosition(property->position()); 3268 __ RecordPosition(property->position());
3225 } 3269 }
3226 3270
3227 switch (type_) { 3271 switch (type_) {
3228 case SLOT: { 3272 case SLOT: {
3229 Comment cmnt(masm, "[ Store to Slot"); 3273 Comment cmnt(masm, "[ Store to Slot");
3230 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 3274 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
3231 ASSERT(slot != NULL); 3275 ASSERT(slot != NULL);
3232 if (slot->type() == Slot::LOOKUP) { 3276 if (slot->type() == Slot::LOOKUP) {
3233 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 3277 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
3234 3278
3235 // For now, just do a runtime call. 3279 // For now, just do a runtime call.
3236 __ push(cp); 3280 frame->Push(cp);
3237 __ mov(r0, Operand(slot->var()->name())); 3281 __ mov(r0, Operand(slot->var()->name()));
3238 __ push(r0); 3282 frame->Push(r0);
3239 3283
3240 if (init_state == CONST_INIT) { 3284 if (init_state == CONST_INIT) {
3241 // Same as the case for a normal store, but ignores attribute 3285 // Same as the case for a normal store, but ignores attribute
3242 // (e.g. READ_ONLY) of context slot so that we can initialize 3286 // (e.g. READ_ONLY) of context slot so that we can initialize
3243 // const properties (introduced via eval("const foo = (some 3287 // const properties (introduced via eval("const foo = (some
3244 // expr);")). Also, uses the current function context instead of 3288 // expr);")). Also, uses the current function context instead of
3245 // the top context. 3289 // the top context.
3246 // 3290 //
3247 // Note that we must declare the foo upon entry of eval(), via a 3291 // Note that we must declare the foo upon entry of eval(), via a
3248 // context slot declaration, but we cannot initialize it at the 3292 // context slot declaration, but we cannot initialize it at the
3249 // same time, because the const declaration may be at the end of 3293 // same time, because the const declaration may be at the end of
3250 // the eval code (sigh...) and the const variable may have been 3294 // the eval code (sigh...) and the const variable may have been
3251 // used before (where its value is 'undefined'). Thus, we can only 3295 // used before (where its value is 'undefined'). Thus, we can only
3252 // do the initialization when we actually encounter the expression 3296 // do the initialization when we actually encounter the expression
3253 // and when the expression operands are defined and valid, and 3297 // and when the expression operands are defined and valid, and
3254 // thus we need the split into 2 operations: declaration of the 3298 // thus we need the split into 2 operations: declaration of the
3255 // context slot followed by initialization. 3299 // context slot followed by initialization.
3256 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 3300 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
3257 } else { 3301 } else {
3258 __ CallRuntime(Runtime::kStoreContextSlot, 3); 3302 __ CallRuntime(Runtime::kStoreContextSlot, 3);
3259 } 3303 }
3260 // Storing a variable must keep the (new) value on the expression 3304 // Storing a variable must keep the (new) value on the expression
3261 // stack. This is necessary for compiling assignment expressions. 3305 // stack. This is necessary for compiling assignment expressions.
3262 __ push(r0); 3306 frame->Push(r0);
3263 3307
3264 } else { 3308 } else {
3265 ASSERT(slot->var()->mode() != Variable::DYNAMIC); 3309 ASSERT(slot->var()->mode() != Variable::DYNAMIC);
3266 3310
3267 Label exit; 3311 Label exit;
3268 if (init_state == CONST_INIT) { 3312 if (init_state == CONST_INIT) {
3269 ASSERT(slot->var()->mode() == Variable::CONST); 3313 ASSERT(slot->var()->mode() == Variable::CONST);
3270 // Only the first const initialization must be executed (the slot 3314 // Only the first const initialization must be executed (the slot
3271 // still contains 'the hole' value). When the assignment is 3315 // still contains 'the hole' value). When the assignment is
3272 // executed, the code is identical to a normal store (see below). 3316 // executed, the code is identical to a normal store (see below).
3273 Comment cmnt(masm, "[ Init const"); 3317 Comment cmnt(masm, "[ Init const");
3274 __ ldr(r2, cgen_->SlotOperand(slot, r2)); 3318 __ ldr(r2, cgen_->SlotOperand(slot, r2));
3275 __ cmp(r2, Operand(Factory::the_hole_value())); 3319 __ cmp(r2, Operand(Factory::the_hole_value()));
3276 __ b(ne, &exit); 3320 __ b(ne, &exit);
3277 } 3321 }
3278 3322
3279 // We must execute the store. Storing a variable must keep the 3323 // We must execute the store. Storing a variable must keep the
3280 // (new) value on the stack. This is necessary for compiling 3324 // (new) value on the stack. This is necessary for compiling
3281 // assignment expressions. 3325 // assignment expressions.
3282 // 3326 //
3283 // Note: We will reach here even with slot->var()->mode() == 3327 // Note: We will reach here even with slot->var()->mode() ==
3284 // Variable::CONST because of const declarations which will 3328 // Variable::CONST because of const declarations which will
3285 // initialize consts to 'the hole' value and by doing so, end up 3329 // initialize consts to 'the hole' value and by doing so, end up
3286 // calling this code. r2 may be loaded with context; used below in 3330 // calling this code. r2 may be loaded with context; used below in
3287 // RecordWrite. 3331 // RecordWrite.
3288 __ pop(r0); 3332 frame->Pop(r0);
3289 __ str(r0, cgen_->SlotOperand(slot, r2)); 3333 __ str(r0, cgen_->SlotOperand(slot, r2));
3290 __ push(r0); 3334 frame->Push(r0);
3291 if (slot->type() == Slot::CONTEXT) { 3335 if (slot->type() == Slot::CONTEXT) {
3292 // Skip write barrier if the written value is a smi. 3336 // Skip write barrier if the written value is a smi.
3293 __ tst(r0, Operand(kSmiTagMask)); 3337 __ tst(r0, Operand(kSmiTagMask));
3294 __ b(eq, &exit); 3338 __ b(eq, &exit);
3295 // r2 is loaded with context when calling SlotOperand above. 3339 // r2 is loaded with context when calling SlotOperand above.
3296 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 3340 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
3297 __ mov(r3, Operand(offset)); 3341 __ mov(r3, Operand(offset));
3298 __ RecordWrite(r2, r3, r1); 3342 __ RecordWrite(r2, r3, r1);
3299 } 3343 }
3300 // If we definitely did not jump over the assignment, we do not need 3344 // If we definitely did not jump over the assignment, we do not need
3301 // to bind the exit label. Doing so can defeat peephole 3345 // to bind the exit label. Doing so can defeat peephole
3302 // optimization. 3346 // optimization.
3303 if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) { 3347 if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) {
3304 __ bind(&exit); 3348 __ bind(&exit);
3305 } 3349 }
3306 } 3350 }
3307 break; 3351 break;
3308 } 3352 }
3309 3353
3310 case NAMED: { 3354 case NAMED: {
3311 Comment cmnt(masm, "[ Store to named Property"); 3355 Comment cmnt(masm, "[ Store to named Property");
3312 // Call the appropriate IC code. 3356 // Call the appropriate IC code.
3313 __ pop(r0); // value 3357 frame->Pop(r0); // value
3314 // Setup the name register. 3358 // Setup the name register.
3315 Handle<String> name(GetName()); 3359 Handle<String> name(GetName());
3316 __ mov(r2, Operand(name)); 3360 __ mov(r2, Operand(name));
3317 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 3361 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
3318 __ Call(ic, RelocInfo::CODE_TARGET); 3362 __ Call(ic, RelocInfo::CODE_TARGET);
3319 __ push(r0); 3363 frame->Push(r0);
3320 break; 3364 break;
3321 } 3365 }
3322 3366
3323 case KEYED: { 3367 case KEYED: {
3324 Comment cmnt(masm, "[ Store to keyed Property"); 3368 Comment cmnt(masm, "[ Store to keyed Property");
3325 Property* property = expression_->AsProperty(); 3369 Property* property = expression_->AsProperty();
3326 ASSERT(property != NULL); 3370 ASSERT(property != NULL);
3327 __ RecordPosition(property->position()); 3371 __ RecordPosition(property->position());
3328 __ pop(r0); // value 3372
3329 SetPropertyStub stub; 3373 // Call IC code.
3330 __ CallStub(&stub); 3374 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
3331 __ push(r0); 3375 // TODO(1222589): Make the IC grab the values from the stack.
3376 frame->Pop(r0); // value
3377 __ Call(ic, RelocInfo::CODE_TARGET);
3378 frame->Push(r0);
3332 break; 3379 break;
3333 } 3380 }
3334 3381
3335 default: 3382 default:
3336 UNREACHABLE(); 3383 UNREACHABLE();
3337 } 3384 }
3338 } 3385 }
3339 3386
3340 3387
3341 void GetPropertyStub::Generate(MacroAssembler* masm) { 3388 void GetPropertyStub::Generate(MacroAssembler* masm) {
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
3806 3853
3807 // Set pending exception and r0 to out of memory exception. 3854 // Set pending exception and r0 to out of memory exception.
3808 Failure* out_of_memory = Failure::OutOfMemoryException(); 3855 Failure* out_of_memory = Failure::OutOfMemoryException();
3809 __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); 3856 __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
3810 __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address))); 3857 __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address)));
3811 __ str(r0, MemOperand(r2)); 3858 __ str(r0, MemOperand(r2));
3812 3859
3813 // Restore the stack to the address of the ENTRY handler 3860 // Restore the stack to the address of the ENTRY handler
3814 __ mov(sp, Operand(r3)); 3861 __ mov(sp, Operand(r3));
3815 3862
3816 // restore parameter- and frame-pointer and pop state. 3863 // Stack layout at this point. See also PushTryHandler
3817 __ ldm(ia_w, sp, r3.bit() | pp.bit() | fp.bit()); 3864 // r3, sp -> next handler
3865 // state (ENTRY)
3866 // pp
3867 // fp
3868 // lr
3869
3870 // Discard ENTRY state (r2 is not used), and restore parameter-
3871 // and frame-pointer and pop state.
3872 __ ldm(ia_w, sp, r2.bit() | r3.bit() | pp.bit() | fp.bit());
3818 // Before returning we restore the context from the frame pointer if not NULL. 3873 // Before returning we restore the context from the frame pointer if not NULL.
3819 // The frame pointer is NULL in the exception handler of a JS entry frame. 3874 // The frame pointer is NULL in the exception handler of a JS entry frame.
3820 __ cmp(fp, Operand(0)); 3875 __ cmp(fp, Operand(0));
3821 // Set cp to NULL if fp is NULL. 3876 // Set cp to NULL if fp is NULL.
3822 __ mov(cp, Operand(0), LeaveCC, eq); 3877 __ mov(cp, Operand(0), LeaveCC, eq);
3823 // Restore cp otherwise. 3878 // Restore cp otherwise.
3824 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); 3879 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
3825 if (kDebug && FLAG_debug_code) __ mov(lr, Operand(pc)); 3880 if (kDebug && FLAG_debug_code) __ mov(lr, Operand(pc));
3826 __ pop(pc); 3881 __ pop(pc);
3827 } 3882 }
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
4037 4092
4038 // Call a faked try-block that does the invoke. 4093 // Call a faked try-block that does the invoke.
4039 __ bl(&invoke); 4094 __ bl(&invoke);
4040 4095
4041 // Caught exception: Store result (exception) in the pending 4096 // Caught exception: Store result (exception) in the pending
4042 // exception field in the JSEnv and return a failure sentinel. 4097 // exception field in the JSEnv and return a failure sentinel.
4043 // Coming in here the fp will be invalid because the PushTryHandler below 4098 // Coming in here the fp will be invalid because the PushTryHandler below
4044 // sets it to 0 to signal the existence of the JSEntry frame. 4099 // sets it to 0 to signal the existence of the JSEntry frame.
4045 __ mov(ip, Operand(Top::pending_exception_address())); 4100 __ mov(ip, Operand(Top::pending_exception_address()));
4046 __ str(r0, MemOperand(ip)); 4101 __ str(r0, MemOperand(ip));
4047 __ mov(r0, Operand(Handle<Failure>(Failure::Exception()))); 4102 __ mov(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception())));
4048 __ b(&exit); 4103 __ b(&exit);
4049 4104
4050 // Invoke: Link this frame into the handler chain. 4105 // Invoke: Link this frame into the handler chain.
4051 __ bind(&invoke); 4106 __ bind(&invoke);
4052 // Must preserve r0-r4, r5-r7 are available. 4107 // Must preserve r0-r4, r5-r7 are available.
4053 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER); 4108 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER);
4054 // If an exception not caught by another handler occurs, this handler returns 4109 // If an exception not caught by another handler occurs, this handler returns
4055 // control to the code after the bl(&invoke) above, which restores all 4110 // control to the code after the bl(&invoke) above, which restores all
4056 // kCalleeSaved registers (including cp, pp and fp) to their saved values 4111 // kCalleeSaved registers (including cp, pp and fp) to their saved values
4057 // before returning a failure to C. 4112 // before returning a failure to C.
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
4222 __ b(ne, &slow); 4277 __ b(ne, &slow);
4223 4278
4224 // Fast-case: Invoke the function now. 4279 // Fast-case: Invoke the function now.
4225 // r1: pushed function 4280 // r1: pushed function
4226 ParameterCount actual(argc_); 4281 ParameterCount actual(argc_);
4227 __ InvokeFunction(r1, actual, JUMP_FUNCTION); 4282 __ InvokeFunction(r1, actual, JUMP_FUNCTION);
4228 4283
4229 // Slow-case: Non-function called. 4284 // Slow-case: Non-function called.
4230 __ bind(&slow); 4285 __ bind(&slow);
4231 __ mov(r0, Operand(argc_)); // Setup the number of arguments. 4286 __ mov(r0, Operand(argc_)); // Setup the number of arguments.
4232 __ InvokeBuiltin(Builtins::CALL_NON_FUNCTION, JUMP_JS); 4287 __ mov(r2, Operand(0));
4288 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
4289 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)),
4290 RelocInfo::CODE_TARGET);
4233 } 4291 }
4234 4292
4235 4293
4236 #undef __ 4294 #undef __
4237 4295
4238 } } // namespace v8::internal 4296 } } // 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