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

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

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

Powered by Google App Engine
This is Rietveld 408576698