Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / v8 / src / arm / full-codegen-arm.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "v8.h"
6
7 #if V8_TARGET_ARCH_ARM
8
9 #include "code-stubs.h"
10 #include "codegen.h"
11 #include "compiler.h"
12 #include "debug.h"
13 #include "full-codegen.h"
14 #include "isolate-inl.h"
15 #include "parser.h"
16 #include "scopes.h"
17 #include "stub-cache.h"
18
19 #include "arm/code-stubs-arm.h"
20 #include "arm/macro-assembler-arm.h"
21
22 namespace v8 {
23 namespace internal {
24
25 #define __ ACCESS_MASM(masm_)
26
27
28 // A patch site is a location in the code which it is possible to patch. This
29 // class has a number of methods to emit the code which is patchable and the
30 // method EmitPatchInfo to record a marker back to the patchable code. This
31 // marker is a cmp rx, #yyy instruction, and x * 0x00000fff + yyy (raw 12 bit
32 // immediate value is used) is the delta from the pc to the first instruction of
33 // the patchable code.
34 class JumpPatchSite BASE_EMBEDDED {
35  public:
36   explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
37 #ifdef DEBUG
38     info_emitted_ = false;
39 #endif
40   }
41
42   ~JumpPatchSite() {
43     ASSERT(patch_site_.is_bound() == info_emitted_);
44   }
45
46   // When initially emitting this ensure that a jump is always generated to skip
47   // the inlined smi code.
48   void EmitJumpIfNotSmi(Register reg, Label* target) {
49     ASSERT(!patch_site_.is_bound() && !info_emitted_);
50     Assembler::BlockConstPoolScope block_const_pool(masm_);
51     __ bind(&patch_site_);
52     __ cmp(reg, Operand(reg));
53     __ b(eq, target);  // Always taken before patched.
54   }
55
56   // When initially emitting this ensure that a jump is never generated to skip
57   // the inlined smi code.
58   void EmitJumpIfSmi(Register reg, Label* target) {
59     ASSERT(!patch_site_.is_bound() && !info_emitted_);
60     Assembler::BlockConstPoolScope block_const_pool(masm_);
61     __ bind(&patch_site_);
62     __ cmp(reg, Operand(reg));
63     __ b(ne, target);  // Never taken before patched.
64   }
65
66   void EmitPatchInfo() {
67     // Block literal pool emission whilst recording patch site information.
68     Assembler::BlockConstPoolScope block_const_pool(masm_);
69     if (patch_site_.is_bound()) {
70       int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_);
71       Register reg;
72       reg.set_code(delta_to_patch_site / kOff12Mask);
73       __ cmp_raw_immediate(reg, delta_to_patch_site % kOff12Mask);
74 #ifdef DEBUG
75       info_emitted_ = true;
76 #endif
77     } else {
78       __ nop();  // Signals no inlined code.
79     }
80   }
81
82  private:
83   MacroAssembler* masm_;
84   Label patch_site_;
85 #ifdef DEBUG
86   bool info_emitted_;
87 #endif
88 };
89
90
91 static void EmitStackCheck(MacroAssembler* masm_,
92                            Register stack_limit_scratch,
93                            int pointers = 0,
94                            Register scratch = sp) {
95     Isolate* isolate = masm_->isolate();
96   Label ok;
97   ASSERT(scratch.is(sp) == (pointers == 0));
98   Heap::RootListIndex index;
99   if (pointers != 0) {
100     __ sub(scratch, sp, Operand(pointers * kPointerSize));
101     index = Heap::kRealStackLimitRootIndex;
102   } else {
103     index = Heap::kStackLimitRootIndex;
104   }
105   __ LoadRoot(stack_limit_scratch, index);
106   __ cmp(scratch, Operand(stack_limit_scratch));
107   __ b(hs, &ok);
108   Handle<Code> stack_check = isolate->builtins()->StackCheck();
109   PredictableCodeSizeScope predictable(masm_,
110       masm_->CallSize(stack_check, RelocInfo::CODE_TARGET));
111   __ Call(stack_check, RelocInfo::CODE_TARGET);
112   __ bind(&ok);
113 }
114
115
116 // Generate code for a JS function.  On entry to the function the receiver
117 // and arguments have been pushed on the stack left to right.  The actual
118 // argument count matches the formal parameter count expected by the
119 // function.
120 //
121 // The live registers are:
122 //   o r1: the JS function object being called (i.e., ourselves)
123 //   o cp: our context
124 //   o pp: our caller's constant pool pointer (if FLAG_enable_ool_constant_pool)
125 //   o fp: our caller's frame pointer
126 //   o sp: stack pointer
127 //   o lr: return address
128 //
129 // The function builds a JS frame.  Please see JavaScriptFrameConstants in
130 // frames-arm.h for its layout.
131 void FullCodeGenerator::Generate() {
132   CompilationInfo* info = info_;
133   handler_table_ =
134       isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
135
136   profiling_counter_ = isolate()->factory()->NewCell(
137       Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
138   SetFunctionPosition(function());
139   Comment cmnt(masm_, "[ function compiled by full code generator");
140
141   ProfileEntryHookStub::MaybeCallEntryHook(masm_);
142
143 #ifdef DEBUG
144   if (strlen(FLAG_stop_at) > 0 &&
145       info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
146     __ stop("stop-at");
147   }
148 #endif
149
150   // Sloppy mode functions and builtins need to replace the receiver with the
151   // global proxy when called as functions (without an explicit receiver
152   // object).
153   if (info->strict_mode() == SLOPPY && !info->is_native()) {
154     Label ok;
155     int receiver_offset = info->scope()->num_parameters() * kPointerSize;
156     __ ldr(r2, MemOperand(sp, receiver_offset));
157     __ CompareRoot(r2, Heap::kUndefinedValueRootIndex);
158     __ b(ne, &ok);
159
160     __ ldr(r2, GlobalObjectOperand());
161     __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
162
163     __ str(r2, MemOperand(sp, receiver_offset));
164
165     __ bind(&ok);
166   }
167
168   // Open a frame scope to indicate that there is a frame on the stack.  The
169   // MANUAL indicates that the scope shouldn't actually generate code to set up
170   // the frame (that is done below).
171   FrameScope frame_scope(masm_, StackFrame::MANUAL);
172
173   info->set_prologue_offset(masm_->pc_offset());
174   __ Prologue(BUILD_FUNCTION_FRAME);
175   info->AddNoFrameRange(0, masm_->pc_offset());
176
177   { Comment cmnt(masm_, "[ Allocate locals");
178     int locals_count = info->scope()->num_stack_slots();
179     // Generators allocate locals, if any, in context slots.
180     ASSERT(!info->function()->is_generator() || locals_count == 0);
181     if (locals_count > 0) {
182       if (locals_count >= 128) {
183         EmitStackCheck(masm_, r2, locals_count, r9);
184       }
185       __ LoadRoot(r9, Heap::kUndefinedValueRootIndex);
186       int kMaxPushes = FLAG_optimize_for_size ? 4 : 32;
187       if (locals_count >= kMaxPushes) {
188         int loop_iterations = locals_count / kMaxPushes;
189         __ mov(r2, Operand(loop_iterations));
190         Label loop_header;
191         __ bind(&loop_header);
192         // Do pushes.
193         for (int i = 0; i < kMaxPushes; i++) {
194           __ push(r9);
195         }
196         // Continue loop if not done.
197         __ sub(r2, r2, Operand(1), SetCC);
198         __ b(&loop_header, ne);
199       }
200       int remaining = locals_count % kMaxPushes;
201       // Emit the remaining pushes.
202       for (int i  = 0; i < remaining; i++) {
203         __ push(r9);
204       }
205     }
206   }
207
208   bool function_in_register = true;
209
210   // Possibly allocate a local context.
211   int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
212   if (heap_slots > 0) {
213     // Argument to NewContext is the function, which is still in r1.
214     Comment cmnt(masm_, "[ Allocate context");
215     if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
216       __ push(r1);
217       __ Push(info->scope()->GetScopeInfo());
218       __ CallRuntime(Runtime::kHiddenNewGlobalContext, 2);
219     } else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
220       FastNewContextStub stub(isolate(), heap_slots);
221       __ CallStub(&stub);
222     } else {
223       __ push(r1);
224       __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1);
225     }
226     function_in_register = false;
227     // Context is returned in r0.  It replaces the context passed to us.
228     // It's saved in the stack and kept live in cp.
229     __ mov(cp, r0);
230     __ str(r0, MemOperand(fp, StandardFrameConstants::kContextOffset));
231     // Copy any necessary parameters into the context.
232     int num_parameters = info->scope()->num_parameters();
233     for (int i = 0; i < num_parameters; i++) {
234       Variable* var = scope()->parameter(i);
235       if (var->IsContextSlot()) {
236         int parameter_offset = StandardFrameConstants::kCallerSPOffset +
237             (num_parameters - 1 - i) * kPointerSize;
238         // Load parameter from stack.
239         __ ldr(r0, MemOperand(fp, parameter_offset));
240         // Store it in the context.
241         MemOperand target = ContextOperand(cp, var->index());
242         __ str(r0, target);
243
244         // Update the write barrier.
245         __ RecordWriteContextSlot(
246             cp, target.offset(), r0, r3, kLRHasBeenSaved, kDontSaveFPRegs);
247       }
248     }
249   }
250
251   Variable* arguments = scope()->arguments();
252   if (arguments != NULL) {
253     // Function uses arguments object.
254     Comment cmnt(masm_, "[ Allocate arguments object");
255     if (!function_in_register) {
256       // Load this again, if it's used by the local context below.
257       __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
258     } else {
259       __ mov(r3, r1);
260     }
261     // Receiver is just before the parameters on the caller's stack.
262     int num_parameters = info->scope()->num_parameters();
263     int offset = num_parameters * kPointerSize;
264     __ add(r2, fp,
265            Operand(StandardFrameConstants::kCallerSPOffset + offset));
266     __ mov(r1, Operand(Smi::FromInt(num_parameters)));
267     __ Push(r3, r2, r1);
268
269     // Arguments to ArgumentsAccessStub:
270     //   function, receiver address, parameter count.
271     // The stub will rewrite receiever and parameter count if the previous
272     // stack frame was an arguments adapter frame.
273     ArgumentsAccessStub::Type type;
274     if (strict_mode() == STRICT) {
275       type = ArgumentsAccessStub::NEW_STRICT;
276     } else if (function()->has_duplicate_parameters()) {
277       type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
278     } else {
279       type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
280     }
281     ArgumentsAccessStub stub(isolate(), type);
282     __ CallStub(&stub);
283
284     SetVar(arguments, r0, r1, r2);
285   }
286
287   if (FLAG_trace) {
288     __ CallRuntime(Runtime::kTraceEnter, 0);
289   }
290
291   // Visit the declarations and body unless there is an illegal
292   // redeclaration.
293   if (scope()->HasIllegalRedeclaration()) {
294     Comment cmnt(masm_, "[ Declarations");
295     scope()->VisitIllegalRedeclaration(this);
296
297   } else {
298     PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
299     { Comment cmnt(masm_, "[ Declarations");
300       // For named function expressions, declare the function name as a
301       // constant.
302       if (scope()->is_function_scope() && scope()->function() != NULL) {
303         VariableDeclaration* function = scope()->function();
304         ASSERT(function->proxy()->var()->mode() == CONST ||
305                function->proxy()->var()->mode() == CONST_LEGACY);
306         ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
307         VisitVariableDeclaration(function);
308       }
309       VisitDeclarations(scope()->declarations());
310     }
311
312     { Comment cmnt(masm_, "[ Stack check");
313       PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
314       EmitStackCheck(masm_, ip);
315     }
316
317     { Comment cmnt(masm_, "[ Body");
318       ASSERT(loop_depth() == 0);
319       VisitStatements(function()->body());
320       ASSERT(loop_depth() == 0);
321     }
322   }
323
324   // Always emit a 'return undefined' in case control fell off the end of
325   // the body.
326   { Comment cmnt(masm_, "[ return <undefined>;");
327     __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
328   }
329   EmitReturnSequence();
330
331   // Force emit the constant pool, so it doesn't get emitted in the middle
332   // of the back edge table.
333   masm()->CheckConstPool(true, false);
334 }
335
336
337 void FullCodeGenerator::ClearAccumulator() {
338   __ mov(r0, Operand(Smi::FromInt(0)));
339 }
340
341
342 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
343   __ mov(r2, Operand(profiling_counter_));
344   __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
345   __ sub(r3, r3, Operand(Smi::FromInt(delta)), SetCC);
346   __ str(r3, FieldMemOperand(r2, Cell::kValueOffset));
347 }
348
349
350 void FullCodeGenerator::EmitProfilingCounterReset() {
351   int reset_value = FLAG_interrupt_budget;
352   if (isolate()->IsDebuggerActive()) {
353     // Detect debug break requests as soon as possible.
354     reset_value = FLAG_interrupt_budget >> 4;
355   }
356   __ mov(r2, Operand(profiling_counter_));
357   __ mov(r3, Operand(Smi::FromInt(reset_value)));
358   __ str(r3, FieldMemOperand(r2, Cell::kValueOffset));
359 }
360
361
362 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
363                                                 Label* back_edge_target) {
364   Comment cmnt(masm_, "[ Back edge bookkeeping");
365   // Block literal pools whilst emitting back edge code.
366   Assembler::BlockConstPoolScope block_const_pool(masm_);
367   Label ok;
368
369   ASSERT(back_edge_target->is_bound());
370   int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
371   int weight = Min(kMaxBackEdgeWeight,
372                    Max(1, distance / kCodeSizeMultiplier));
373   EmitProfilingCounterDecrement(weight);
374   __ b(pl, &ok);
375   __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
376
377   // Record a mapping of this PC offset to the OSR id.  This is used to find
378   // the AST id from the unoptimized code in order to use it as a key into
379   // the deoptimization input data found in the optimized code.
380   RecordBackEdge(stmt->OsrEntryId());
381
382   EmitProfilingCounterReset();
383
384   __ bind(&ok);
385   PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
386   // Record a mapping of the OSR id to this PC.  This is used if the OSR
387   // entry becomes the target of a bailout.  We don't expect it to be, but
388   // we want it to work if it is.
389   PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
390 }
391
392
393 void FullCodeGenerator::EmitReturnSequence() {
394   Comment cmnt(masm_, "[ Return sequence");
395   if (return_label_.is_bound()) {
396     __ b(&return_label_);
397   } else {
398     __ bind(&return_label_);
399     if (FLAG_trace) {
400       // Push the return value on the stack as the parameter.
401       // Runtime::TraceExit returns its parameter in r0.
402       __ push(r0);
403       __ CallRuntime(Runtime::kTraceExit, 1);
404     }
405     // Pretend that the exit is a backwards jump to the entry.
406     int weight = 1;
407     if (info_->ShouldSelfOptimize()) {
408       weight = FLAG_interrupt_budget / FLAG_self_opt_count;
409     } else {
410       int distance = masm_->pc_offset();
411       weight = Min(kMaxBackEdgeWeight,
412                    Max(1, distance / kCodeSizeMultiplier));
413     }
414     EmitProfilingCounterDecrement(weight);
415     Label ok;
416     __ b(pl, &ok);
417     __ push(r0);
418     __ Call(isolate()->builtins()->InterruptCheck(),
419             RelocInfo::CODE_TARGET);
420     __ pop(r0);
421     EmitProfilingCounterReset();
422     __ bind(&ok);
423
424 #ifdef DEBUG
425     // Add a label for checking the size of the code used for returning.
426     Label check_exit_codesize;
427     __ bind(&check_exit_codesize);
428 #endif
429     // Make sure that the constant pool is not emitted inside of the return
430     // sequence.
431     { Assembler::BlockConstPoolScope block_const_pool(masm_);
432       int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize;
433       CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
434       // TODO(svenpanne) The code below is sometimes 4 words, sometimes 5!
435       PredictableCodeSizeScope predictable(masm_, -1);
436       __ RecordJSReturn();
437       int no_frame_start = __ LeaveFrame(StackFrame::JAVA_SCRIPT);
438       __ add(sp, sp, Operand(sp_delta));
439       __ Jump(lr);
440       info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
441     }
442
443 #ifdef DEBUG
444     // Check that the size of the code used for returning is large enough
445     // for the debugger's requirements.
446     ASSERT(Assembler::kJSReturnSequenceInstructions <=
447            masm_->InstructionsGeneratedSince(&check_exit_codesize));
448 #endif
449   }
450 }
451
452
453 void FullCodeGenerator::EffectContext::Plug(Variable* var) const {
454   ASSERT(var->IsStackAllocated() || var->IsContextSlot());
455 }
456
457
458 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
459   ASSERT(var->IsStackAllocated() || var->IsContextSlot());
460   codegen()->GetVar(result_register(), var);
461 }
462
463
464 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
465   ASSERT(var->IsStackAllocated() || var->IsContextSlot());
466   codegen()->GetVar(result_register(), var);
467   __ push(result_register());
468 }
469
470
471 void FullCodeGenerator::TestContext::Plug(Variable* var) const {
472   ASSERT(var->IsStackAllocated() || var->IsContextSlot());
473   // For simplicity we always test the accumulator register.
474   codegen()->GetVar(result_register(), var);
475   codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
476   codegen()->DoTest(this);
477 }
478
479
480 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
481 }
482
483
484 void FullCodeGenerator::AccumulatorValueContext::Plug(
485     Heap::RootListIndex index) const {
486   __ LoadRoot(result_register(), index);
487 }
488
489
490 void FullCodeGenerator::StackValueContext::Plug(
491     Heap::RootListIndex index) const {
492   __ LoadRoot(result_register(), index);
493   __ push(result_register());
494 }
495
496
497 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
498   codegen()->PrepareForBailoutBeforeSplit(condition(),
499                                           true,
500                                           true_label_,
501                                           false_label_);
502   if (index == Heap::kUndefinedValueRootIndex ||
503       index == Heap::kNullValueRootIndex ||
504       index == Heap::kFalseValueRootIndex) {
505     if (false_label_ != fall_through_) __ b(false_label_);
506   } else if (index == Heap::kTrueValueRootIndex) {
507     if (true_label_ != fall_through_) __ b(true_label_);
508   } else {
509     __ LoadRoot(result_register(), index);
510     codegen()->DoTest(this);
511   }
512 }
513
514
515 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
516 }
517
518
519 void FullCodeGenerator::AccumulatorValueContext::Plug(
520     Handle<Object> lit) const {
521   __ mov(result_register(), Operand(lit));
522 }
523
524
525 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
526   // Immediates cannot be pushed directly.
527   __ mov(result_register(), Operand(lit));
528   __ push(result_register());
529 }
530
531
532 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
533   codegen()->PrepareForBailoutBeforeSplit(condition(),
534                                           true,
535                                           true_label_,
536                                           false_label_);
537   ASSERT(!lit->IsUndetectableObject());  // There are no undetectable literals.
538   if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
539     if (false_label_ != fall_through_) __ b(false_label_);
540   } else if (lit->IsTrue() || lit->IsJSObject()) {
541     if (true_label_ != fall_through_) __ b(true_label_);
542   } else if (lit->IsString()) {
543     if (String::cast(*lit)->length() == 0) {
544       if (false_label_ != fall_through_) __ b(false_label_);
545     } else {
546       if (true_label_ != fall_through_) __ b(true_label_);
547     }
548   } else if (lit->IsSmi()) {
549     if (Smi::cast(*lit)->value() == 0) {
550       if (false_label_ != fall_through_) __ b(false_label_);
551     } else {
552       if (true_label_ != fall_through_) __ b(true_label_);
553     }
554   } else {
555     // For simplicity we always test the accumulator register.
556     __ mov(result_register(), Operand(lit));
557     codegen()->DoTest(this);
558   }
559 }
560
561
562 void FullCodeGenerator::EffectContext::DropAndPlug(int count,
563                                                    Register reg) const {
564   ASSERT(count > 0);
565   __ Drop(count);
566 }
567
568
569 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
570     int count,
571     Register reg) const {
572   ASSERT(count > 0);
573   __ Drop(count);
574   __ Move(result_register(), reg);
575 }
576
577
578 void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
579                                                        Register reg) const {
580   ASSERT(count > 0);
581   if (count > 1) __ Drop(count - 1);
582   __ str(reg, MemOperand(sp, 0));
583 }
584
585
586 void FullCodeGenerator::TestContext::DropAndPlug(int count,
587                                                  Register reg) const {
588   ASSERT(count > 0);
589   // For simplicity we always test the accumulator register.
590   __ Drop(count);
591   __ Move(result_register(), reg);
592   codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
593   codegen()->DoTest(this);
594 }
595
596
597 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
598                                             Label* materialize_false) const {
599   ASSERT(materialize_true == materialize_false);
600   __ bind(materialize_true);
601 }
602
603
604 void FullCodeGenerator::AccumulatorValueContext::Plug(
605     Label* materialize_true,
606     Label* materialize_false) const {
607   Label done;
608   __ bind(materialize_true);
609   __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
610   __ jmp(&done);
611   __ bind(materialize_false);
612   __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
613   __ bind(&done);
614 }
615
616
617 void FullCodeGenerator::StackValueContext::Plug(
618     Label* materialize_true,
619     Label* materialize_false) const {
620   Label done;
621   __ bind(materialize_true);
622   __ LoadRoot(ip, Heap::kTrueValueRootIndex);
623   __ jmp(&done);
624   __ bind(materialize_false);
625   __ LoadRoot(ip, Heap::kFalseValueRootIndex);
626   __ bind(&done);
627   __ push(ip);
628 }
629
630
631 void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
632                                           Label* materialize_false) const {
633   ASSERT(materialize_true == true_label_);
634   ASSERT(materialize_false == false_label_);
635 }
636
637
638 void FullCodeGenerator::EffectContext::Plug(bool flag) const {
639 }
640
641
642 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
643   Heap::RootListIndex value_root_index =
644       flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
645   __ LoadRoot(result_register(), value_root_index);
646 }
647
648
649 void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
650   Heap::RootListIndex value_root_index =
651       flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
652   __ LoadRoot(ip, value_root_index);
653   __ push(ip);
654 }
655
656
657 void FullCodeGenerator::TestContext::Plug(bool flag) const {
658   codegen()->PrepareForBailoutBeforeSplit(condition(),
659                                           true,
660                                           true_label_,
661                                           false_label_);
662   if (flag) {
663     if (true_label_ != fall_through_) __ b(true_label_);
664   } else {
665     if (false_label_ != fall_through_) __ b(false_label_);
666   }
667 }
668
669
670 void FullCodeGenerator::DoTest(Expression* condition,
671                                Label* if_true,
672                                Label* if_false,
673                                Label* fall_through) {
674   Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
675   CallIC(ic, condition->test_id());
676   __ tst(result_register(), result_register());
677   Split(ne, if_true, if_false, fall_through);
678 }
679
680
681 void FullCodeGenerator::Split(Condition cond,
682                               Label* if_true,
683                               Label* if_false,
684                               Label* fall_through) {
685   if (if_false == fall_through) {
686     __ b(cond, if_true);
687   } else if (if_true == fall_through) {
688     __ b(NegateCondition(cond), if_false);
689   } else {
690     __ b(cond, if_true);
691     __ b(if_false);
692   }
693 }
694
695
696 MemOperand FullCodeGenerator::StackOperand(Variable* var) {
697   ASSERT(var->IsStackAllocated());
698   // Offset is negative because higher indexes are at lower addresses.
699   int offset = -var->index() * kPointerSize;
700   // Adjust by a (parameter or local) base offset.
701   if (var->IsParameter()) {
702     offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
703   } else {
704     offset += JavaScriptFrameConstants::kLocal0Offset;
705   }
706   return MemOperand(fp, offset);
707 }
708
709
710 MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
711   ASSERT(var->IsContextSlot() || var->IsStackAllocated());
712   if (var->IsContextSlot()) {
713     int context_chain_length = scope()->ContextChainLength(var->scope());
714     __ LoadContext(scratch, context_chain_length);
715     return ContextOperand(scratch, var->index());
716   } else {
717     return StackOperand(var);
718   }
719 }
720
721
722 void FullCodeGenerator::GetVar(Register dest, Variable* var) {
723   // Use destination as scratch.
724   MemOperand location = VarOperand(var, dest);
725   __ ldr(dest, location);
726 }
727
728
729 void FullCodeGenerator::SetVar(Variable* var,
730                                Register src,
731                                Register scratch0,
732                                Register scratch1) {
733   ASSERT(var->IsContextSlot() || var->IsStackAllocated());
734   ASSERT(!scratch0.is(src));
735   ASSERT(!scratch0.is(scratch1));
736   ASSERT(!scratch1.is(src));
737   MemOperand location = VarOperand(var, scratch0);
738   __ str(src, location);
739
740   // Emit the write barrier code if the location is in the heap.
741   if (var->IsContextSlot()) {
742     __ RecordWriteContextSlot(scratch0,
743                               location.offset(),
744                               src,
745                               scratch1,
746                               kLRHasBeenSaved,
747                               kDontSaveFPRegs);
748   }
749 }
750
751
752 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
753                                                      bool should_normalize,
754                                                      Label* if_true,
755                                                      Label* if_false) {
756   // Only prepare for bailouts before splits if we're in a test
757   // context. Otherwise, we let the Visit function deal with the
758   // preparation to avoid preparing with the same AST id twice.
759   if (!context()->IsTest() || !info_->IsOptimizable()) return;
760
761   Label skip;
762   if (should_normalize) __ b(&skip);
763   PrepareForBailout(expr, TOS_REG);
764   if (should_normalize) {
765     __ LoadRoot(ip, Heap::kTrueValueRootIndex);
766     __ cmp(r0, ip);
767     Split(eq, if_true, if_false, NULL);
768     __ bind(&skip);
769   }
770 }
771
772
773 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
774   // The variable in the declaration always resides in the current function
775   // context.
776   ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
777   if (generate_debug_code_) {
778     // Check that we're not inside a with or catch context.
779     __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset));
780     __ CompareRoot(r1, Heap::kWithContextMapRootIndex);
781     __ Check(ne, kDeclarationInWithContext);
782     __ CompareRoot(r1, Heap::kCatchContextMapRootIndex);
783     __ Check(ne, kDeclarationInCatchContext);
784   }
785 }
786
787
788 void FullCodeGenerator::VisitVariableDeclaration(
789     VariableDeclaration* declaration) {
790   // If it was not possible to allocate the variable at compile time, we
791   // need to "declare" it at runtime to make sure it actually exists in the
792   // local context.
793   VariableProxy* proxy = declaration->proxy();
794   VariableMode mode = declaration->mode();
795   Variable* variable = proxy->var();
796   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
797   switch (variable->location()) {
798     case Variable::UNALLOCATED:
799       globals_->Add(variable->name(), zone());
800       globals_->Add(variable->binding_needs_init()
801                         ? isolate()->factory()->the_hole_value()
802                         : isolate()->factory()->undefined_value(),
803                     zone());
804       break;
805
806     case Variable::PARAMETER:
807     case Variable::LOCAL:
808       if (hole_init) {
809         Comment cmnt(masm_, "[ VariableDeclaration");
810         __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
811         __ str(ip, StackOperand(variable));
812       }
813       break;
814
815     case Variable::CONTEXT:
816       if (hole_init) {
817         Comment cmnt(masm_, "[ VariableDeclaration");
818         EmitDebugCheckDeclarationContext(variable);
819         __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
820         __ str(ip, ContextOperand(cp, variable->index()));
821         // No write barrier since the_hole_value is in old space.
822         PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
823       }
824       break;
825
826     case Variable::LOOKUP: {
827       Comment cmnt(masm_, "[ VariableDeclaration");
828       __ mov(r2, Operand(variable->name()));
829       // Declaration nodes are always introduced in one of four modes.
830       ASSERT(IsDeclaredVariableMode(mode));
831       PropertyAttributes attr =
832           IsImmutableVariableMode(mode) ? READ_ONLY : NONE;
833       __ mov(r1, Operand(Smi::FromInt(attr)));
834       // Push initial value, if any.
835       // Note: For variables we must not push an initial value (such as
836       // 'undefined') because we may have a (legal) redeclaration and we
837       // must not destroy the current value.
838       if (hole_init) {
839         __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
840         __ Push(cp, r2, r1, r0);
841       } else {
842         __ mov(r0, Operand(Smi::FromInt(0)));  // Indicates no initial value.
843         __ Push(cp, r2, r1, r0);
844       }
845       __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4);
846       break;
847     }
848   }
849 }
850
851
852 void FullCodeGenerator::VisitFunctionDeclaration(
853     FunctionDeclaration* declaration) {
854   VariableProxy* proxy = declaration->proxy();
855   Variable* variable = proxy->var();
856   switch (variable->location()) {
857     case Variable::UNALLOCATED: {
858       globals_->Add(variable->name(), zone());
859       Handle<SharedFunctionInfo> function =
860           Compiler::BuildFunctionInfo(declaration->fun(), script());
861       // Check for stack-overflow exception.
862       if (function.is_null()) return SetStackOverflow();
863       globals_->Add(function, zone());
864       break;
865     }
866
867     case Variable::PARAMETER:
868     case Variable::LOCAL: {
869       Comment cmnt(masm_, "[ FunctionDeclaration");
870       VisitForAccumulatorValue(declaration->fun());
871       __ str(result_register(), StackOperand(variable));
872       break;
873     }
874
875     case Variable::CONTEXT: {
876       Comment cmnt(masm_, "[ FunctionDeclaration");
877       EmitDebugCheckDeclarationContext(variable);
878       VisitForAccumulatorValue(declaration->fun());
879       __ str(result_register(), ContextOperand(cp, variable->index()));
880       int offset = Context::SlotOffset(variable->index());
881       // We know that we have written a function, which is not a smi.
882       __ RecordWriteContextSlot(cp,
883                                 offset,
884                                 result_register(),
885                                 r2,
886                                 kLRHasBeenSaved,
887                                 kDontSaveFPRegs,
888                                 EMIT_REMEMBERED_SET,
889                                 OMIT_SMI_CHECK);
890       PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
891       break;
892     }
893
894     case Variable::LOOKUP: {
895       Comment cmnt(masm_, "[ FunctionDeclaration");
896       __ mov(r2, Operand(variable->name()));
897       __ mov(r1, Operand(Smi::FromInt(NONE)));
898       __ Push(cp, r2, r1);
899       // Push initial value for function declaration.
900       VisitForStackValue(declaration->fun());
901       __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4);
902       break;
903     }
904   }
905 }
906
907
908 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
909   Variable* variable = declaration->proxy()->var();
910   ASSERT(variable->location() == Variable::CONTEXT);
911   ASSERT(variable->interface()->IsFrozen());
912
913   Comment cmnt(masm_, "[ ModuleDeclaration");
914   EmitDebugCheckDeclarationContext(variable);
915
916   // Load instance object.
917   __ LoadContext(r1, scope_->ContextChainLength(scope_->GlobalScope()));
918   __ ldr(r1, ContextOperand(r1, variable->interface()->Index()));
919   __ ldr(r1, ContextOperand(r1, Context::EXTENSION_INDEX));
920
921   // Assign it.
922   __ str(r1, ContextOperand(cp, variable->index()));
923   // We know that we have written a module, which is not a smi.
924   __ RecordWriteContextSlot(cp,
925                             Context::SlotOffset(variable->index()),
926                             r1,
927                             r3,
928                             kLRHasBeenSaved,
929                             kDontSaveFPRegs,
930                             EMIT_REMEMBERED_SET,
931                             OMIT_SMI_CHECK);
932   PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS);
933
934   // Traverse into body.
935   Visit(declaration->module());
936 }
937
938
939 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
940   VariableProxy* proxy = declaration->proxy();
941   Variable* variable = proxy->var();
942   switch (variable->location()) {
943     case Variable::UNALLOCATED:
944       // TODO(rossberg)
945       break;
946
947     case Variable::CONTEXT: {
948       Comment cmnt(masm_, "[ ImportDeclaration");
949       EmitDebugCheckDeclarationContext(variable);
950       // TODO(rossberg)
951       break;
952     }
953
954     case Variable::PARAMETER:
955     case Variable::LOCAL:
956     case Variable::LOOKUP:
957       UNREACHABLE();
958   }
959 }
960
961
962 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) {
963   // TODO(rossberg)
964 }
965
966
967 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
968   // Call the runtime to declare the globals.
969   // The context is the first argument.
970   __ mov(r1, Operand(pairs));
971   __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags())));
972   __ Push(cp, r1, r0);
973   __ CallRuntime(Runtime::kHiddenDeclareGlobals, 3);
974   // Return value is ignored.
975 }
976
977
978 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) {
979   // Call the runtime to declare the modules.
980   __ Push(descriptions);
981   __ CallRuntime(Runtime::kHiddenDeclareModules, 1);
982   // Return value is ignored.
983 }
984
985
986 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
987   Comment cmnt(masm_, "[ SwitchStatement");
988   Breakable nested_statement(this, stmt);
989   SetStatementPosition(stmt);
990
991   // Keep the switch value on the stack until a case matches.
992   VisitForStackValue(stmt->tag());
993   PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
994
995   ZoneList<CaseClause*>* clauses = stmt->cases();
996   CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
997
998   Label next_test;  // Recycled for each test.
999   // Compile all the tests with branches to their bodies.
1000   for (int i = 0; i < clauses->length(); i++) {
1001     CaseClause* clause = clauses->at(i);
1002     clause->body_target()->Unuse();
1003
1004     // The default is not a test, but remember it as final fall through.
1005     if (clause->is_default()) {
1006       default_clause = clause;
1007       continue;
1008     }
1009
1010     Comment cmnt(masm_, "[ Case comparison");
1011     __ bind(&next_test);
1012     next_test.Unuse();
1013
1014     // Compile the label expression.
1015     VisitForAccumulatorValue(clause->label());
1016
1017     // Perform the comparison as if via '==='.
1018     __ ldr(r1, MemOperand(sp, 0));  // Switch value.
1019     bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
1020     JumpPatchSite patch_site(masm_);
1021     if (inline_smi_code) {
1022       Label slow_case;
1023       __ orr(r2, r1, r0);
1024       patch_site.EmitJumpIfNotSmi(r2, &slow_case);
1025
1026       __ cmp(r1, r0);
1027       __ b(ne, &next_test);
1028       __ Drop(1);  // Switch value is no longer needed.
1029       __ b(clause->body_target());
1030       __ bind(&slow_case);
1031     }
1032
1033     // Record position before stub call for type feedback.
1034     SetSourcePosition(clause->position());
1035     Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT);
1036     CallIC(ic, clause->CompareId());
1037     patch_site.EmitPatchInfo();
1038
1039     Label skip;
1040     __ b(&skip);
1041     PrepareForBailout(clause, TOS_REG);
1042     __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1043     __ cmp(r0, ip);
1044     __ b(ne, &next_test);
1045     __ Drop(1);
1046     __ jmp(clause->body_target());
1047     __ bind(&skip);
1048
1049     __ cmp(r0, Operand::Zero());
1050     __ b(ne, &next_test);
1051     __ Drop(1);  // Switch value is no longer needed.
1052     __ b(clause->body_target());
1053   }
1054
1055   // Discard the test value and jump to the default if present, otherwise to
1056   // the end of the statement.
1057   __ bind(&next_test);
1058   __ Drop(1);  // Switch value is no longer needed.
1059   if (default_clause == NULL) {
1060     __ b(nested_statement.break_label());
1061   } else {
1062     __ b(default_clause->body_target());
1063   }
1064
1065   // Compile all the case bodies.
1066   for (int i = 0; i < clauses->length(); i++) {
1067     Comment cmnt(masm_, "[ Case body");
1068     CaseClause* clause = clauses->at(i);
1069     __ bind(clause->body_target());
1070     PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
1071     VisitStatements(clause->statements());
1072   }
1073
1074   __ bind(nested_statement.break_label());
1075   PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1076 }
1077
1078
1079 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1080   Comment cmnt(masm_, "[ ForInStatement");
1081   int slot = stmt->ForInFeedbackSlot();
1082   SetStatementPosition(stmt);
1083
1084   Label loop, exit;
1085   ForIn loop_statement(this, stmt);
1086   increment_loop_depth();
1087
1088   // Get the object to enumerate over. If the object is null or undefined, skip
1089   // over the loop.  See ECMA-262 version 5, section 12.6.4.
1090   VisitForAccumulatorValue(stmt->enumerable());
1091   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1092   __ cmp(r0, ip);
1093   __ b(eq, &exit);
1094   Register null_value = r5;
1095   __ LoadRoot(null_value, Heap::kNullValueRootIndex);
1096   __ cmp(r0, null_value);
1097   __ b(eq, &exit);
1098
1099   PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
1100
1101   // Convert the object to a JS object.
1102   Label convert, done_convert;
1103   __ JumpIfSmi(r0, &convert);
1104   __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
1105   __ b(ge, &done_convert);
1106   __ bind(&convert);
1107   __ push(r0);
1108   __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1109   __ bind(&done_convert);
1110   __ push(r0);
1111
1112   // Check for proxies.
1113   Label call_runtime;
1114   STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1115   __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE);
1116   __ b(le, &call_runtime);
1117
1118   // Check cache validity in generated code. This is a fast case for
1119   // the JSObject::IsSimpleEnum cache validity checks. If we cannot
1120   // guarantee cache validity, call the runtime system to check cache
1121   // validity or get the property names in a fixed array.
1122   __ CheckEnumCache(null_value, &call_runtime);
1123
1124   // The enum cache is valid.  Load the map of the object being
1125   // iterated over and use the cache for the iteration.
1126   Label use_cache;
1127   __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
1128   __ b(&use_cache);
1129
1130   // Get the set of properties to enumerate.
1131   __ bind(&call_runtime);
1132   __ push(r0);  // Duplicate the enumerable object on the stack.
1133   __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1134
1135   // If we got a map from the runtime call, we can do a fast
1136   // modification check. Otherwise, we got a fixed array, and we have
1137   // to do a slow check.
1138   Label fixed_array;
1139   __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
1140   __ LoadRoot(ip, Heap::kMetaMapRootIndex);
1141   __ cmp(r2, ip);
1142   __ b(ne, &fixed_array);
1143
1144   // We got a map in register r0. Get the enumeration cache from it.
1145   Label no_descriptors;
1146   __ bind(&use_cache);
1147
1148   __ EnumLength(r1, r0);
1149   __ cmp(r1, Operand(Smi::FromInt(0)));
1150   __ b(eq, &no_descriptors);
1151
1152   __ LoadInstanceDescriptors(r0, r2);
1153   __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheOffset));
1154   __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheBridgeCacheOffset));
1155
1156   // Set up the four remaining stack slots.
1157   __ push(r0);  // Map.
1158   __ mov(r0, Operand(Smi::FromInt(0)));
1159   // Push enumeration cache, enumeration cache length (as smi) and zero.
1160   __ Push(r2, r1, r0);
1161   __ jmp(&loop);
1162
1163   __ bind(&no_descriptors);
1164   __ Drop(1);
1165   __ jmp(&exit);
1166
1167   // We got a fixed array in register r0. Iterate through that.
1168   Label non_proxy;
1169   __ bind(&fixed_array);
1170
1171   __ Move(r1, FeedbackVector());
1172   __ mov(r2, Operand(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
1173   __ str(r2, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(slot)));
1174
1175   __ mov(r1, Operand(Smi::FromInt(1)));  // Smi indicates slow check
1176   __ ldr(r2, MemOperand(sp, 0 * kPointerSize));  // Get enumerated object
1177   STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1178   __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE);
1179   __ b(gt, &non_proxy);
1180   __ mov(r1, Operand(Smi::FromInt(0)));  // Zero indicates proxy
1181   __ bind(&non_proxy);
1182   __ Push(r1, r0);  // Smi and array
1183   __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset));
1184   __ mov(r0, Operand(Smi::FromInt(0)));
1185   __ Push(r1, r0);  // Fixed array length (as smi) and initial index.
1186
1187   // Generate code for doing the condition check.
1188   PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1189   __ bind(&loop);
1190   // Load the current count to r0, load the length to r1.
1191   __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
1192   __ cmp(r0, r1);  // Compare to the array length.
1193   __ b(hs, loop_statement.break_label());
1194
1195   // Get the current entry of the array into register r3.
1196   __ ldr(r2, MemOperand(sp, 2 * kPointerSize));
1197   __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1198   __ ldr(r3, MemOperand::PointerAddressFromSmiKey(r2, r0));
1199
1200   // Get the expected map from the stack or a smi in the
1201   // permanent slow case into register r2.
1202   __ ldr(r2, MemOperand(sp, 3 * kPointerSize));
1203
1204   // Check if the expected map still matches that of the enumerable.
1205   // If not, we may have to filter the key.
1206   Label update_each;
1207   __ ldr(r1, MemOperand(sp, 4 * kPointerSize));
1208   __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset));
1209   __ cmp(r4, Operand(r2));
1210   __ b(eq, &update_each);
1211
1212   // For proxies, no filtering is done.
1213   // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
1214   __ cmp(r2, Operand(Smi::FromInt(0)));
1215   __ b(eq, &update_each);
1216
1217   // Convert the entry to a string or (smi) 0 if it isn't a property
1218   // any more. If the property has been removed while iterating, we
1219   // just skip it.
1220   __ push(r1);  // Enumerable.
1221   __ push(r3);  // Current entry.
1222   __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1223   __ mov(r3, Operand(r0), SetCC);
1224   __ b(eq, loop_statement.continue_label());
1225
1226   // Update the 'each' property or variable from the possibly filtered
1227   // entry in register r3.
1228   __ bind(&update_each);
1229   __ mov(result_register(), r3);
1230   // Perform the assignment as if via '='.
1231   { EffectContext context(this);
1232     EmitAssignment(stmt->each());
1233   }
1234
1235   // Generate code for the body of the loop.
1236   Visit(stmt->body());
1237
1238   // Generate code for the going to the next element by incrementing
1239   // the index (smi) stored on top of the stack.
1240   __ bind(loop_statement.continue_label());
1241   __ pop(r0);
1242   __ add(r0, r0, Operand(Smi::FromInt(1)));
1243   __ push(r0);
1244
1245   EmitBackEdgeBookkeeping(stmt, &loop);
1246   __ b(&loop);
1247
1248   // Remove the pointers stored on the stack.
1249   __ bind(loop_statement.break_label());
1250   __ Drop(5);
1251
1252   // Exit and decrement the loop depth.
1253   PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1254   __ bind(&exit);
1255   decrement_loop_depth();
1256 }
1257
1258
1259 void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
1260   Comment cmnt(masm_, "[ ForOfStatement");
1261   SetStatementPosition(stmt);
1262
1263   Iteration loop_statement(this, stmt);
1264   increment_loop_depth();
1265
1266   // var iterator = iterable[@@iterator]()
1267   VisitForAccumulatorValue(stmt->assign_iterator());
1268
1269   // As with for-in, skip the loop if the iterator is null or undefined.
1270   __ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
1271   __ b(eq, loop_statement.break_label());
1272   __ CompareRoot(r0, Heap::kNullValueRootIndex);
1273   __ b(eq, loop_statement.break_label());
1274
1275   // Convert the iterator to a JS object.
1276   Label convert, done_convert;
1277   __ JumpIfSmi(r0, &convert);
1278   __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
1279   __ b(ge, &done_convert);
1280   __ bind(&convert);
1281   __ push(r0);
1282   __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1283   __ bind(&done_convert);
1284   __ push(r0);
1285
1286   // Loop entry.
1287   __ bind(loop_statement.continue_label());
1288
1289   // result = iterator.next()
1290   VisitForEffect(stmt->next_result());
1291
1292   // if (result.done) break;
1293   Label result_not_done;
1294   VisitForControl(stmt->result_done(),
1295                   loop_statement.break_label(),
1296                   &result_not_done,
1297                   &result_not_done);
1298   __ bind(&result_not_done);
1299
1300   // each = result.value
1301   VisitForEffect(stmt->assign_each());
1302
1303   // Generate code for the body of the loop.
1304   Visit(stmt->body());
1305
1306   // Check stack before looping.
1307   PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
1308   EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
1309   __ jmp(loop_statement.continue_label());
1310
1311   // Exit and decrement the loop depth.
1312   PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1313   __ bind(loop_statement.break_label());
1314   decrement_loop_depth();
1315 }
1316
1317
1318 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
1319                                        bool pretenure) {
1320   // Use the fast case closure allocation code that allocates in new
1321   // space for nested functions that don't need literals cloning. If
1322   // we're running with the --always-opt or the --prepare-always-opt
1323   // flag, we need to use the runtime function so that the new function
1324   // we are creating here gets a chance to have its code optimized and
1325   // doesn't just get a copy of the existing unoptimized code.
1326   if (!FLAG_always_opt &&
1327       !FLAG_prepare_always_opt &&
1328       !pretenure &&
1329       scope()->is_function_scope() &&
1330       info->num_literals() == 0) {
1331     FastNewClosureStub stub(isolate(),
1332                             info->strict_mode(),
1333                             info->is_generator());
1334     __ mov(r2, Operand(info));
1335     __ CallStub(&stub);
1336   } else {
1337     __ mov(r0, Operand(info));
1338     __ LoadRoot(r1, pretenure ? Heap::kTrueValueRootIndex
1339                               : Heap::kFalseValueRootIndex);
1340     __ Push(cp, r0, r1);
1341     __ CallRuntime(Runtime::kHiddenNewClosure, 3);
1342   }
1343   context()->Plug(r0);
1344 }
1345
1346
1347 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
1348   Comment cmnt(masm_, "[ VariableProxy");
1349   EmitVariableLoad(expr);
1350 }
1351
1352
1353 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
1354                                                       TypeofState typeof_state,
1355                                                       Label* slow) {
1356   Register current = cp;
1357   Register next = r1;
1358   Register temp = r2;
1359
1360   Scope* s = scope();
1361   while (s != NULL) {
1362     if (s->num_heap_slots() > 0) {
1363       if (s->calls_sloppy_eval()) {
1364         // Check that extension is NULL.
1365         __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX));
1366         __ tst(temp, temp);
1367         __ b(ne, slow);
1368       }
1369       // Load next context in chain.
1370       __ ldr(next, ContextOperand(current, Context::PREVIOUS_INDEX));
1371       // Walk the rest of the chain without clobbering cp.
1372       current = next;
1373     }
1374     // If no outer scope calls eval, we do not need to check more
1375     // context extensions.
1376     if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break;
1377     s = s->outer_scope();
1378   }
1379
1380   if (s->is_eval_scope()) {
1381     Label loop, fast;
1382     if (!current.is(next)) {
1383       __ Move(next, current);
1384     }
1385     __ bind(&loop);
1386     // Terminate at native context.
1387     __ ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset));
1388     __ LoadRoot(ip, Heap::kNativeContextMapRootIndex);
1389     __ cmp(temp, ip);
1390     __ b(eq, &fast);
1391     // Check that extension is NULL.
1392     __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX));
1393     __ tst(temp, temp);
1394     __ b(ne, slow);
1395     // Load next context in chain.
1396     __ ldr(next, ContextOperand(next, Context::PREVIOUS_INDEX));
1397     __ b(&loop);
1398     __ bind(&fast);
1399   }
1400
1401   __ ldr(r0, GlobalObjectOperand());
1402   __ mov(r2, Operand(var->name()));
1403   ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
1404       ? NOT_CONTEXTUAL
1405       : CONTEXTUAL;
1406   CallLoadIC(mode);
1407 }
1408
1409
1410 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1411                                                                 Label* slow) {
1412   ASSERT(var->IsContextSlot());
1413   Register context = cp;
1414   Register next = r3;
1415   Register temp = r4;
1416
1417   for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
1418     if (s->num_heap_slots() > 0) {
1419       if (s->calls_sloppy_eval()) {
1420         // Check that extension is NULL.
1421         __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX));
1422         __ tst(temp, temp);
1423         __ b(ne, slow);
1424       }
1425       __ ldr(next, ContextOperand(context, Context::PREVIOUS_INDEX));
1426       // Walk the rest of the chain without clobbering cp.
1427       context = next;
1428     }
1429   }
1430   // Check that last extension is NULL.
1431   __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX));
1432   __ tst(temp, temp);
1433   __ b(ne, slow);
1434
1435   // This function is used only for loads, not stores, so it's safe to
1436   // return an cp-based operand (the write barrier cannot be allowed to
1437   // destroy the cp register).
1438   return ContextOperand(context, var->index());
1439 }
1440
1441
1442 void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
1443                                                   TypeofState typeof_state,
1444                                                   Label* slow,
1445                                                   Label* done) {
1446   // Generate fast-case code for variables that might be shadowed by
1447   // eval-introduced variables.  Eval is used a lot without
1448   // introducing variables.  In those cases, we do not want to
1449   // perform a runtime call for all variables in the scope
1450   // containing the eval.
1451   if (var->mode() == DYNAMIC_GLOBAL) {
1452     EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
1453     __ jmp(done);
1454   } else if (var->mode() == DYNAMIC_LOCAL) {
1455     Variable* local = var->local_if_not_shadowed();
1456     __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow));
1457     if (local->mode() == LET || local->mode() == CONST ||
1458         local->mode() == CONST_LEGACY) {
1459       __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
1460       if (local->mode() == CONST_LEGACY) {
1461         __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
1462       } else {  // LET || CONST
1463         __ b(ne, done);
1464         __ mov(r0, Operand(var->name()));
1465         __ push(r0);
1466         __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1);
1467       }
1468     }
1469     __ jmp(done);
1470   }
1471 }
1472
1473
1474 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
1475   // Record position before possible IC call.
1476   SetSourcePosition(proxy->position());
1477   Variable* var = proxy->var();
1478
1479   // Three cases: global variables, lookup variables, and all other types of
1480   // variables.
1481   switch (var->location()) {
1482     case Variable::UNALLOCATED: {
1483       Comment cmnt(masm_, "[ Global variable");
1484       // Use inline caching. Variable name is passed in r2 and the global
1485       // object (receiver) in r0.
1486       __ ldr(r0, GlobalObjectOperand());
1487       __ mov(r2, Operand(var->name()));
1488       CallLoadIC(CONTEXTUAL);
1489       context()->Plug(r0);
1490       break;
1491     }
1492
1493     case Variable::PARAMETER:
1494     case Variable::LOCAL:
1495     case Variable::CONTEXT: {
1496       Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
1497                                                : "[ Stack variable");
1498       if (var->binding_needs_init()) {
1499         // var->scope() may be NULL when the proxy is located in eval code and
1500         // refers to a potential outside binding. Currently those bindings are
1501         // always looked up dynamically, i.e. in that case
1502         //     var->location() == LOOKUP.
1503         // always holds.
1504         ASSERT(var->scope() != NULL);
1505
1506         // Check if the binding really needs an initialization check. The check
1507         // can be skipped in the following situation: we have a LET or CONST
1508         // binding in harmony mode, both the Variable and the VariableProxy have
1509         // the same declaration scope (i.e. they are both in global code, in the
1510         // same function or in the same eval code) and the VariableProxy is in
1511         // the source physically located after the initializer of the variable.
1512         //
1513         // We cannot skip any initialization checks for CONST in non-harmony
1514         // mode because const variables may be declared but never initialized:
1515         //   if (false) { const x; }; var y = x;
1516         //
1517         // The condition on the declaration scopes is a conservative check for
1518         // nested functions that access a binding and are called before the
1519         // binding is initialized:
1520         //   function() { f(); let x = 1; function f() { x = 2; } }
1521         //
1522         bool skip_init_check;
1523         if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
1524           skip_init_check = false;
1525         } else {
1526           // Check that we always have valid source position.
1527           ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
1528           ASSERT(proxy->position() != RelocInfo::kNoPosition);
1529           skip_init_check = var->mode() != CONST_LEGACY &&
1530               var->initializer_position() < proxy->position();
1531         }
1532
1533         if (!skip_init_check) {
1534           // Let and const need a read barrier.
1535           GetVar(r0, var);
1536           __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
1537           if (var->mode() == LET || var->mode() == CONST) {
1538             // Throw a reference error when using an uninitialized let/const
1539             // binding in harmony mode.
1540             Label done;
1541             __ b(ne, &done);
1542             __ mov(r0, Operand(var->name()));
1543             __ push(r0);
1544             __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1);
1545             __ bind(&done);
1546           } else {
1547             // Uninitalized const bindings outside of harmony mode are unholed.
1548             ASSERT(var->mode() == CONST_LEGACY);
1549             __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
1550           }
1551           context()->Plug(r0);
1552           break;
1553         }
1554       }
1555       context()->Plug(var);
1556       break;
1557     }
1558
1559     case Variable::LOOKUP: {
1560       Comment cmnt(masm_, "[ Lookup variable");
1561       Label done, slow;
1562       // Generate code for loading from variables potentially shadowed
1563       // by eval-introduced variables.
1564       EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
1565       __ bind(&slow);
1566       __ mov(r1, Operand(var->name()));
1567       __ Push(cp, r1);  // Context and name.
1568       __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2);
1569       __ bind(&done);
1570       context()->Plug(r0);
1571     }
1572   }
1573 }
1574
1575
1576 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1577   Comment cmnt(masm_, "[ RegExpLiteral");
1578   Label materialized;
1579   // Registers will be used as follows:
1580   // r5 = materialized value (RegExp literal)
1581   // r4 = JS function, literals array
1582   // r3 = literal index
1583   // r2 = RegExp pattern
1584   // r1 = RegExp flags
1585   // r0 = RegExp literal clone
1586   __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1587   __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
1588   int literal_offset =
1589       FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1590   __ ldr(r5, FieldMemOperand(r4, literal_offset));
1591   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1592   __ cmp(r5, ip);
1593   __ b(ne, &materialized);
1594
1595   // Create regexp literal using runtime function.
1596   // Result will be in r0.
1597   __ mov(r3, Operand(Smi::FromInt(expr->literal_index())));
1598   __ mov(r2, Operand(expr->pattern()));
1599   __ mov(r1, Operand(expr->flags()));
1600   __ Push(r4, r3, r2, r1);
1601   __ CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4);
1602   __ mov(r5, r0);
1603
1604   __ bind(&materialized);
1605   int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1606   Label allocated, runtime_allocate;
1607   __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT);
1608   __ jmp(&allocated);
1609
1610   __ bind(&runtime_allocate);
1611   __ mov(r0, Operand(Smi::FromInt(size)));
1612   __ Push(r5, r0);
1613   __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1);
1614   __ pop(r5);
1615
1616   __ bind(&allocated);
1617   // After this, registers are used as follows:
1618   // r0: Newly allocated regexp.
1619   // r5: Materialized regexp.
1620   // r2: temp.
1621   __ CopyFields(r0, r5, d0, size / kPointerSize);
1622   context()->Plug(r0);
1623 }
1624
1625
1626 void FullCodeGenerator::EmitAccessor(Expression* expression) {
1627   if (expression == NULL) {
1628     __ LoadRoot(r1, Heap::kNullValueRootIndex);
1629     __ push(r1);
1630   } else {
1631     VisitForStackValue(expression);
1632   }
1633 }
1634
1635
1636 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1637   Comment cmnt(masm_, "[ ObjectLiteral");
1638
1639   expr->BuildConstantProperties(isolate());
1640   Handle<FixedArray> constant_properties = expr->constant_properties();
1641   __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1642   __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
1643   __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
1644   __ mov(r1, Operand(constant_properties));
1645   int flags = expr->fast_elements()
1646       ? ObjectLiteral::kFastElements
1647       : ObjectLiteral::kNoFlags;
1648   flags |= expr->has_function()
1649       ? ObjectLiteral::kHasFunction
1650       : ObjectLiteral::kNoFlags;
1651   __ mov(r0, Operand(Smi::FromInt(flags)));
1652   int properties_count = constant_properties->length() / 2;
1653   if (expr->may_store_doubles() || expr->depth() > 1 ||
1654       Serializer::enabled(isolate()) || flags != ObjectLiteral::kFastElements ||
1655       properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
1656     __ Push(r3, r2, r1, r0);
1657     __ CallRuntime(Runtime::kHiddenCreateObjectLiteral, 4);
1658   } else {
1659     FastCloneShallowObjectStub stub(isolate(), properties_count);
1660     __ CallStub(&stub);
1661   }
1662
1663   // If result_saved is true the result is on top of the stack.  If
1664   // result_saved is false the result is in r0.
1665   bool result_saved = false;
1666
1667   // Mark all computed expressions that are bound to a key that
1668   // is shadowed by a later occurrence of the same key. For the
1669   // marked expressions, no store code is emitted.
1670   expr->CalculateEmitStore(zone());
1671
1672   AccessorTable accessor_table(zone());
1673   for (int i = 0; i < expr->properties()->length(); i++) {
1674     ObjectLiteral::Property* property = expr->properties()->at(i);
1675     if (property->IsCompileTimeValue()) continue;
1676
1677     Literal* key = property->key();
1678     Expression* value = property->value();
1679     if (!result_saved) {
1680       __ push(r0);  // Save result on stack
1681       result_saved = true;
1682     }
1683     switch (property->kind()) {
1684       case ObjectLiteral::Property::CONSTANT:
1685         UNREACHABLE();
1686       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1687         ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value()));
1688         // Fall through.
1689       case ObjectLiteral::Property::COMPUTED:
1690         if (key->value()->IsInternalizedString()) {
1691           if (property->emit_store()) {
1692             VisitForAccumulatorValue(value);
1693             __ mov(r2, Operand(key->value()));
1694             __ ldr(r1, MemOperand(sp));
1695             CallStoreIC(key->LiteralFeedbackId());
1696             PrepareForBailoutForId(key->id(), NO_REGISTERS);
1697           } else {
1698             VisitForEffect(value);
1699           }
1700           break;
1701         }
1702         // Duplicate receiver on stack.
1703         __ ldr(r0, MemOperand(sp));
1704         __ push(r0);
1705         VisitForStackValue(key);
1706         VisitForStackValue(value);
1707         if (property->emit_store()) {
1708           __ mov(r0, Operand(Smi::FromInt(NONE)));  // PropertyAttributes
1709           __ push(r0);
1710           __ CallRuntime(Runtime::kSetProperty, 4);
1711         } else {
1712           __ Drop(3);
1713         }
1714         break;
1715       case ObjectLiteral::Property::PROTOTYPE:
1716         // Duplicate receiver on stack.
1717         __ ldr(r0, MemOperand(sp));
1718         __ push(r0);
1719         VisitForStackValue(value);
1720         if (property->emit_store()) {
1721           __ CallRuntime(Runtime::kSetPrototype, 2);
1722         } else {
1723           __ Drop(2);
1724         }
1725         break;
1726
1727       case ObjectLiteral::Property::GETTER:
1728         accessor_table.lookup(key)->second->getter = value;
1729         break;
1730       case ObjectLiteral::Property::SETTER:
1731         accessor_table.lookup(key)->second->setter = value;
1732         break;
1733     }
1734   }
1735
1736   // Emit code to define accessors, using only a single call to the runtime for
1737   // each pair of corresponding getters and setters.
1738   for (AccessorTable::Iterator it = accessor_table.begin();
1739        it != accessor_table.end();
1740        ++it) {
1741     __ ldr(r0, MemOperand(sp));  // Duplicate receiver.
1742     __ push(r0);
1743     VisitForStackValue(it->first);
1744     EmitAccessor(it->second->getter);
1745     EmitAccessor(it->second->setter);
1746     __ mov(r0, Operand(Smi::FromInt(NONE)));
1747     __ push(r0);
1748     __ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
1749   }
1750
1751   if (expr->has_function()) {
1752     ASSERT(result_saved);
1753     __ ldr(r0, MemOperand(sp));
1754     __ push(r0);
1755     __ CallRuntime(Runtime::kToFastProperties, 1);
1756   }
1757
1758   if (result_saved) {
1759     context()->PlugTOS();
1760   } else {
1761     context()->Plug(r0);
1762   }
1763 }
1764
1765
1766 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1767   Comment cmnt(masm_, "[ ArrayLiteral");
1768
1769   expr->BuildConstantElements(isolate());
1770   int flags = expr->depth() == 1
1771       ? ArrayLiteral::kShallowElements
1772       : ArrayLiteral::kNoFlags;
1773
1774   ZoneList<Expression*>* subexprs = expr->values();
1775   int length = subexprs->length();
1776   Handle<FixedArray> constant_elements = expr->constant_elements();
1777   ASSERT_EQ(2, constant_elements->length());
1778   ElementsKind constant_elements_kind =
1779       static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
1780   bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind);
1781   Handle<FixedArrayBase> constant_elements_values(
1782       FixedArrayBase::cast(constant_elements->get(1)));
1783
1784   AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1785   if (has_fast_elements && !FLAG_allocation_site_pretenuring) {
1786     // If the only customer of allocation sites is transitioning, then
1787     // we can turn it off if we don't have anywhere else to transition to.
1788     allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1789   }
1790
1791   __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1792   __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
1793   __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
1794   __ mov(r1, Operand(constant_elements));
1795   if (has_fast_elements && constant_elements_values->map() ==
1796       isolate()->heap()->fixed_cow_array_map()) {
1797     FastCloneShallowArrayStub stub(
1798         isolate(),
1799         FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS,
1800         allocation_site_mode,
1801         length);
1802     __ CallStub(&stub);
1803     __ IncrementCounter(
1804         isolate()->counters()->cow_arrays_created_stub(), 1, r1, r2);
1805   } else if (expr->depth() > 1 || Serializer::enabled(isolate()) ||
1806              length > FastCloneShallowArrayStub::kMaximumClonedLength) {
1807     __ mov(r0, Operand(Smi::FromInt(flags)));
1808     __ Push(r3, r2, r1, r0);
1809     __ CallRuntime(Runtime::kHiddenCreateArrayLiteral, 4);
1810   } else {
1811     ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) ||
1812            FLAG_smi_only_arrays);
1813     FastCloneShallowArrayStub::Mode mode =
1814         FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS;
1815
1816     if (has_fast_elements) {
1817       mode = FastCloneShallowArrayStub::CLONE_ELEMENTS;
1818     }
1819
1820     FastCloneShallowArrayStub stub(isolate(), mode, allocation_site_mode,
1821                                    length);
1822     __ CallStub(&stub);
1823   }
1824
1825   bool result_saved = false;  // Is the result saved to the stack?
1826
1827   // Emit code to evaluate all the non-constant subexpressions and to store
1828   // them into the newly cloned array.
1829   for (int i = 0; i < length; i++) {
1830     Expression* subexpr = subexprs->at(i);
1831     // If the subexpression is a literal or a simple materialized literal it
1832     // is already set in the cloned array.
1833     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1834
1835     if (!result_saved) {
1836       __ push(r0);
1837       __ Push(Smi::FromInt(expr->literal_index()));
1838       result_saved = true;
1839     }
1840     VisitForAccumulatorValue(subexpr);
1841
1842     if (IsFastObjectElementsKind(constant_elements_kind)) {
1843       int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1844       __ ldr(r6, MemOperand(sp, kPointerSize));  // Copy of array literal.
1845       __ ldr(r1, FieldMemOperand(r6, JSObject::kElementsOffset));
1846       __ str(result_register(), FieldMemOperand(r1, offset));
1847       // Update the write barrier for the array store.
1848       __ RecordWriteField(r1, offset, result_register(), r2,
1849                           kLRHasBeenSaved, kDontSaveFPRegs,
1850                           EMIT_REMEMBERED_SET, INLINE_SMI_CHECK);
1851     } else {
1852       __ mov(r3, Operand(Smi::FromInt(i)));
1853       StoreArrayLiteralElementStub stub(isolate());
1854       __ CallStub(&stub);
1855     }
1856
1857     PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
1858   }
1859
1860   if (result_saved) {
1861     __ pop();  // literal index
1862     context()->PlugTOS();
1863   } else {
1864     context()->Plug(r0);
1865   }
1866 }
1867
1868
1869 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1870   ASSERT(expr->target()->IsValidReferenceExpression());
1871
1872   Comment cmnt(masm_, "[ Assignment");
1873
1874   // Left-hand side can only be a property, a global or a (parameter or local)
1875   // slot.
1876   enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1877   LhsKind assign_type = VARIABLE;
1878   Property* property = expr->target()->AsProperty();
1879   if (property != NULL) {
1880     assign_type = (property->key()->IsPropertyName())
1881         ? NAMED_PROPERTY
1882         : KEYED_PROPERTY;
1883   }
1884
1885   // Evaluate LHS expression.
1886   switch (assign_type) {
1887     case VARIABLE:
1888       // Nothing to do here.
1889       break;
1890     case NAMED_PROPERTY:
1891       if (expr->is_compound()) {
1892         // We need the receiver both on the stack and in the accumulator.
1893         VisitForAccumulatorValue(property->obj());
1894         __ push(result_register());
1895       } else {
1896         VisitForStackValue(property->obj());
1897       }
1898       break;
1899     case KEYED_PROPERTY:
1900       if (expr->is_compound()) {
1901         VisitForStackValue(property->obj());
1902         VisitForAccumulatorValue(property->key());
1903         __ ldr(r1, MemOperand(sp, 0));
1904         __ push(r0);
1905       } else {
1906         VisitForStackValue(property->obj());
1907         VisitForStackValue(property->key());
1908       }
1909       break;
1910   }
1911
1912   // For compound assignments we need another deoptimization point after the
1913   // variable/property load.
1914   if (expr->is_compound()) {
1915     { AccumulatorValueContext context(this);
1916       switch (assign_type) {
1917         case VARIABLE:
1918           EmitVariableLoad(expr->target()->AsVariableProxy());
1919           PrepareForBailout(expr->target(), TOS_REG);
1920           break;
1921         case NAMED_PROPERTY:
1922           EmitNamedPropertyLoad(property);
1923           PrepareForBailoutForId(property->LoadId(), TOS_REG);
1924           break;
1925         case KEYED_PROPERTY:
1926           EmitKeyedPropertyLoad(property);
1927           PrepareForBailoutForId(property->LoadId(), TOS_REG);
1928           break;
1929       }
1930     }
1931
1932     Token::Value op = expr->binary_op();
1933     __ push(r0);  // Left operand goes on the stack.
1934     VisitForAccumulatorValue(expr->value());
1935
1936     OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
1937         ? OVERWRITE_RIGHT
1938         : NO_OVERWRITE;
1939     SetSourcePosition(expr->position() + 1);
1940     AccumulatorValueContext context(this);
1941     if (ShouldInlineSmiCase(op)) {
1942       EmitInlineSmiBinaryOp(expr->binary_operation(),
1943                             op,
1944                             mode,
1945                             expr->target(),
1946                             expr->value());
1947     } else {
1948       EmitBinaryOp(expr->binary_operation(), op, mode);
1949     }
1950
1951     // Deoptimization point in case the binary operation may have side effects.
1952     PrepareForBailout(expr->binary_operation(), TOS_REG);
1953   } else {
1954     VisitForAccumulatorValue(expr->value());
1955   }
1956
1957   // Record source position before possible IC call.
1958   SetSourcePosition(expr->position());
1959
1960   // Store the value.
1961   switch (assign_type) {
1962     case VARIABLE:
1963       EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1964                              expr->op());
1965       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1966       context()->Plug(r0);
1967       break;
1968     case NAMED_PROPERTY:
1969       EmitNamedPropertyAssignment(expr);
1970       break;
1971     case KEYED_PROPERTY:
1972       EmitKeyedPropertyAssignment(expr);
1973       break;
1974   }
1975 }
1976
1977
1978 void FullCodeGenerator::VisitYield(Yield* expr) {
1979   Comment cmnt(masm_, "[ Yield");
1980   // Evaluate yielded value first; the initial iterator definition depends on
1981   // this.  It stays on the stack while we update the iterator.
1982   VisitForStackValue(expr->expression());
1983
1984   switch (expr->yield_kind()) {
1985     case Yield::SUSPEND:
1986       // Pop value from top-of-stack slot; box result into result register.
1987       EmitCreateIteratorResult(false);
1988       __ push(result_register());
1989       // Fall through.
1990     case Yield::INITIAL: {
1991       Label suspend, continuation, post_runtime, resume;
1992
1993       __ jmp(&suspend);
1994
1995       __ bind(&continuation);
1996       __ jmp(&resume);
1997
1998       __ bind(&suspend);
1999       VisitForAccumulatorValue(expr->generator_object());
2000       ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
2001       __ mov(r1, Operand(Smi::FromInt(continuation.pos())));
2002       __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset));
2003       __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset));
2004       __ mov(r1, cp);
2005       __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2,
2006                           kLRHasBeenSaved, kDontSaveFPRegs);
2007       __ add(r1, fp, Operand(StandardFrameConstants::kExpressionsOffset));
2008       __ cmp(sp, r1);
2009       __ b(eq, &post_runtime);
2010       __ push(r0);  // generator object
2011       __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1);
2012       __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2013       __ bind(&post_runtime);
2014       __ pop(result_register());
2015       EmitReturnSequence();
2016
2017       __ bind(&resume);
2018       context()->Plug(result_register());
2019       break;
2020     }
2021
2022     case Yield::FINAL: {
2023       VisitForAccumulatorValue(expr->generator_object());
2024       __ mov(r1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
2025       __ str(r1, FieldMemOperand(result_register(),
2026                                  JSGeneratorObject::kContinuationOffset));
2027       // Pop value from top-of-stack slot, box result into result register.
2028       EmitCreateIteratorResult(true);
2029       EmitUnwindBeforeReturn();
2030       EmitReturnSequence();
2031       break;
2032     }
2033
2034     case Yield::DELEGATING: {
2035       VisitForStackValue(expr->generator_object());
2036
2037       // Initial stack layout is as follows:
2038       // [sp + 1 * kPointerSize] iter
2039       // [sp + 0 * kPointerSize] g
2040
2041       Label l_catch, l_try, l_suspend, l_continuation, l_resume;
2042       Label l_next, l_call, l_loop;
2043       // Initial send value is undefined.
2044       __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
2045       __ b(&l_next);
2046
2047       // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
2048       __ bind(&l_catch);
2049       handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
2050       __ LoadRoot(r2, Heap::kthrow_stringRootIndex);  // "throw"
2051       __ ldr(r3, MemOperand(sp, 1 * kPointerSize));   // iter
2052       __ Push(r2, r3, r0);                            // "throw", iter, except
2053       __ jmp(&l_call);
2054
2055       // try { received = %yield result }
2056       // Shuffle the received result above a try handler and yield it without
2057       // re-boxing.
2058       __ bind(&l_try);
2059       __ pop(r0);                                        // result
2060       __ PushTryHandler(StackHandler::CATCH, expr->index());
2061       const int handler_size = StackHandlerConstants::kSize;
2062       __ push(r0);                                       // result
2063       __ jmp(&l_suspend);
2064       __ bind(&l_continuation);
2065       __ jmp(&l_resume);
2066       __ bind(&l_suspend);
2067       const int generator_object_depth = kPointerSize + handler_size;
2068       __ ldr(r0, MemOperand(sp, generator_object_depth));
2069       __ push(r0);                                       // g
2070       ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
2071       __ mov(r1, Operand(Smi::FromInt(l_continuation.pos())));
2072       __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset));
2073       __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset));
2074       __ mov(r1, cp);
2075       __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2,
2076                           kLRHasBeenSaved, kDontSaveFPRegs);
2077       __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1);
2078       __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2079       __ pop(r0);                                      // result
2080       EmitReturnSequence();
2081       __ bind(&l_resume);                              // received in r0
2082       __ PopTryHandler();
2083
2084       // receiver = iter; f = 'next'; arg = received;
2085       __ bind(&l_next);
2086       __ LoadRoot(r2, Heap::knext_stringRootIndex);    // "next"
2087       __ ldr(r3, MemOperand(sp, 1 * kPointerSize));    // iter
2088       __ Push(r2, r3, r0);                             // "next", iter, received
2089
2090       // result = receiver[f](arg);
2091       __ bind(&l_call);
2092       __ ldr(r1, MemOperand(sp, kPointerSize));
2093       __ ldr(r0, MemOperand(sp, 2 * kPointerSize));
2094       Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2095       CallIC(ic, TypeFeedbackId::None());
2096       __ mov(r1, r0);
2097       __ str(r1, MemOperand(sp, 2 * kPointerSize));
2098       CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
2099       __ CallStub(&stub);
2100
2101       __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2102       __ Drop(1);  // The function is still on the stack; drop it.
2103
2104       // if (!result.done) goto l_try;
2105       __ bind(&l_loop);
2106       __ push(r0);                                       // save result
2107       __ LoadRoot(r2, Heap::kdone_stringRootIndex);      // "done"
2108       CallLoadIC(NOT_CONTEXTUAL);                        // result.done in r0
2109       Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
2110       CallIC(bool_ic);
2111       __ cmp(r0, Operand(0));
2112       __ b(eq, &l_try);
2113
2114       // result.value
2115       __ pop(r0);                                        // result
2116       __ LoadRoot(r2, Heap::kvalue_stringRootIndex);     // "value"
2117       CallLoadIC(NOT_CONTEXTUAL);                        // result.value in r0
2118       context()->DropAndPlug(2, r0);                     // drop iter and g
2119       break;
2120     }
2121   }
2122 }
2123
2124
2125 void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
2126     Expression *value,
2127     JSGeneratorObject::ResumeMode resume_mode) {
2128   // The value stays in r0, and is ultimately read by the resumed generator, as
2129   // if CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject) returned it. Or it
2130   // is read to throw the value when the resumed generator is already closed.
2131   // r1 will hold the generator object until the activation has been resumed.
2132   VisitForStackValue(generator);
2133   VisitForAccumulatorValue(value);
2134   __ pop(r1);
2135
2136   // Check generator state.
2137   Label wrong_state, closed_state, done;
2138   __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset));
2139   STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
2140   STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
2141   __ cmp(r3, Operand(Smi::FromInt(0)));
2142   __ b(eq, &closed_state);
2143   __ b(lt, &wrong_state);
2144
2145   // Load suspended function and context.
2146   __ ldr(cp, FieldMemOperand(r1, JSGeneratorObject::kContextOffset));
2147   __ ldr(r4, FieldMemOperand(r1, JSGeneratorObject::kFunctionOffset));
2148
2149   // Load receiver and store as the first argument.
2150   __ ldr(r2, FieldMemOperand(r1, JSGeneratorObject::kReceiverOffset));
2151   __ push(r2);
2152
2153   // Push holes for the rest of the arguments to the generator function.
2154   __ ldr(r3, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
2155   __ ldr(r3,
2156          FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
2157   __ LoadRoot(r2, Heap::kTheHoleValueRootIndex);
2158   Label push_argument_holes, push_frame;
2159   __ bind(&push_argument_holes);
2160   __ sub(r3, r3, Operand(Smi::FromInt(1)), SetCC);
2161   __ b(mi, &push_frame);
2162   __ push(r2);
2163   __ jmp(&push_argument_holes);
2164
2165   // Enter a new JavaScript frame, and initialize its slots as they were when
2166   // the generator was suspended.
2167   Label resume_frame;
2168   __ bind(&push_frame);
2169   __ bl(&resume_frame);
2170   __ jmp(&done);
2171   __ bind(&resume_frame);
2172   // lr = return address.
2173   // fp = caller's frame pointer.
2174   // pp = caller's constant pool (if FLAG_enable_ool_constant_pool),
2175   // cp = callee's context,
2176   // r4 = callee's JS function.
2177   __ PushFixedFrame(r4);
2178   // Adjust FP to point to saved FP.
2179   __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
2180
2181   // Load the operand stack size.
2182   __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset));
2183   __ ldr(r3, FieldMemOperand(r3, FixedArray::kLengthOffset));
2184   __ SmiUntag(r3);
2185
2186   // If we are sending a value and there is no operand stack, we can jump back
2187   // in directly.
2188   if (resume_mode == JSGeneratorObject::NEXT) {
2189     Label slow_resume;
2190     __ cmp(r3, Operand(0));
2191     __ b(ne, &slow_resume);
2192     __ ldr(r3, FieldMemOperand(r4, JSFunction::kCodeEntryOffset));
2193
2194     { ConstantPoolUnavailableScope constant_pool_unavailable(masm_);
2195       if (FLAG_enable_ool_constant_pool) {
2196         // Load the new code object's constant pool pointer.
2197         __ ldr(pp,
2198                MemOperand(r3, Code::kConstantPoolOffset - Code::kHeaderSize));
2199       }
2200
2201       __ ldr(r2, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset));
2202       __ SmiUntag(r2);
2203       __ add(r3, r3, r2);
2204       __ mov(r2, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
2205       __ str(r2, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset));
2206       __ Jump(r3);
2207     }
2208     __ bind(&slow_resume);
2209   }
2210
2211   // Otherwise, we push holes for the operand stack and call the runtime to fix
2212   // up the stack and the handlers.
2213   Label push_operand_holes, call_resume;
2214   __ bind(&push_operand_holes);
2215   __ sub(r3, r3, Operand(1), SetCC);
2216   __ b(mi, &call_resume);
2217   __ push(r2);
2218   __ b(&push_operand_holes);
2219   __ bind(&call_resume);
2220   ASSERT(!result_register().is(r1));
2221   __ Push(r1, result_register());
2222   __ Push(Smi::FromInt(resume_mode));
2223   __ CallRuntime(Runtime::kHiddenResumeJSGeneratorObject, 3);
2224   // Not reached: the runtime call returns elsewhere.
2225   __ stop("not-reached");
2226
2227   // Reach here when generator is closed.
2228   __ bind(&closed_state);
2229   if (resume_mode == JSGeneratorObject::NEXT) {
2230     // Return completed iterator result when generator is closed.
2231     __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
2232     __ push(r2);
2233     // Pop value from top-of-stack slot; box result into result register.
2234     EmitCreateIteratorResult(true);
2235   } else {
2236     // Throw the provided value.
2237     __ push(r0);
2238     __ CallRuntime(Runtime::kHiddenThrow, 1);
2239   }
2240   __ jmp(&done);
2241
2242   // Throw error if we attempt to operate on a running generator.
2243   __ bind(&wrong_state);
2244   __ push(r1);
2245   __ CallRuntime(Runtime::kHiddenThrowGeneratorStateError, 1);
2246
2247   __ bind(&done);
2248   context()->Plug(result_register());
2249 }
2250
2251
2252 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
2253   Label gc_required;
2254   Label allocated;
2255
2256   Handle<Map> map(isolate()->native_context()->iterator_result_map());
2257
2258   __ Allocate(map->instance_size(), r0, r2, r3, &gc_required, TAG_OBJECT);
2259   __ jmp(&allocated);
2260
2261   __ bind(&gc_required);
2262   __ Push(Smi::FromInt(map->instance_size()));
2263   __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1);
2264   __ ldr(context_register(),
2265          MemOperand(fp, StandardFrameConstants::kContextOffset));
2266
2267   __ bind(&allocated);
2268   __ mov(r1, Operand(map));
2269   __ pop(r2);
2270   __ mov(r3, Operand(isolate()->factory()->ToBoolean(done)));
2271   __ mov(r4, Operand(isolate()->factory()->empty_fixed_array()));
2272   ASSERT_EQ(map->instance_size(), 5 * kPointerSize);
2273   __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2274   __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset));
2275   __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
2276   __ str(r2,
2277          FieldMemOperand(r0, JSGeneratorObject::kResultValuePropertyOffset));
2278   __ str(r3,
2279          FieldMemOperand(r0, JSGeneratorObject::kResultDonePropertyOffset));
2280
2281   // Only the value field needs a write barrier, as the other values are in the
2282   // root set.
2283   __ RecordWriteField(r0, JSGeneratorObject::kResultValuePropertyOffset,
2284                       r2, r3, kLRHasBeenSaved, kDontSaveFPRegs);
2285 }
2286
2287
2288 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
2289   SetSourcePosition(prop->position());
2290   Literal* key = prop->key()->AsLiteral();
2291   __ mov(r2, Operand(key->value()));
2292   // Call load IC. It has arguments receiver and property name r0 and r2.
2293   CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
2294 }
2295
2296
2297 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
2298   SetSourcePosition(prop->position());
2299   // Call keyed load IC. It has arguments key and receiver in r0 and r1.
2300   Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2301   CallIC(ic, prop->PropertyFeedbackId());
2302 }
2303
2304
2305 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
2306                                               Token::Value op,
2307                                               OverwriteMode mode,
2308                                               Expression* left_expr,
2309                                               Expression* right_expr) {
2310   Label done, smi_case, stub_call;
2311
2312   Register scratch1 = r2;
2313   Register scratch2 = r3;
2314
2315   // Get the arguments.
2316   Register left = r1;
2317   Register right = r0;
2318   __ pop(left);
2319
2320   // Perform combined smi check on both operands.
2321   __ orr(scratch1, left, Operand(right));
2322   STATIC_ASSERT(kSmiTag == 0);
2323   JumpPatchSite patch_site(masm_);
2324   patch_site.EmitJumpIfSmi(scratch1, &smi_case);
2325
2326   __ bind(&stub_call);
2327   BinaryOpICStub stub(isolate(), op, mode);
2328   CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId());
2329   patch_site.EmitPatchInfo();
2330   __ jmp(&done);
2331
2332   __ bind(&smi_case);
2333   // Smi case. This code works the same way as the smi-smi case in the type
2334   // recording binary operation stub, see
2335   switch (op) {
2336     case Token::SAR:
2337       __ GetLeastBitsFromSmi(scratch1, right, 5);
2338       __ mov(right, Operand(left, ASR, scratch1));
2339       __ bic(right, right, Operand(kSmiTagMask));
2340       break;
2341     case Token::SHL: {
2342       __ SmiUntag(scratch1, left);
2343       __ GetLeastBitsFromSmi(scratch2, right, 5);
2344       __ mov(scratch1, Operand(scratch1, LSL, scratch2));
2345       __ TrySmiTag(right, scratch1, &stub_call);
2346       break;
2347     }
2348     case Token::SHR: {
2349       __ SmiUntag(scratch1, left);
2350       __ GetLeastBitsFromSmi(scratch2, right, 5);
2351       __ mov(scratch1, Operand(scratch1, LSR, scratch2));
2352       __ tst(scratch1, Operand(0xc0000000));
2353       __ b(ne, &stub_call);
2354       __ SmiTag(right, scratch1);
2355       break;
2356     }
2357     case Token::ADD:
2358       __ add(scratch1, left, Operand(right), SetCC);
2359       __ b(vs, &stub_call);
2360       __ mov(right, scratch1);
2361       break;
2362     case Token::SUB:
2363       __ sub(scratch1, left, Operand(right), SetCC);
2364       __ b(vs, &stub_call);
2365       __ mov(right, scratch1);
2366       break;
2367     case Token::MUL: {
2368       __ SmiUntag(ip, right);
2369       __ smull(scratch1, scratch2, left, ip);
2370       __ mov(ip, Operand(scratch1, ASR, 31));
2371       __ cmp(ip, Operand(scratch2));
2372       __ b(ne, &stub_call);
2373       __ cmp(scratch1, Operand::Zero());
2374       __ mov(right, Operand(scratch1), LeaveCC, ne);
2375       __ b(ne, &done);
2376       __ add(scratch2, right, Operand(left), SetCC);
2377       __ mov(right, Operand(Smi::FromInt(0)), LeaveCC, pl);
2378       __ b(mi, &stub_call);
2379       break;
2380     }
2381     case Token::BIT_OR:
2382       __ orr(right, left, Operand(right));
2383       break;
2384     case Token::BIT_AND:
2385       __ and_(right, left, Operand(right));
2386       break;
2387     case Token::BIT_XOR:
2388       __ eor(right, left, Operand(right));
2389       break;
2390     default:
2391       UNREACHABLE();
2392   }
2393
2394   __ bind(&done);
2395   context()->Plug(r0);
2396 }
2397
2398
2399 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
2400                                      Token::Value op,
2401                                      OverwriteMode mode) {
2402   __ pop(r1);
2403   BinaryOpICStub stub(isolate(), op, mode);
2404   JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
2405   CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId());
2406   patch_site.EmitPatchInfo();
2407   context()->Plug(r0);
2408 }
2409
2410
2411 void FullCodeGenerator::EmitAssignment(Expression* expr) {
2412   ASSERT(expr->IsValidReferenceExpression());
2413
2414   // Left-hand side can only be a property, a global or a (parameter or local)
2415   // slot.
2416   enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
2417   LhsKind assign_type = VARIABLE;
2418   Property* prop = expr->AsProperty();
2419   if (prop != NULL) {
2420     assign_type = (prop->key()->IsPropertyName())
2421         ? NAMED_PROPERTY
2422         : KEYED_PROPERTY;
2423   }
2424
2425   switch (assign_type) {
2426     case VARIABLE: {
2427       Variable* var = expr->AsVariableProxy()->var();
2428       EffectContext context(this);
2429       EmitVariableAssignment(var, Token::ASSIGN);
2430       break;
2431     }
2432     case NAMED_PROPERTY: {
2433       __ push(r0);  // Preserve value.
2434       VisitForAccumulatorValue(prop->obj());
2435       __ mov(r1, r0);
2436       __ pop(r0);  // Restore value.
2437       __ mov(r2, Operand(prop->key()->AsLiteral()->value()));
2438       CallStoreIC();
2439       break;
2440     }
2441     case KEYED_PROPERTY: {
2442       __ push(r0);  // Preserve value.
2443       VisitForStackValue(prop->obj());
2444       VisitForAccumulatorValue(prop->key());
2445       __ mov(r1, r0);
2446       __ Pop(r0, r2);  // r0 = restored value.
2447       Handle<Code> ic = strict_mode() == SLOPPY
2448           ? isolate()->builtins()->KeyedStoreIC_Initialize()
2449           : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2450       CallIC(ic);
2451       break;
2452     }
2453   }
2454   context()->Plug(r0);
2455 }
2456
2457
2458 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2459     Variable* var, MemOperand location) {
2460   __ str(result_register(), location);
2461   if (var->IsContextSlot()) {
2462     // RecordWrite may destroy all its register arguments.
2463     __ mov(r3, result_register());
2464     int offset = Context::SlotOffset(var->index());
2465     __ RecordWriteContextSlot(
2466         r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs);
2467   }
2468 }
2469
2470
2471 void FullCodeGenerator::EmitCallStoreContextSlot(
2472     Handle<String> name, StrictMode strict_mode) {
2473   __ push(r0);  // Value.
2474   __ mov(r1, Operand(name));
2475   __ mov(r0, Operand(Smi::FromInt(strict_mode)));
2476   __ Push(cp, r1, r0);  // Context, name, strict mode.
2477   __ CallRuntime(Runtime::kHiddenStoreContextSlot, 4);
2478 }
2479
2480
2481 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) {
2482   if (var->IsUnallocated()) {
2483     // Global var, const, or let.
2484     __ mov(r2, Operand(var->name()));
2485     __ ldr(r1, GlobalObjectOperand());
2486     CallStoreIC();
2487
2488   } else if (op == Token::INIT_CONST_LEGACY) {
2489     // Const initializers need a write barrier.
2490     ASSERT(!var->IsParameter());  // No const parameters.
2491     if (var->IsLookupSlot()) {
2492       __ push(r0);
2493       __ mov(r0, Operand(var->name()));
2494       __ Push(cp, r0);  // Context and name.
2495       __ CallRuntime(Runtime::kHiddenInitializeConstContextSlot, 3);
2496     } else {
2497       ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2498       Label skip;
2499       MemOperand location = VarOperand(var, r1);
2500       __ ldr(r2, location);
2501       __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
2502       __ b(ne, &skip);
2503       EmitStoreToStackLocalOrContextSlot(var, location);
2504       __ bind(&skip);
2505     }
2506
2507   } else if (var->mode() == LET && op != Token::INIT_LET) {
2508     // Non-initializing assignment to let variable needs a write barrier.
2509     if (var->IsLookupSlot()) {
2510       EmitCallStoreContextSlot(var->name(), strict_mode());
2511     } else {
2512       ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2513       Label assign;
2514       MemOperand location = VarOperand(var, r1);
2515       __ ldr(r3, location);
2516       __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
2517       __ b(ne, &assign);
2518       __ mov(r3, Operand(var->name()));
2519       __ push(r3);
2520       __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1);
2521       // Perform the assignment.
2522       __ bind(&assign);
2523       EmitStoreToStackLocalOrContextSlot(var, location);
2524     }
2525
2526   } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
2527     // Assignment to var or initializing assignment to let/const
2528     // in harmony mode.
2529     if (var->IsLookupSlot()) {
2530       EmitCallStoreContextSlot(var->name(), strict_mode());
2531     } else {
2532       ASSERT((var->IsStackAllocated() || var->IsContextSlot()));
2533       MemOperand location = VarOperand(var, r1);
2534       if (generate_debug_code_ && op == Token::INIT_LET) {
2535         // Check for an uninitialized let binding.
2536         __ ldr(r2, location);
2537         __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
2538         __ Check(eq, kLetBindingReInitialization);
2539       }
2540       EmitStoreToStackLocalOrContextSlot(var, location);
2541     }
2542   }
2543   // Non-initializing assignments to consts are ignored.
2544 }
2545
2546
2547 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2548   // Assignment to a property, using a named store IC.
2549   Property* prop = expr->target()->AsProperty();
2550   ASSERT(prop != NULL);
2551   ASSERT(prop->key()->AsLiteral() != NULL);
2552
2553   // Record source code position before IC call.
2554   SetSourcePosition(expr->position());
2555   __ mov(r2, Operand(prop->key()->AsLiteral()->value()));
2556   __ pop(r1);
2557
2558   CallStoreIC(expr->AssignmentFeedbackId());
2559
2560   PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2561   context()->Plug(r0);
2562 }
2563
2564
2565 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2566   // Assignment to a property, using a keyed store IC.
2567
2568   // Record source code position before IC call.
2569   SetSourcePosition(expr->position());
2570   __ Pop(r2, r1);  // r1 = key.
2571
2572   Handle<Code> ic = strict_mode() == SLOPPY
2573       ? isolate()->builtins()->KeyedStoreIC_Initialize()
2574       : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2575   CallIC(ic, expr->AssignmentFeedbackId());
2576
2577   PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2578   context()->Plug(r0);
2579 }
2580
2581
2582 void FullCodeGenerator::VisitProperty(Property* expr) {
2583   Comment cmnt(masm_, "[ Property");
2584   Expression* key = expr->key();
2585
2586   if (key->IsPropertyName()) {
2587     VisitForAccumulatorValue(expr->obj());
2588     EmitNamedPropertyLoad(expr);
2589     PrepareForBailoutForId(expr->LoadId(), TOS_REG);
2590     context()->Plug(r0);
2591   } else {
2592     VisitForStackValue(expr->obj());
2593     VisitForAccumulatorValue(expr->key());
2594     __ pop(r1);
2595     EmitKeyedPropertyLoad(expr);
2596     context()->Plug(r0);
2597   }
2598 }
2599
2600
2601 void FullCodeGenerator::CallIC(Handle<Code> code,
2602                                TypeFeedbackId ast_id) {
2603   ic_total_count_++;
2604   // All calls must have a predictable size in full-codegen code to ensure that
2605   // the debugger can patch them correctly.
2606   __ Call(code, RelocInfo::CODE_TARGET, ast_id, al,
2607           NEVER_INLINE_TARGET_ADDRESS);
2608 }
2609
2610
2611 // Code common for calls using the IC.
2612 void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
2613   Expression* callee = expr->expression();
2614
2615   CallIC::CallType call_type = callee->IsVariableProxy()
2616       ? CallIC::FUNCTION
2617       : CallIC::METHOD;
2618
2619   // Get the target function.
2620   if (call_type == CallIC::FUNCTION) {
2621     { StackValueContext context(this);
2622       EmitVariableLoad(callee->AsVariableProxy());
2623       PrepareForBailout(callee, NO_REGISTERS);
2624     }
2625     // Push undefined as receiver. This is patched in the method prologue if it
2626     // is a sloppy mode method.
2627     __ Push(isolate()->factory()->undefined_value());
2628   } else {
2629     // Load the function from the receiver.
2630     ASSERT(callee->IsProperty());
2631     __ ldr(r0, MemOperand(sp, 0));
2632     EmitNamedPropertyLoad(callee->AsProperty());
2633     PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2634     // Push the target function under the receiver.
2635     __ ldr(ip, MemOperand(sp, 0));
2636     __ push(ip);
2637     __ str(r0, MemOperand(sp, kPointerSize));
2638   }
2639
2640   EmitCall(expr, call_type);
2641 }
2642
2643
2644 // Code common for calls using the IC.
2645 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2646                                                 Expression* key) {
2647   // Load the key.
2648   VisitForAccumulatorValue(key);
2649
2650   Expression* callee = expr->expression();
2651
2652   // Load the function from the receiver.
2653   ASSERT(callee->IsProperty());
2654   __ ldr(r1, MemOperand(sp, 0));
2655   EmitKeyedPropertyLoad(callee->AsProperty());
2656   PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2657
2658   // Push the target function under the receiver.
2659   __ ldr(ip, MemOperand(sp, 0));
2660   __ push(ip);
2661   __ str(r0, MemOperand(sp, kPointerSize));
2662
2663   EmitCall(expr, CallIC::METHOD);
2664 }
2665
2666
2667 void FullCodeGenerator::EmitCall(Call* expr, CallIC::CallType call_type) {
2668   // Load the arguments.
2669   ZoneList<Expression*>* args = expr->arguments();
2670   int arg_count = args->length();
2671   { PreservePositionScope scope(masm()->positions_recorder());
2672     for (int i = 0; i < arg_count; i++) {
2673       VisitForStackValue(args->at(i));
2674     }
2675   }
2676
2677   // Record source position of the IC call.
2678   SetSourcePosition(expr->position());
2679   Handle<Code> ic = CallIC::initialize_stub(
2680       isolate(), arg_count, call_type);
2681   __ mov(r3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
2682   __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2683   // Don't assign a type feedback id to the IC, since type feedback is provided
2684   // by the vector above.
2685   CallIC(ic);
2686
2687   RecordJSReturnSite(expr);
2688   // Restore context register.
2689   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2690   context()->DropAndPlug(1, r0);
2691 }
2692
2693
2694 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2695   // r4: copy of the first argument or undefined if it doesn't exist.
2696   if (arg_count > 0) {
2697     __ ldr(r4, MemOperand(sp, arg_count * kPointerSize));
2698   } else {
2699     __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
2700   }
2701
2702   // r3: the receiver of the enclosing function.
2703   int receiver_offset = 2 + info_->scope()->num_parameters();
2704   __ ldr(r3, MemOperand(fp, receiver_offset * kPointerSize));
2705
2706   // r2: strict mode.
2707   __ mov(r2, Operand(Smi::FromInt(strict_mode())));
2708
2709   // r1: the start position of the scope the calls resides in.
2710   __ mov(r1, Operand(Smi::FromInt(scope()->start_position())));
2711
2712   // Do the runtime call.
2713   __ Push(r4, r3, r2, r1);
2714   __ CallRuntime(Runtime::kHiddenResolvePossiblyDirectEval, 5);
2715 }
2716
2717
2718 void FullCodeGenerator::VisitCall(Call* expr) {
2719 #ifdef DEBUG
2720   // We want to verify that RecordJSReturnSite gets called on all paths
2721   // through this function.  Avoid early returns.
2722   expr->return_is_recorded_ = false;
2723 #endif
2724
2725   Comment cmnt(masm_, "[ Call");
2726   Expression* callee = expr->expression();
2727   Call::CallType call_type = expr->GetCallType(isolate());
2728
2729   if (call_type == Call::POSSIBLY_EVAL_CALL) {
2730     // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
2731     // to resolve the function we need to call and the receiver of the
2732     // call.  Then we call the resolved function using the given
2733     // arguments.
2734     ZoneList<Expression*>* args = expr->arguments();
2735     int arg_count = args->length();
2736
2737     { PreservePositionScope pos_scope(masm()->positions_recorder());
2738       VisitForStackValue(callee);
2739       __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
2740       __ push(r2);  // Reserved receiver slot.
2741
2742       // Push the arguments.
2743       for (int i = 0; i < arg_count; i++) {
2744         VisitForStackValue(args->at(i));
2745       }
2746
2747       // Push a copy of the function (found below the arguments) and
2748       // resolve eval.
2749       __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2750       __ push(r1);
2751       EmitResolvePossiblyDirectEval(arg_count);
2752
2753       // The runtime call returns a pair of values in r0 (function) and
2754       // r1 (receiver). Touch up the stack with the right values.
2755       __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
2756       __ str(r1, MemOperand(sp, arg_count * kPointerSize));
2757     }
2758
2759     // Record source position for debugger.
2760     SetSourcePosition(expr->position());
2761     CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
2762     __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2763     __ CallStub(&stub);
2764     RecordJSReturnSite(expr);
2765     // Restore context register.
2766     __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2767     context()->DropAndPlug(1, r0);
2768   } else if (call_type == Call::GLOBAL_CALL) {
2769     EmitCallWithLoadIC(expr);
2770
2771   } else if (call_type == Call::LOOKUP_SLOT_CALL) {
2772     // Call to a lookup slot (dynamically introduced variable).
2773     VariableProxy* proxy = callee->AsVariableProxy();
2774     Label slow, done;
2775
2776     { PreservePositionScope scope(masm()->positions_recorder());
2777       // Generate code for loading from variables potentially shadowed
2778       // by eval-introduced variables.
2779       EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
2780     }
2781
2782     __ bind(&slow);
2783     // Call the runtime to find the function to call (returned in r0)
2784     // and the object holding it (returned in edx).
2785     ASSERT(!context_register().is(r2));
2786     __ mov(r2, Operand(proxy->name()));
2787     __ Push(context_register(), r2);
2788     __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2);
2789     __ Push(r0, r1);  // Function, receiver.
2790
2791     // If fast case code has been generated, emit code to push the
2792     // function and receiver and have the slow path jump around this
2793     // code.
2794     if (done.is_linked()) {
2795       Label call;
2796       __ b(&call);
2797       __ bind(&done);
2798       // Push function.
2799       __ push(r0);
2800       // The receiver is implicitly the global receiver. Indicate this
2801       // by passing the hole to the call function stub.
2802       __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
2803       __ push(r1);
2804       __ bind(&call);
2805     }
2806
2807     // The receiver is either the global receiver or an object found
2808     // by LoadContextSlot.
2809     EmitCall(expr);
2810   } else if (call_type == Call::PROPERTY_CALL) {
2811     Property* property = callee->AsProperty();
2812     { PreservePositionScope scope(masm()->positions_recorder());
2813       VisitForStackValue(property->obj());
2814     }
2815     if (property->key()->IsPropertyName()) {
2816       EmitCallWithLoadIC(expr);
2817     } else {
2818       EmitKeyedCallWithLoadIC(expr, property->key());
2819     }
2820   } else {
2821     ASSERT(call_type == Call::OTHER_CALL);
2822     // Call to an arbitrary expression not handled specially above.
2823     { PreservePositionScope scope(masm()->positions_recorder());
2824       VisitForStackValue(callee);
2825     }
2826     __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
2827     __ push(r1);
2828     // Emit function call.
2829     EmitCall(expr);
2830   }
2831
2832 #ifdef DEBUG
2833   // RecordJSReturnSite should have been called.
2834   ASSERT(expr->return_is_recorded_);
2835 #endif
2836 }
2837
2838
2839 void FullCodeGenerator::VisitCallNew(CallNew* expr) {
2840   Comment cmnt(masm_, "[ CallNew");
2841   // According to ECMA-262, section 11.2.2, page 44, the function
2842   // expression in new calls must be evaluated before the
2843   // arguments.
2844
2845   // Push constructor on the stack.  If it's not a function it's used as
2846   // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
2847   // ignored.
2848   VisitForStackValue(expr->expression());
2849
2850   // Push the arguments ("left-to-right") on the stack.
2851   ZoneList<Expression*>* args = expr->arguments();
2852   int arg_count = args->length();
2853   for (int i = 0; i < arg_count; i++) {
2854     VisitForStackValue(args->at(i));
2855   }
2856
2857   // Call the construct call builtin that handles allocation and
2858   // constructor invocation.
2859   SetSourcePosition(expr->position());
2860
2861   // Load function and argument count into r1 and r0.
2862   __ mov(r0, Operand(arg_count));
2863   __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
2864
2865   // Record call targets in unoptimized code.
2866   if (FLAG_pretenuring_call_new) {
2867     EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot());
2868     ASSERT(expr->AllocationSiteFeedbackSlot() ==
2869            expr->CallNewFeedbackSlot() + 1);
2870   }
2871
2872   __ Move(r2, FeedbackVector());
2873   __ mov(r3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));
2874
2875   CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET);
2876   __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
2877   PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
2878   context()->Plug(r0);
2879 }
2880
2881
2882 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2883   ZoneList<Expression*>* args = expr->arguments();
2884   ASSERT(args->length() == 1);
2885
2886   VisitForAccumulatorValue(args->at(0));
2887
2888   Label materialize_true, materialize_false;
2889   Label* if_true = NULL;
2890   Label* if_false = NULL;
2891   Label* fall_through = NULL;
2892   context()->PrepareTest(&materialize_true, &materialize_false,
2893                          &if_true, &if_false, &fall_through);
2894
2895   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2896   __ SmiTst(r0);
2897   Split(eq, if_true, if_false, fall_through);
2898
2899   context()->Plug(if_true, if_false);
2900 }
2901
2902
2903 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
2904   ZoneList<Expression*>* args = expr->arguments();
2905   ASSERT(args->length() == 1);
2906
2907   VisitForAccumulatorValue(args->at(0));
2908
2909   Label materialize_true, materialize_false;
2910   Label* if_true = NULL;
2911   Label* if_false = NULL;
2912   Label* fall_through = NULL;
2913   context()->PrepareTest(&materialize_true, &materialize_false,
2914                          &if_true, &if_false, &fall_through);
2915
2916   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2917   __ NonNegativeSmiTst(r0);
2918   Split(eq, if_true, if_false, fall_through);
2919
2920   context()->Plug(if_true, if_false);
2921 }
2922
2923
2924 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
2925   ZoneList<Expression*>* args = expr->arguments();
2926   ASSERT(args->length() == 1);
2927
2928   VisitForAccumulatorValue(args->at(0));
2929
2930   Label materialize_true, materialize_false;
2931   Label* if_true = NULL;
2932   Label* if_false = NULL;
2933   Label* fall_through = NULL;
2934   context()->PrepareTest(&materialize_true, &materialize_false,
2935                          &if_true, &if_false, &fall_through);
2936
2937   __ JumpIfSmi(r0, if_false);
2938   __ LoadRoot(ip, Heap::kNullValueRootIndex);
2939   __ cmp(r0, ip);
2940   __ b(eq, if_true);
2941   __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
2942   // Undetectable objects behave like undefined when tested with typeof.
2943   __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
2944   __ tst(r1, Operand(1 << Map::kIsUndetectable));
2945   __ b(ne, if_false);
2946   __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset));
2947   __ cmp(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2948   __ b(lt, if_false);
2949   __ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
2950   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2951   Split(le, if_true, if_false, fall_through);
2952
2953   context()->Plug(if_true, if_false);
2954 }
2955
2956
2957 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
2958   ZoneList<Expression*>* args = expr->arguments();
2959   ASSERT(args->length() == 1);
2960
2961   VisitForAccumulatorValue(args->at(0));
2962
2963   Label materialize_true, materialize_false;
2964   Label* if_true = NULL;
2965   Label* if_false = NULL;
2966   Label* fall_through = NULL;
2967   context()->PrepareTest(&materialize_true, &materialize_false,
2968                          &if_true, &if_false, &fall_through);
2969
2970   __ JumpIfSmi(r0, if_false);
2971   __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
2972   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2973   Split(ge, if_true, if_false, fall_through);
2974
2975   context()->Plug(if_true, if_false);
2976 }
2977
2978
2979 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
2980   ZoneList<Expression*>* args = expr->arguments();
2981   ASSERT(args->length() == 1);
2982
2983   VisitForAccumulatorValue(args->at(0));
2984
2985   Label materialize_true, materialize_false;
2986   Label* if_true = NULL;
2987   Label* if_false = NULL;
2988   Label* fall_through = NULL;
2989   context()->PrepareTest(&materialize_true, &materialize_false,
2990                          &if_true, &if_false, &fall_through);
2991
2992   __ JumpIfSmi(r0, if_false);
2993   __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2994   __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
2995   __ tst(r1, Operand(1 << Map::kIsUndetectable));
2996   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2997   Split(ne, if_true, if_false, fall_through);
2998
2999   context()->Plug(if_true, if_false);
3000 }
3001
3002
3003 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
3004     CallRuntime* expr) {
3005   ZoneList<Expression*>* args = expr->arguments();
3006   ASSERT(args->length() == 1);
3007
3008   VisitForAccumulatorValue(args->at(0));
3009
3010   Label materialize_true, materialize_false, skip_lookup;
3011   Label* if_true = NULL;
3012   Label* if_false = NULL;
3013   Label* fall_through = NULL;
3014   context()->PrepareTest(&materialize_true, &materialize_false,
3015                          &if_true, &if_false, &fall_through);
3016
3017   __ AssertNotSmi(r0);
3018
3019   __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
3020   __ ldrb(ip, FieldMemOperand(r1, Map::kBitField2Offset));
3021   __ tst(ip, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
3022   __ b(ne, &skip_lookup);
3023
3024   // Check for fast case object. Generate false result for slow case object.
3025   __ ldr(r2, FieldMemOperand(r0, JSObject::kPropertiesOffset));
3026   __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
3027   __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
3028   __ cmp(r2, ip);
3029   __ b(eq, if_false);
3030
3031   // Look for valueOf name in the descriptor array, and indicate false if
3032   // found. Since we omit an enumeration index check, if it is added via a
3033   // transition that shares its descriptor array, this is a false positive.
3034   Label entry, loop, done;
3035
3036   // Skip loop if no descriptors are valid.
3037   __ NumberOfOwnDescriptors(r3, r1);
3038   __ cmp(r3, Operand::Zero());
3039   __ b(eq, &done);
3040
3041   __ LoadInstanceDescriptors(r1, r4);
3042   // r4: descriptor array.
3043   // r3: valid entries in the descriptor array.
3044   __ mov(ip, Operand(DescriptorArray::kDescriptorSize));
3045   __ mul(r3, r3, ip);
3046   // Calculate location of the first key name.
3047   __ add(r4, r4, Operand(DescriptorArray::kFirstOffset - kHeapObjectTag));
3048   // Calculate the end of the descriptor array.
3049   __ mov(r2, r4);
3050   __ add(r2, r2, Operand::PointerOffsetFromSmiKey(r3));
3051
3052   // Loop through all the keys in the descriptor array. If one of these is the
3053   // string "valueOf" the result is false.
3054   // The use of ip to store the valueOf string assumes that it is not otherwise
3055   // used in the loop below.
3056   __ mov(ip, Operand(isolate()->factory()->value_of_string()));
3057   __ jmp(&entry);
3058   __ bind(&loop);
3059   __ ldr(r3, MemOperand(r4, 0));
3060   __ cmp(r3, ip);
3061   __ b(eq, if_false);
3062   __ add(r4, r4, Operand(DescriptorArray::kDescriptorSize * kPointerSize));
3063   __ bind(&entry);
3064   __ cmp(r4, Operand(r2));
3065   __ b(ne, &loop);
3066
3067   __ bind(&done);
3068
3069   // Set the bit in the map to indicate that there is no local valueOf field.
3070   __ ldrb(r2, FieldMemOperand(r1, Map::kBitField2Offset));
3071   __ orr(r2, r2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
3072   __ strb(r2, FieldMemOperand(r1, Map::kBitField2Offset));
3073
3074   __ bind(&skip_lookup);
3075
3076   // If a valueOf property is not found on the object check that its
3077   // prototype is the un-modified String prototype. If not result is false.
3078   __ ldr(r2, FieldMemOperand(r1, Map::kPrototypeOffset));
3079   __ JumpIfSmi(r2, if_false);
3080   __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
3081   __ ldr(r3, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
3082   __ ldr(r3, FieldMemOperand(r3, GlobalObject::kNativeContextOffset));
3083   __ ldr(r3, ContextOperand(r3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
3084   __ cmp(r2, r3);
3085   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3086   Split(eq, if_true, if_false, fall_through);
3087
3088   context()->Plug(if_true, if_false);
3089 }
3090
3091
3092 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
3093   ZoneList<Expression*>* args = expr->arguments();
3094   ASSERT(args->length() == 1);
3095
3096   VisitForAccumulatorValue(args->at(0));
3097
3098   Label materialize_true, materialize_false;
3099   Label* if_true = NULL;
3100   Label* if_false = NULL;
3101   Label* fall_through = NULL;
3102   context()->PrepareTest(&materialize_true, &materialize_false,
3103                          &if_true, &if_false, &fall_through);
3104
3105   __ JumpIfSmi(r0, if_false);
3106   __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE);
3107   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3108   Split(eq, if_true, if_false, fall_through);
3109
3110   context()->Plug(if_true, if_false);
3111 }
3112
3113
3114 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
3115   ZoneList<Expression*>* args = expr->arguments();
3116   ASSERT(args->length() == 1);
3117
3118   VisitForAccumulatorValue(args->at(0));
3119
3120   Label materialize_true, materialize_false;
3121   Label* if_true = NULL;
3122   Label* if_false = NULL;
3123   Label* fall_through = NULL;
3124   context()->PrepareTest(&materialize_true, &materialize_false,
3125                          &if_true, &if_false, &fall_through);
3126
3127   __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK);
3128   __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
3129   __ ldr(r1, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
3130   __ cmp(r2, Operand(0x80000000));
3131   __ cmp(r1, Operand(0x00000000), eq);
3132
3133   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3134   Split(eq, if_true, if_false, fall_through);
3135
3136   context()->Plug(if_true, if_false);
3137 }
3138
3139
3140 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
3141   ZoneList<Expression*>* args = expr->arguments();
3142   ASSERT(args->length() == 1);
3143
3144   VisitForAccumulatorValue(args->at(0));
3145
3146   Label materialize_true, materialize_false;
3147   Label* if_true = NULL;
3148   Label* if_false = NULL;
3149   Label* fall_through = NULL;
3150   context()->PrepareTest(&materialize_true, &materialize_false,
3151                          &if_true, &if_false, &fall_through);
3152
3153   __ JumpIfSmi(r0, if_false);
3154   __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
3155   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3156   Split(eq, if_true, if_false, fall_through);
3157
3158   context()->Plug(if_true, if_false);
3159 }
3160
3161
3162 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
3163   ZoneList<Expression*>* args = expr->arguments();
3164   ASSERT(args->length() == 1);
3165
3166   VisitForAccumulatorValue(args->at(0));
3167
3168   Label materialize_true, materialize_false;
3169   Label* if_true = NULL;
3170   Label* if_false = NULL;
3171   Label* fall_through = NULL;
3172   context()->PrepareTest(&materialize_true, &materialize_false,
3173                          &if_true, &if_false, &fall_through);
3174
3175   __ JumpIfSmi(r0, if_false);
3176   __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
3177   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3178   Split(eq, if_true, if_false, fall_through);
3179
3180   context()->Plug(if_true, if_false);
3181 }
3182
3183
3184
3185 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
3186   ASSERT(expr->arguments()->length() == 0);
3187
3188   Label materialize_true, materialize_false;
3189   Label* if_true = NULL;
3190   Label* if_false = NULL;
3191   Label* fall_through = NULL;
3192   context()->PrepareTest(&materialize_true, &materialize_false,
3193                          &if_true, &if_false, &fall_through);
3194
3195   // Get the frame pointer for the calling frame.
3196   __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3197
3198   // Skip the arguments adaptor frame if it exists.
3199   __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset));
3200   __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3201   __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset), eq);
3202
3203   // Check the marker in the calling frame.
3204   __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
3205   __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
3206   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3207   Split(eq, if_true, if_false, fall_through);
3208
3209   context()->Plug(if_true, if_false);
3210 }
3211
3212
3213 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
3214   ZoneList<Expression*>* args = expr->arguments();
3215   ASSERT(args->length() == 2);
3216
3217   // Load the two objects into registers and perform the comparison.
3218   VisitForStackValue(args->at(0));
3219   VisitForAccumulatorValue(args->at(1));
3220
3221   Label materialize_true, materialize_false;
3222   Label* if_true = NULL;
3223   Label* if_false = NULL;
3224   Label* fall_through = NULL;
3225   context()->PrepareTest(&materialize_true, &materialize_false,
3226                          &if_true, &if_false, &fall_through);
3227
3228   __ pop(r1);
3229   __ cmp(r0, r1);
3230   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3231   Split(eq, if_true, if_false, fall_through);
3232
3233   context()->Plug(if_true, if_false);
3234 }
3235
3236
3237 void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
3238   ZoneList<Expression*>* args = expr->arguments();
3239   ASSERT(args->length() == 1);
3240
3241   // ArgumentsAccessStub expects the key in edx and the formal
3242   // parameter count in r0.
3243   VisitForAccumulatorValue(args->at(0));
3244   __ mov(r1, r0);
3245   __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
3246   ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT);
3247   __ CallStub(&stub);
3248   context()->Plug(r0);
3249 }
3250
3251
3252 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
3253   ASSERT(expr->arguments()->length() == 0);
3254
3255   // Get the number of formal parameters.
3256   __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
3257
3258   // Check if the calling frame is an arguments adaptor frame.
3259   __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3260   __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
3261   __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3262
3263   // Arguments adaptor case: Read the arguments length from the
3264   // adaptor frame.
3265   __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset), eq);
3266
3267   context()->Plug(r0);
3268 }
3269
3270
3271 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
3272   ZoneList<Expression*>* args = expr->arguments();
3273   ASSERT(args->length() == 1);
3274   Label done, null, function, non_function_constructor;
3275
3276   VisitForAccumulatorValue(args->at(0));
3277
3278   // If the object is a smi, we return null.
3279   __ JumpIfSmi(r0, &null);
3280
3281   // Check that the object is a JS object but take special care of JS
3282   // functions to make sure they have 'Function' as their class.
3283   // Assume that there are only two callable types, and one of them is at
3284   // either end of the type range for JS object types. Saves extra comparisons.
3285   STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
3286   __ CompareObjectType(r0, r0, r1, FIRST_SPEC_OBJECT_TYPE);
3287   // Map is now in r0.
3288   __ b(lt, &null);
3289   STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
3290                 FIRST_SPEC_OBJECT_TYPE + 1);
3291   __ b(eq, &function);
3292
3293   __ cmp(r1, Operand(LAST_SPEC_OBJECT_TYPE));
3294   STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
3295                 LAST_SPEC_OBJECT_TYPE - 1);
3296   __ b(eq, &function);
3297   // Assume that there is no larger type.
3298   STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
3299
3300   // Check if the constructor in the map is a JS function.
3301   __ ldr(r0, FieldMemOperand(r0, Map::kConstructorOffset));
3302   __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
3303   __ b(ne, &non_function_constructor);
3304
3305   // r0 now contains the constructor function. Grab the
3306   // instance class name from there.
3307   __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
3308   __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset));
3309   __ b(&done);
3310
3311   // Functions have class 'Function'.
3312   __ bind(&function);
3313   __ LoadRoot(r0, Heap::kfunction_class_stringRootIndex);
3314   __ jmp(&done);
3315
3316   // Objects with a non-function constructor have class 'Object'.
3317   __ bind(&non_function_constructor);
3318   __ LoadRoot(r0, Heap::kObject_stringRootIndex);
3319   __ jmp(&done);
3320
3321   // Non-JS objects have class null.
3322   __ bind(&null);
3323   __ LoadRoot(r0, Heap::kNullValueRootIndex);
3324
3325   // All done.
3326   __ bind(&done);
3327
3328   context()->Plug(r0);
3329 }
3330
3331
3332 void FullCodeGenerator::EmitLog(CallRuntime* expr) {
3333   // Conditionally generate a log call.
3334   // Args:
3335   //   0 (literal string): The type of logging (corresponds to the flags).
3336   //     This is used to determine whether or not to generate the log call.
3337   //   1 (string): Format string.  Access the string at argument index 2
3338   //     with '%2s' (see Logger::LogRuntime for all the formats).
3339   //   2 (array): Arguments to the format string.
3340   ZoneList<Expression*>* args = expr->arguments();
3341   ASSERT_EQ(args->length(), 3);
3342   if (CodeGenerator::ShouldGenerateLog(isolate(), args->at(0))) {
3343     VisitForStackValue(args->at(1));
3344     VisitForStackValue(args->at(2));
3345     __ CallRuntime(Runtime::kHiddenLog, 2);
3346   }
3347
3348   // Finally, we're expected to leave a value on the top of the stack.
3349   __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
3350   context()->Plug(r0);
3351 }
3352
3353
3354 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
3355   // Load the arguments on the stack and call the stub.
3356   SubStringStub stub(isolate());
3357   ZoneList<Expression*>* args = expr->arguments();
3358   ASSERT(args->length() == 3);
3359   VisitForStackValue(args->at(0));
3360   VisitForStackValue(args->at(1));
3361   VisitForStackValue(args->at(2));
3362   __ CallStub(&stub);
3363   context()->Plug(r0);
3364 }
3365
3366
3367 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
3368   // Load the arguments on the stack and call the stub.
3369   RegExpExecStub stub(isolate());
3370   ZoneList<Expression*>* args = expr->arguments();
3371   ASSERT(args->length() == 4);
3372   VisitForStackValue(args->at(0));
3373   VisitForStackValue(args->at(1));
3374   VisitForStackValue(args->at(2));
3375   VisitForStackValue(args->at(3));
3376   __ CallStub(&stub);
3377   context()->Plug(r0);
3378 }
3379
3380
3381 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
3382   ZoneList<Expression*>* args = expr->arguments();
3383   ASSERT(args->length() == 1);
3384   VisitForAccumulatorValue(args->at(0));  // Load the object.
3385
3386   Label done;
3387   // If the object is a smi return the object.
3388   __ JumpIfSmi(r0, &done);
3389   // If the object is not a value type, return the object.
3390   __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE);
3391   __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset), eq);
3392
3393   __ bind(&done);
3394   context()->Plug(r0);
3395 }
3396
3397
3398 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
3399   ZoneList<Expression*>* args = expr->arguments();
3400   ASSERT(args->length() == 2);
3401   ASSERT_NE(NULL, args->at(1)->AsLiteral());
3402   Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value()));
3403
3404   VisitForAccumulatorValue(args->at(0));  // Load the object.
3405
3406   Label runtime, done, not_date_object;
3407   Register object = r0;
3408   Register result = r0;
3409   Register scratch0 = r9;
3410   Register scratch1 = r1;
3411
3412   __ JumpIfSmi(object, &not_date_object);
3413   __ CompareObjectType(object, scratch1, scratch1, JS_DATE_TYPE);
3414   __ b(ne, &not_date_object);
3415
3416   if (index->value() == 0) {
3417     __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
3418     __ jmp(&done);
3419   } else {
3420     if (index->value() < JSDate::kFirstUncachedField) {
3421       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
3422       __ mov(scratch1, Operand(stamp));
3423       __ ldr(scratch1, MemOperand(scratch1));
3424       __ ldr(scratch0, FieldMemOperand(object, JSDate::kCacheStampOffset));
3425       __ cmp(scratch1, scratch0);
3426       __ b(ne, &runtime);
3427       __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset +
3428                                              kPointerSize * index->value()));
3429       __ jmp(&done);
3430     }
3431     __ bind(&runtime);
3432     __ PrepareCallCFunction(2, scratch1);
3433     __ mov(r1, Operand(index));
3434     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
3435     __ jmp(&done);
3436   }
3437
3438   __ bind(&not_date_object);
3439   __ CallRuntime(Runtime::kHiddenThrowNotDateError, 0);
3440   __ bind(&done);
3441   context()->Plug(r0);
3442 }
3443
3444
3445 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
3446   ZoneList<Expression*>* args = expr->arguments();
3447   ASSERT_EQ(3, args->length());
3448
3449   Register string = r0;
3450   Register index = r1;
3451   Register value = r2;
3452
3453   VisitForStackValue(args->at(1));  // index
3454   VisitForStackValue(args->at(2));  // value
3455   VisitForAccumulatorValue(args->at(0));  // string
3456   __ Pop(index, value);
3457
3458   if (FLAG_debug_code) {
3459     __ SmiTst(value);
3460     __ Check(eq, kNonSmiValue);
3461     __ SmiTst(index);
3462     __ Check(eq, kNonSmiIndex);
3463     __ SmiUntag(index, index);
3464     static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
3465     __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
3466     __ SmiTag(index, index);
3467   }
3468
3469   __ SmiUntag(value, value);
3470   __ add(ip,
3471          string,
3472          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3473   __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize));
3474   context()->Plug(string);
3475 }
3476
3477
3478 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
3479   ZoneList<Expression*>* args = expr->arguments();
3480   ASSERT_EQ(3, args->length());
3481
3482   Register string = r0;
3483   Register index = r1;
3484   Register value = r2;
3485
3486   VisitForStackValue(args->at(1));  // index
3487   VisitForStackValue(args->at(2));  // value
3488   VisitForAccumulatorValue(args->at(0));  // string
3489   __ Pop(index, value);
3490
3491   if (FLAG_debug_code) {
3492     __ SmiTst(value);
3493     __ Check(eq, kNonSmiValue);
3494     __ SmiTst(index);
3495     __ Check(eq, kNonSmiIndex);
3496     __ SmiUntag(index, index);
3497     static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
3498     __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
3499     __ SmiTag(index, index);
3500   }
3501
3502   __ SmiUntag(value, value);
3503   __ add(ip,
3504          string,
3505          Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
3506   STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
3507   __ strh(value, MemOperand(ip, index));
3508   context()->Plug(string);
3509 }
3510
3511
3512
3513 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
3514   // Load the arguments on the stack and call the runtime function.
3515   ZoneList<Expression*>* args = expr->arguments();
3516   ASSERT(args->length() == 2);
3517   VisitForStackValue(args->at(0));
3518   VisitForStackValue(args->at(1));
3519   MathPowStub stub(isolate(), MathPowStub::ON_STACK);
3520   __ CallStub(&stub);
3521   context()->Plug(r0);
3522 }
3523
3524
3525 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
3526   ZoneList<Expression*>* args = expr->arguments();
3527   ASSERT(args->length() == 2);
3528   VisitForStackValue(args->at(0));  // Load the object.
3529   VisitForAccumulatorValue(args->at(1));  // Load the value.
3530   __ pop(r1);  // r0 = value. r1 = object.
3531
3532   Label done;
3533   // If the object is a smi, return the value.
3534   __ JumpIfSmi(r1, &done);
3535
3536   // If the object is not a value type, return the value.
3537   __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE);
3538   __ b(ne, &done);
3539
3540   // Store the value.
3541   __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
3542   // Update the write barrier.  Save the value as it will be
3543   // overwritten by the write barrier code and is needed afterward.
3544   __ mov(r2, r0);
3545   __ RecordWriteField(
3546       r1, JSValue::kValueOffset, r2, r3, kLRHasBeenSaved, kDontSaveFPRegs);
3547
3548   __ bind(&done);
3549   context()->Plug(r0);
3550 }
3551
3552
3553 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
3554   ZoneList<Expression*>* args = expr->arguments();
3555   ASSERT_EQ(args->length(), 1);
3556   // Load the argument into r0 and call the stub.
3557   VisitForAccumulatorValue(args->at(0));
3558
3559   NumberToStringStub stub(isolate());
3560   __ CallStub(&stub);
3561   context()->Plug(r0);
3562 }
3563
3564
3565 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
3566   ZoneList<Expression*>* args = expr->arguments();
3567   ASSERT(args->length() == 1);
3568   VisitForAccumulatorValue(args->at(0));
3569
3570   Label done;
3571   StringCharFromCodeGenerator generator(r0, r1);
3572   generator.GenerateFast(masm_);
3573   __ jmp(&done);
3574
3575   NopRuntimeCallHelper call_helper;
3576   generator.GenerateSlow(masm_, call_helper);
3577
3578   __ bind(&done);
3579   context()->Plug(r1);
3580 }
3581
3582
3583 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
3584   ZoneList<Expression*>* args = expr->arguments();
3585   ASSERT(args->length() == 2);
3586   VisitForStackValue(args->at(0));
3587   VisitForAccumulatorValue(args->at(1));
3588
3589   Register object = r1;
3590   Register index = r0;
3591   Register result = r3;
3592
3593   __ pop(object);
3594
3595   Label need_conversion;
3596   Label index_out_of_range;
3597   Label done;
3598   StringCharCodeAtGenerator generator(object,
3599                                       index,
3600                                       result,
3601                                       &need_conversion,
3602                                       &need_conversion,
3603                                       &index_out_of_range,
3604                                       STRING_INDEX_IS_NUMBER);
3605   generator.GenerateFast(masm_);
3606   __ jmp(&done);
3607
3608   __ bind(&index_out_of_range);
3609   // When the index is out of range, the spec requires us to return
3610   // NaN.
3611   __ LoadRoot(result, Heap::kNanValueRootIndex);
3612   __ jmp(&done);
3613
3614   __ bind(&need_conversion);
3615   // Load the undefined value into the result register, which will
3616   // trigger conversion.
3617   __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
3618   __ jmp(&done);
3619
3620   NopRuntimeCallHelper call_helper;
3621   generator.GenerateSlow(masm_, call_helper);
3622
3623   __ bind(&done);
3624   context()->Plug(result);
3625 }
3626
3627
3628 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
3629   ZoneList<Expression*>* args = expr->arguments();
3630   ASSERT(args->length() == 2);
3631   VisitForStackValue(args->at(0));
3632   VisitForAccumulatorValue(args->at(1));
3633
3634   Register object = r1;
3635   Register index = r0;
3636   Register scratch = r3;
3637   Register result = r0;
3638
3639   __ pop(object);
3640
3641   Label need_conversion;
3642   Label index_out_of_range;
3643   Label done;
3644   StringCharAtGenerator generator(object,
3645                                   index,
3646                                   scratch,
3647                                   result,
3648                                   &need_conversion,
3649                                   &need_conversion,
3650                                   &index_out_of_range,
3651                                   STRING_INDEX_IS_NUMBER);
3652   generator.GenerateFast(masm_);
3653   __ jmp(&done);
3654
3655   __ bind(&index_out_of_range);
3656   // When the index is out of range, the spec requires us to return
3657   // the empty string.
3658   __ LoadRoot(result, Heap::kempty_stringRootIndex);
3659   __ jmp(&done);
3660
3661   __ bind(&need_conversion);
3662   // Move smi zero into the result register, which will trigger
3663   // conversion.
3664   __ mov(result, Operand(Smi::FromInt(0)));
3665   __ jmp(&done);
3666
3667   NopRuntimeCallHelper call_helper;
3668   generator.GenerateSlow(masm_, call_helper);
3669
3670   __ bind(&done);
3671   context()->Plug(result);
3672 }
3673
3674
3675 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3676   ZoneList<Expression*>* args = expr->arguments();
3677   ASSERT_EQ(2, args->length());
3678   VisitForStackValue(args->at(0));
3679   VisitForAccumulatorValue(args->at(1));
3680
3681   __ pop(r1);
3682   StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED);
3683   __ CallStub(&stub);
3684   context()->Plug(r0);
3685 }
3686
3687
3688 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3689   ZoneList<Expression*>* args = expr->arguments();
3690   ASSERT_EQ(2, args->length());
3691   VisitForStackValue(args->at(0));
3692   VisitForStackValue(args->at(1));
3693
3694   StringCompareStub stub(isolate());
3695   __ CallStub(&stub);
3696   context()->Plug(r0);
3697 }
3698
3699
3700 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
3701   ZoneList<Expression*>* args = expr->arguments();
3702   ASSERT(args->length() >= 2);
3703
3704   int arg_count = args->length() - 2;  // 2 ~ receiver and function.
3705   for (int i = 0; i < arg_count + 1; i++) {
3706     VisitForStackValue(args->at(i));
3707   }
3708   VisitForAccumulatorValue(args->last());  // Function.
3709
3710   Label runtime, done;
3711   // Check for non-function argument (including proxy).
3712   __ JumpIfSmi(r0, &runtime);
3713   __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
3714   __ b(ne, &runtime);
3715
3716   // InvokeFunction requires the function in r1. Move it in there.
3717   __ mov(r1, result_register());
3718   ParameterCount count(arg_count);
3719   __ InvokeFunction(r1, count, CALL_FUNCTION, NullCallWrapper());
3720   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
3721   __ jmp(&done);
3722
3723   __ bind(&runtime);
3724   __ push(r0);
3725   __ CallRuntime(Runtime::kCall, args->length());
3726   __ bind(&done);
3727
3728   context()->Plug(r0);
3729 }
3730
3731
3732 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3733   RegExpConstructResultStub stub(isolate());
3734   ZoneList<Expression*>* args = expr->arguments();
3735   ASSERT(args->length() == 3);
3736   VisitForStackValue(args->at(0));
3737   VisitForStackValue(args->at(1));
3738   VisitForAccumulatorValue(args->at(2));
3739   __ pop(r1);
3740   __ pop(r2);
3741   __ CallStub(&stub);
3742   context()->Plug(r0);
3743 }
3744
3745
3746 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3747   ZoneList<Expression*>* args = expr->arguments();
3748   ASSERT_EQ(2, args->length());
3749   ASSERT_NE(NULL, args->at(0)->AsLiteral());
3750   int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value();
3751
3752   Handle<FixedArray> jsfunction_result_caches(
3753       isolate()->native_context()->jsfunction_result_caches());
3754   if (jsfunction_result_caches->length() <= cache_id) {
3755     __ Abort(kAttemptToUseUndefinedCache);
3756     __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
3757     context()->Plug(r0);
3758     return;
3759   }
3760
3761   VisitForAccumulatorValue(args->at(1));
3762
3763   Register key = r0;
3764   Register cache = r1;
3765   __ ldr(cache, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
3766   __ ldr(cache, FieldMemOperand(cache, GlobalObject::kNativeContextOffset));
3767   __ ldr(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
3768   __ ldr(cache,
3769          FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
3770
3771
3772   Label done, not_found;
3773   __ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset));
3774   // r2 now holds finger offset as a smi.
3775   __ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3776   // r3 now points to the start of fixed array elements.
3777   __ ldr(r2, MemOperand::PointerAddressFromSmiKey(r3, r2, PreIndex));
3778   // Note side effect of PreIndex: r3 now points to the key of the pair.
3779   __ cmp(key, r2);
3780   __ b(ne, &not_found);
3781
3782   __ ldr(r0, MemOperand(r3, kPointerSize));
3783   __ b(&done);
3784
3785   __ bind(&not_found);
3786   // Call runtime to perform the lookup.
3787   __ Push(cache, key);
3788   __ CallRuntime(Runtime::kHiddenGetFromCache, 2);
3789
3790   __ bind(&done);
3791   context()->Plug(r0);
3792 }
3793
3794
3795 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3796   ZoneList<Expression*>* args = expr->arguments();
3797   VisitForAccumulatorValue(args->at(0));
3798
3799   Label materialize_true, materialize_false;
3800   Label* if_true = NULL;
3801   Label* if_false = NULL;
3802   Label* fall_through = NULL;
3803   context()->PrepareTest(&materialize_true, &materialize_false,
3804                          &if_true, &if_false, &fall_through);
3805
3806   __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
3807   __ tst(r0, Operand(String::kContainsCachedArrayIndexMask));
3808   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3809   Split(eq, if_true, if_false, fall_through);
3810
3811   context()->Plug(if_true, if_false);
3812 }
3813
3814
3815 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
3816   ZoneList<Expression*>* args = expr->arguments();
3817   ASSERT(args->length() == 1);
3818   VisitForAccumulatorValue(args->at(0));
3819
3820   __ AssertString(r0);
3821
3822   __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
3823   __ IndexFromHash(r0, r0);
3824
3825   context()->Plug(r0);
3826 }
3827
3828
3829 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
3830   Label bailout, done, one_char_separator, long_separator, non_trivial_array,
3831       not_size_one_array, loop, empty_separator_loop, one_char_separator_loop,
3832       one_char_separator_loop_entry, long_separator_loop;
3833   ZoneList<Expression*>* args = expr->arguments();
3834   ASSERT(args->length() == 2);
3835   VisitForStackValue(args->at(1));
3836   VisitForAccumulatorValue(args->at(0));
3837
3838   // All aliases of the same register have disjoint lifetimes.
3839   Register array = r0;
3840   Register elements = no_reg;  // Will be r0.
3841   Register result = no_reg;  // Will be r0.
3842   Register separator = r1;
3843   Register array_length = r2;
3844   Register result_pos = no_reg;  // Will be r2
3845   Register string_length = r3;
3846   Register string = r4;
3847   Register element = r5;
3848   Register elements_end = r6;
3849   Register scratch = r9;
3850
3851   // Separator operand is on the stack.
3852   __ pop(separator);
3853
3854   // Check that the array is a JSArray.
3855   __ JumpIfSmi(array, &bailout);
3856   __ CompareObjectType(array, scratch, array_length, JS_ARRAY_TYPE);
3857   __ b(ne, &bailout);
3858
3859   // Check that the array has fast elements.
3860   __ CheckFastElements(scratch, array_length, &bailout);
3861
3862   // If the array has length zero, return the empty string.
3863   __ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
3864   __ SmiUntag(array_length, SetCC);
3865   __ b(ne, &non_trivial_array);
3866   __ LoadRoot(r0, Heap::kempty_stringRootIndex);
3867   __ b(&done);
3868
3869   __ bind(&non_trivial_array);
3870
3871   // Get the FixedArray containing array's elements.
3872   elements = array;
3873   __ ldr(elements, FieldMemOperand(array, JSArray::kElementsOffset));
3874   array = no_reg;  // End of array's live range.
3875
3876   // Check that all array elements are sequential ASCII strings, and
3877   // accumulate the sum of their lengths, as a smi-encoded value.
3878   __ mov(string_length, Operand::Zero());
3879   __ add(element,
3880          elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3881   __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2));
3882   // Loop condition: while (element < elements_end).
3883   // Live values in registers:
3884   //   elements: Fixed array of strings.
3885   //   array_length: Length of the fixed array of strings (not smi)
3886   //   separator: Separator string
3887   //   string_length: Accumulated sum of string lengths (smi).
3888   //   element: Current array element.
3889   //   elements_end: Array end.
3890   if (generate_debug_code_) {
3891     __ cmp(array_length, Operand::Zero());
3892     __ Assert(gt, kNoEmptyArraysHereInEmitFastAsciiArrayJoin);
3893   }
3894   __ bind(&loop);
3895   __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
3896   __ JumpIfSmi(string, &bailout);
3897   __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset));
3898   __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
3899   __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &bailout);
3900   __ ldr(scratch, FieldMemOperand(string, SeqOneByteString::kLengthOffset));
3901   __ add(string_length, string_length, Operand(scratch), SetCC);
3902   __ b(vs, &bailout);
3903   __ cmp(element, elements_end);
3904   __ b(lt, &loop);
3905
3906   // If array_length is 1, return elements[0], a string.
3907   __ cmp(array_length, Operand(1));
3908   __ b(ne, &not_size_one_array);
3909   __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize));
3910   __ b(&done);
3911
3912   __ bind(&not_size_one_array);
3913
3914   // Live values in registers:
3915   //   separator: Separator string
3916   //   array_length: Length of the array.
3917   //   string_length: Sum of string lengths (smi).
3918   //   elements: FixedArray of strings.
3919
3920   // Check that the separator is a flat ASCII string.
3921   __ JumpIfSmi(separator, &bailout);
3922   __ ldr(scratch, FieldMemOperand(separator, HeapObject::kMapOffset));
3923   __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
3924   __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &bailout);
3925
3926   // Add (separator length times array_length) - separator length to the
3927   // string_length to get the length of the result string. array_length is not
3928   // smi but the other values are, so the result is a smi
3929   __ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
3930   __ sub(string_length, string_length, Operand(scratch));
3931   __ smull(scratch, ip, array_length, scratch);
3932   // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are
3933   // zero.
3934   __ cmp(ip, Operand::Zero());
3935   __ b(ne, &bailout);
3936   __ tst(scratch, Operand(0x80000000));
3937   __ b(ne, &bailout);
3938   __ add(string_length, string_length, Operand(scratch), SetCC);
3939   __ b(vs, &bailout);
3940   __ SmiUntag(string_length);
3941
3942   // Get first element in the array to free up the elements register to be used
3943   // for the result.
3944   __ add(element,
3945          elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3946   result = elements;  // End of live range for elements.
3947   elements = no_reg;
3948   // Live values in registers:
3949   //   element: First array element
3950   //   separator: Separator string
3951   //   string_length: Length of result string (not smi)
3952   //   array_length: Length of the array.
3953   __ AllocateAsciiString(result,
3954                          string_length,
3955                          scratch,
3956                          string,  // used as scratch
3957                          elements_end,  // used as scratch
3958                          &bailout);
3959   // Prepare for looping. Set up elements_end to end of the array. Set
3960   // result_pos to the position of the result where to write the first
3961   // character.
3962   __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2));
3963   result_pos = array_length;  // End of live range for array_length.
3964   array_length = no_reg;
3965   __ add(result_pos,
3966          result,
3967          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3968
3969   // Check the length of the separator.
3970   __ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
3971   __ cmp(scratch, Operand(Smi::FromInt(1)));
3972   __ b(eq, &one_char_separator);
3973   __ b(gt, &long_separator);
3974
3975   // Empty separator case
3976   __ bind(&empty_separator_loop);
3977   // Live values in registers:
3978   //   result_pos: the position to which we are currently copying characters.
3979   //   element: Current array element.
3980   //   elements_end: Array end.
3981
3982   // Copy next array element to the result.
3983   __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
3984   __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
3985   __ SmiUntag(string_length);
3986   __ add(string,
3987          string,
3988          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3989   __ CopyBytes(string, result_pos, string_length, scratch);
3990   __ cmp(element, elements_end);
3991   __ b(lt, &empty_separator_loop);  // End while (element < elements_end).
3992   ASSERT(result.is(r0));
3993   __ b(&done);
3994
3995   // One-character separator case
3996   __ bind(&one_char_separator);
3997   // Replace separator with its ASCII character value.
3998   __ ldrb(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize));
3999   // Jump into the loop after the code that copies the separator, so the first
4000   // element is not preceded by a separator
4001   __ jmp(&one_char_separator_loop_entry);
4002
4003   __ bind(&one_char_separator_loop);
4004   // Live values in registers:
4005   //   result_pos: the position to which we are currently copying characters.
4006   //   element: Current array element.
4007   //   elements_end: Array end.
4008   //   separator: Single separator ASCII char (in lower byte).
4009
4010   // Copy the separator character to the result.
4011   __ strb(separator, MemOperand(result_pos, 1, PostIndex));
4012
4013   // Copy next array element to the result.
4014   __ bind(&one_char_separator_loop_entry);
4015   __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
4016   __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
4017   __ SmiUntag(string_length);
4018   __ add(string,
4019          string,
4020          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
4021   __ CopyBytes(string, result_pos, string_length, scratch);
4022   __ cmp(element, elements_end);
4023   __ b(lt, &one_char_separator_loop);  // End while (element < elements_end).
4024   ASSERT(result.is(r0));
4025   __ b(&done);
4026
4027   // Long separator case (separator is more than one character). Entry is at the
4028   // label long_separator below.
4029   __ bind(&long_separator_loop);
4030   // Live values in registers:
4031   //   result_pos: the position to which we are currently copying characters.
4032   //   element: Current array element.
4033   //   elements_end: Array end.
4034   //   separator: Separator string.
4035
4036   // Copy the separator to the result.
4037   __ ldr(string_length, FieldMemOperand(separator, String::kLengthOffset));
4038   __ SmiUntag(string_length);
4039   __ add(string,
4040          separator,
4041          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
4042   __ CopyBytes(string, result_pos, string_length, scratch);
4043
4044   __ bind(&long_separator);
4045   __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
4046   __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
4047   __ SmiUntag(string_length);
4048   __ add(string,
4049          string,
4050          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
4051   __ CopyBytes(string, result_pos, string_length, scratch);
4052   __ cmp(element, elements_end);
4053   __ b(lt, &long_separator_loop);  // End while (element < elements_end).
4054   ASSERT(result.is(r0));
4055   __ b(&done);
4056
4057   __ bind(&bailout);
4058   __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
4059   __ bind(&done);
4060   context()->Plug(r0);
4061 }
4062
4063
4064 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
4065   if (expr->function() != NULL &&
4066       expr->function()->intrinsic_type == Runtime::INLINE) {
4067     Comment cmnt(masm_, "[ InlineRuntimeCall");
4068     EmitInlineRuntimeCall(expr);
4069     return;
4070   }
4071
4072   Comment cmnt(masm_, "[ CallRuntime");
4073   ZoneList<Expression*>* args = expr->arguments();
4074   int arg_count = args->length();
4075
4076   if (expr->is_jsruntime()) {
4077     // Push the builtins object as the receiver.
4078     __ ldr(r0, GlobalObjectOperand());
4079     __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset));
4080     __ push(r0);
4081
4082     // Load the function from the receiver.
4083     __ mov(r2, Operand(expr->name()));
4084     CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
4085
4086     // Push the target function under the receiver.
4087     __ ldr(ip, MemOperand(sp, 0));
4088     __ push(ip);
4089     __ str(r0, MemOperand(sp, kPointerSize));
4090
4091     // Push the arguments ("left-to-right").
4092     int arg_count = args->length();
4093     for (int i = 0; i < arg_count; i++) {
4094       VisitForStackValue(args->at(i));
4095     }
4096
4097     // Record source position of the IC call.
4098     SetSourcePosition(expr->position());
4099     CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
4100     __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
4101     __ CallStub(&stub);
4102
4103     // Restore context register.
4104     __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
4105
4106     context()->DropAndPlug(1, r0);
4107   } else {
4108     // Push the arguments ("left-to-right").
4109     for (int i = 0; i < arg_count; i++) {
4110       VisitForStackValue(args->at(i));
4111     }
4112
4113     // Call the C runtime function.
4114     __ CallRuntime(expr->function(), arg_count);
4115     context()->Plug(r0);
4116   }
4117 }
4118
4119
4120 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
4121   switch (expr->op()) {
4122     case Token::DELETE: {
4123       Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
4124       Property* property = expr->expression()->AsProperty();
4125       VariableProxy* proxy = expr->expression()->AsVariableProxy();
4126
4127       if (property != NULL) {
4128         VisitForStackValue(property->obj());
4129         VisitForStackValue(property->key());
4130         __ mov(r1, Operand(Smi::FromInt(strict_mode())));
4131         __ push(r1);
4132         __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
4133         context()->Plug(r0);
4134       } else if (proxy != NULL) {
4135         Variable* var = proxy->var();
4136         // Delete of an unqualified identifier is disallowed in strict mode
4137         // but "delete this" is allowed.
4138         ASSERT(strict_mode() == SLOPPY || var->is_this());
4139         if (var->IsUnallocated()) {
4140           __ ldr(r2, GlobalObjectOperand());
4141           __ mov(r1, Operand(var->name()));
4142           __ mov(r0, Operand(Smi::FromInt(SLOPPY)));
4143           __ Push(r2, r1, r0);
4144           __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
4145           context()->Plug(r0);
4146         } else if (var->IsStackAllocated() || var->IsContextSlot()) {
4147           // Result of deleting non-global, non-dynamic variables is false.
4148           // The subexpression does not have side effects.
4149           context()->Plug(var->is_this());
4150         } else {
4151           // Non-global variable.  Call the runtime to try to delete from the
4152           // context where the variable was introduced.
4153           ASSERT(!context_register().is(r2));
4154           __ mov(r2, Operand(var->name()));
4155           __ Push(context_register(), r2);
4156           __ CallRuntime(Runtime::kHiddenDeleteContextSlot, 2);
4157           context()->Plug(r0);
4158         }
4159       } else {
4160         // Result of deleting non-property, non-variable reference is true.
4161         // The subexpression may have side effects.
4162         VisitForEffect(expr->expression());
4163         context()->Plug(true);
4164       }
4165       break;
4166     }
4167
4168     case Token::VOID: {
4169       Comment cmnt(masm_, "[ UnaryOperation (VOID)");
4170       VisitForEffect(expr->expression());
4171       context()->Plug(Heap::kUndefinedValueRootIndex);
4172       break;
4173     }
4174
4175     case Token::NOT: {
4176       Comment cmnt(masm_, "[ UnaryOperation (NOT)");
4177       if (context()->IsEffect()) {
4178         // Unary NOT has no side effects so it's only necessary to visit the
4179         // subexpression.  Match the optimizing compiler by not branching.
4180         VisitForEffect(expr->expression());
4181       } else if (context()->IsTest()) {
4182         const TestContext* test = TestContext::cast(context());
4183         // The labels are swapped for the recursive call.
4184         VisitForControl(expr->expression(),
4185                         test->false_label(),
4186                         test->true_label(),
4187                         test->fall_through());
4188         context()->Plug(test->true_label(), test->false_label());
4189       } else {
4190         // We handle value contexts explicitly rather than simply visiting
4191         // for control and plugging the control flow into the context,
4192         // because we need to prepare a pair of extra administrative AST ids
4193         // for the optimizing compiler.
4194         ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
4195         Label materialize_true, materialize_false, done;
4196         VisitForControl(expr->expression(),
4197                         &materialize_false,
4198                         &materialize_true,
4199                         &materialize_true);
4200         __ bind(&materialize_true);
4201         PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
4202         __ LoadRoot(r0, Heap::kTrueValueRootIndex);
4203         if (context()->IsStackValue()) __ push(r0);
4204         __ jmp(&done);
4205         __ bind(&materialize_false);
4206         PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
4207         __ LoadRoot(r0, Heap::kFalseValueRootIndex);
4208         if (context()->IsStackValue()) __ push(r0);
4209         __ bind(&done);
4210       }
4211       break;
4212     }
4213
4214     case Token::TYPEOF: {
4215       Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
4216       { StackValueContext context(this);
4217         VisitForTypeofValue(expr->expression());
4218       }
4219       __ CallRuntime(Runtime::kTypeof, 1);
4220       context()->Plug(r0);
4221       break;
4222     }
4223
4224     default:
4225       UNREACHABLE();
4226   }
4227 }
4228
4229
4230 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
4231   ASSERT(expr->expression()->IsValidReferenceExpression());
4232
4233   Comment cmnt(masm_, "[ CountOperation");
4234   SetSourcePosition(expr->position());
4235
4236   // Expression can only be a property, a global or a (parameter or local)
4237   // slot.
4238   enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
4239   LhsKind assign_type = VARIABLE;
4240   Property* prop = expr->expression()->AsProperty();
4241   // In case of a property we use the uninitialized expression context
4242   // of the key to detect a named property.
4243   if (prop != NULL) {
4244     assign_type =
4245         (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
4246   }
4247
4248   // Evaluate expression and get value.
4249   if (assign_type == VARIABLE) {
4250     ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
4251     AccumulatorValueContext context(this);
4252     EmitVariableLoad(expr->expression()->AsVariableProxy());
4253   } else {
4254     // Reserve space for result of postfix operation.
4255     if (expr->is_postfix() && !context()->IsEffect()) {
4256       __ mov(ip, Operand(Smi::FromInt(0)));
4257       __ push(ip);
4258     }
4259     if (assign_type == NAMED_PROPERTY) {
4260       // Put the object both on the stack and in the accumulator.
4261       VisitForAccumulatorValue(prop->obj());
4262       __ push(r0);
4263       EmitNamedPropertyLoad(prop);
4264     } else {
4265       VisitForStackValue(prop->obj());
4266       VisitForAccumulatorValue(prop->key());
4267       __ ldr(r1, MemOperand(sp, 0));
4268       __ push(r0);
4269       EmitKeyedPropertyLoad(prop);
4270     }
4271   }
4272
4273   // We need a second deoptimization point after loading the value
4274   // in case evaluating the property load my have a side effect.
4275   if (assign_type == VARIABLE) {
4276     PrepareForBailout(expr->expression(), TOS_REG);
4277   } else {
4278     PrepareForBailoutForId(prop->LoadId(), TOS_REG);
4279   }
4280
4281   // Inline smi case if we are in a loop.
4282   Label stub_call, done;
4283   JumpPatchSite patch_site(masm_);
4284
4285   int count_value = expr->op() == Token::INC ? 1 : -1;
4286   if (ShouldInlineSmiCase(expr->op())) {
4287     Label slow;
4288     patch_site.EmitJumpIfNotSmi(r0, &slow);
4289
4290     // Save result for postfix expressions.
4291     if (expr->is_postfix()) {
4292       if (!context()->IsEffect()) {
4293         // Save the result on the stack. If we have a named or keyed property
4294         // we store the result under the receiver that is currently on top
4295         // of the stack.
4296         switch (assign_type) {
4297           case VARIABLE:
4298             __ push(r0);
4299             break;
4300           case NAMED_PROPERTY:
4301             __ str(r0, MemOperand(sp, kPointerSize));
4302             break;
4303           case KEYED_PROPERTY:
4304             __ str(r0, MemOperand(sp, 2 * kPointerSize));
4305             break;
4306         }
4307       }
4308     }
4309
4310     __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC);
4311     __ b(vc, &done);
4312     // Call stub. Undo operation first.
4313     __ sub(r0, r0, Operand(Smi::FromInt(count_value)));
4314     __ jmp(&stub_call);
4315     __ bind(&slow);
4316   }
4317   ToNumberStub convert_stub(isolate());
4318   __ CallStub(&convert_stub);
4319
4320   // Save result for postfix expressions.
4321   if (expr->is_postfix()) {
4322     if (!context()->IsEffect()) {
4323       // Save the result on the stack. If we have a named or keyed property
4324       // we store the result under the receiver that is currently on top
4325       // of the stack.
4326       switch (assign_type) {
4327         case VARIABLE:
4328           __ push(r0);
4329           break;
4330         case NAMED_PROPERTY:
4331           __ str(r0, MemOperand(sp, kPointerSize));
4332           break;
4333         case KEYED_PROPERTY:
4334           __ str(r0, MemOperand(sp, 2 * kPointerSize));
4335           break;
4336       }
4337     }
4338   }
4339
4340
4341   __ bind(&stub_call);
4342   __ mov(r1, r0);
4343   __ mov(r0, Operand(Smi::FromInt(count_value)));
4344
4345   // Record position before stub call.
4346   SetSourcePosition(expr->position());
4347
4348   BinaryOpICStub stub(isolate(), Token::ADD, NO_OVERWRITE);
4349   CallIC(stub.GetCode(), expr->CountBinOpFeedbackId());
4350   patch_site.EmitPatchInfo();
4351   __ bind(&done);
4352
4353   // Store the value returned in r0.
4354   switch (assign_type) {
4355     case VARIABLE:
4356       if (expr->is_postfix()) {
4357         { EffectContext context(this);
4358           EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4359                                  Token::ASSIGN);
4360           PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4361           context.Plug(r0);
4362         }
4363         // For all contexts except EffectConstant We have the result on
4364         // top of the stack.
4365         if (!context()->IsEffect()) {
4366           context()->PlugTOS();
4367         }
4368       } else {
4369         EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4370                                Token::ASSIGN);
4371         PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4372         context()->Plug(r0);
4373       }
4374       break;
4375     case NAMED_PROPERTY: {
4376       __ mov(r2, Operand(prop->key()->AsLiteral()->value()));
4377       __ pop(r1);
4378       CallStoreIC(expr->CountStoreFeedbackId());
4379       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4380       if (expr->is_postfix()) {
4381         if (!context()->IsEffect()) {
4382           context()->PlugTOS();
4383         }
4384       } else {
4385         context()->Plug(r0);
4386       }
4387       break;
4388     }
4389     case KEYED_PROPERTY: {
4390       __ Pop(r2, r1);  // r1 = key. r2 = receiver.
4391       Handle<Code> ic = strict_mode() == SLOPPY
4392           ? isolate()->builtins()->KeyedStoreIC_Initialize()
4393           : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
4394       CallIC(ic, expr->CountStoreFeedbackId());
4395       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4396       if (expr->is_postfix()) {
4397         if (!context()->IsEffect()) {
4398           context()->PlugTOS();
4399         }
4400       } else {
4401         context()->Plug(r0);
4402       }
4403       break;
4404     }
4405   }
4406 }
4407
4408
4409 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
4410   ASSERT(!context()->IsEffect());
4411   ASSERT(!context()->IsTest());
4412   VariableProxy* proxy = expr->AsVariableProxy();
4413   if (proxy != NULL && proxy->var()->IsUnallocated()) {
4414     Comment cmnt(masm_, "[ Global variable");
4415     __ ldr(r0, GlobalObjectOperand());
4416     __ mov(r2, Operand(proxy->name()));
4417     // Use a regular load, not a contextual load, to avoid a reference
4418     // error.
4419     CallLoadIC(NOT_CONTEXTUAL);
4420     PrepareForBailout(expr, TOS_REG);
4421     context()->Plug(r0);
4422   } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
4423     Comment cmnt(masm_, "[ Lookup slot");
4424     Label done, slow;
4425
4426     // Generate code for loading from variables potentially shadowed
4427     // by eval-introduced variables.
4428     EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
4429
4430     __ bind(&slow);
4431     __ mov(r0, Operand(proxy->name()));
4432     __ Push(cp, r0);
4433     __ CallRuntime(Runtime::kHiddenLoadContextSlotNoReferenceError, 2);
4434     PrepareForBailout(expr, TOS_REG);
4435     __ bind(&done);
4436
4437     context()->Plug(r0);
4438   } else {
4439     // This expression cannot throw a reference error at the top level.
4440     VisitInDuplicateContext(expr);
4441   }
4442 }
4443
4444
4445 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
4446                                                  Expression* sub_expr,
4447                                                  Handle<String> check) {
4448   Label materialize_true, materialize_false;
4449   Label* if_true = NULL;
4450   Label* if_false = NULL;
4451   Label* fall_through = NULL;
4452   context()->PrepareTest(&materialize_true, &materialize_false,
4453                          &if_true, &if_false, &fall_through);
4454
4455   { AccumulatorValueContext context(this);
4456     VisitForTypeofValue(sub_expr);
4457   }
4458   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4459
4460   Factory* factory = isolate()->factory();
4461   if (String::Equals(check, factory->number_string())) {
4462     __ JumpIfSmi(r0, if_true);
4463     __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
4464     __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
4465     __ cmp(r0, ip);
4466     Split(eq, if_true, if_false, fall_through);
4467   } else if (String::Equals(check, factory->float32x4_string())) {
4468     __ JumpIfSmi(r0, if_false);
4469     __ CompareObjectType(r0, r0, r1, FLOAT32x4_TYPE);
4470     Split(eq, if_true, if_false, fall_through);
4471   } else if (String::Equals(check, factory->float64x2_string())) {
4472     __ JumpIfSmi(r0, if_false);
4473     __ CompareObjectType(r0, r0, r1, FLOAT64x2_TYPE);
4474     Split(eq, if_true, if_false, fall_through);
4475   } else if (String::Equals(check, factory->int32x4_string())) {
4476     __ JumpIfSmi(r0, if_false);
4477     __ CompareObjectType(r0, r0, r1, INT32x4_TYPE);
4478     Split(eq, if_true, if_false, fall_through);
4479   } else if (String::Equals(check, factory->string_string())) {
4480     __ JumpIfSmi(r0, if_false);
4481     // Check for undetectable objects => false.
4482     __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE);
4483     __ b(ge, if_false);
4484     __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
4485     __ tst(r1, Operand(1 << Map::kIsUndetectable));
4486     Split(eq, if_true, if_false, fall_through);
4487   } else if (String::Equals(check, factory->symbol_string())) {
4488     __ JumpIfSmi(r0, if_false);
4489     __ CompareObjectType(r0, r0, r1, SYMBOL_TYPE);
4490     Split(eq, if_true, if_false, fall_through);
4491   } else if (String::Equals(check, factory->boolean_string())) {
4492     __ CompareRoot(r0, Heap::kTrueValueRootIndex);
4493     __ b(eq, if_true);
4494     __ CompareRoot(r0, Heap::kFalseValueRootIndex);
4495     Split(eq, if_true, if_false, fall_through);
4496   } else if (FLAG_harmony_typeof &&
4497              String::Equals(check, factory->null_string())) {
4498     __ CompareRoot(r0, Heap::kNullValueRootIndex);
4499     Split(eq, if_true, if_false, fall_through);
4500   } else if (String::Equals(check, factory->undefined_string())) {
4501     __ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
4502     __ b(eq, if_true);
4503     __ JumpIfSmi(r0, if_false);
4504     // Check for undetectable objects => true.
4505     __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
4506     __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
4507     __ tst(r1, Operand(1 << Map::kIsUndetectable));
4508     Split(ne, if_true, if_false, fall_through);
4509
4510   } else if (String::Equals(check, factory->function_string())) {
4511     __ JumpIfSmi(r0, if_false);
4512     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
4513     __ CompareObjectType(r0, r0, r1, JS_FUNCTION_TYPE);
4514     __ b(eq, if_true);
4515     __ cmp(r1, Operand(JS_FUNCTION_PROXY_TYPE));
4516     Split(eq, if_true, if_false, fall_through);
4517   } else if (String::Equals(check, factory->object_string())) {
4518     __ JumpIfSmi(r0, if_false);
4519     if (!FLAG_harmony_typeof) {
4520       __ CompareRoot(r0, Heap::kNullValueRootIndex);
4521       __ b(eq, if_true);
4522     }
4523     // Check for JS objects => true.
4524     __ CompareObjectType(r0, r0, r1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
4525     __ b(lt, if_false);
4526     __ CompareInstanceType(r0, r1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
4527     __ b(gt, if_false);
4528     // Check for undetectable objects => false.
4529     __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
4530     __ tst(r1, Operand(1 << Map::kIsUndetectable));
4531     Split(eq, if_true, if_false, fall_through);
4532   } else {
4533     if (if_false != fall_through) __ jmp(if_false);
4534   }
4535   context()->Plug(if_true, if_false);
4536 }
4537
4538
4539 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4540   Comment cmnt(masm_, "[ CompareOperation");
4541   SetSourcePosition(expr->position());
4542
4543   // First we try a fast inlined version of the compare when one of
4544   // the operands is a literal.
4545   if (TryLiteralCompare(expr)) return;
4546
4547   // Always perform the comparison for its control flow.  Pack the result
4548   // into the expression's context after the comparison is performed.
4549   Label materialize_true, materialize_false;
4550   Label* if_true = NULL;
4551   Label* if_false = NULL;
4552   Label* fall_through = NULL;
4553   context()->PrepareTest(&materialize_true, &materialize_false,
4554                          &if_true, &if_false, &fall_through);
4555
4556   Token::Value op = expr->op();
4557   VisitForStackValue(expr->left());
4558   switch (op) {
4559     case Token::IN:
4560       VisitForStackValue(expr->right());
4561       __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
4562       PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
4563       __ LoadRoot(ip, Heap::kTrueValueRootIndex);
4564       __ cmp(r0, ip);
4565       Split(eq, if_true, if_false, fall_through);
4566       break;
4567
4568     case Token::INSTANCEOF: {
4569       VisitForStackValue(expr->right());
4570       InstanceofStub stub(isolate(), InstanceofStub::kNoFlags);
4571       __ CallStub(&stub);
4572       PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4573       // The stub returns 0 for true.
4574       __ tst(r0, r0);
4575       Split(eq, if_true, if_false, fall_through);
4576       break;
4577     }
4578
4579     default: {
4580       VisitForAccumulatorValue(expr->right());
4581       Condition cond = CompareIC::ComputeCondition(op);
4582       __ pop(r1);
4583
4584       bool inline_smi_code = ShouldInlineSmiCase(op);
4585       JumpPatchSite patch_site(masm_);
4586       if (inline_smi_code) {
4587         Label slow_case;
4588         __ orr(r2, r0, Operand(r1));
4589         patch_site.EmitJumpIfNotSmi(r2, &slow_case);
4590         __ cmp(r1, r0);
4591         Split(cond, if_true, if_false, NULL);
4592         __ bind(&slow_case);
4593       }
4594
4595       // Record position and call the compare IC.
4596       SetSourcePosition(expr->position());
4597       Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
4598       CallIC(ic, expr->CompareOperationFeedbackId());
4599       patch_site.EmitPatchInfo();
4600       PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4601       __ cmp(r0, Operand::Zero());
4602       Split(cond, if_true, if_false, fall_through);
4603     }
4604   }
4605
4606   // Convert the result of the comparison into one expected for this
4607   // expression's context.
4608   context()->Plug(if_true, if_false);
4609 }
4610
4611
4612 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
4613                                               Expression* sub_expr,
4614                                               NilValue nil) {
4615   Label materialize_true, materialize_false;
4616   Label* if_true = NULL;
4617   Label* if_false = NULL;
4618   Label* fall_through = NULL;
4619   context()->PrepareTest(&materialize_true, &materialize_false,
4620                          &if_true, &if_false, &fall_through);
4621
4622   VisitForAccumulatorValue(sub_expr);
4623   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4624   if (expr->op() == Token::EQ_STRICT) {
4625     Heap::RootListIndex nil_value = nil == kNullValue ?
4626         Heap::kNullValueRootIndex :
4627         Heap::kUndefinedValueRootIndex;
4628     __ LoadRoot(r1, nil_value);
4629     __ cmp(r0, r1);
4630     Split(eq, if_true, if_false, fall_through);
4631   } else {
4632     Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
4633     CallIC(ic, expr->CompareOperationFeedbackId());
4634     __ cmp(r0, Operand(0));
4635     Split(ne, if_true, if_false, fall_through);
4636   }
4637   context()->Plug(if_true, if_false);
4638 }
4639
4640
4641 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4642   __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
4643   context()->Plug(r0);
4644 }
4645
4646
4647 Register FullCodeGenerator::result_register() {
4648   return r0;
4649 }
4650
4651
4652 Register FullCodeGenerator::context_register() {
4653   return cp;
4654 }
4655
4656
4657 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4658   ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
4659   __ str(value, MemOperand(fp, frame_offset));
4660 }
4661
4662
4663 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
4664   __ ldr(dst, ContextOperand(cp, context_index));
4665 }
4666
4667
4668 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
4669   Scope* declaration_scope = scope()->DeclarationScope();
4670   if (declaration_scope->is_global_scope() ||
4671       declaration_scope->is_module_scope()) {
4672     // Contexts nested in the native context have a canonical empty function
4673     // as their closure, not the anonymous closure containing the global
4674     // code.  Pass a smi sentinel and let the runtime look up the empty
4675     // function.
4676     __ mov(ip, Operand(Smi::FromInt(0)));
4677   } else if (declaration_scope->is_eval_scope()) {
4678     // Contexts created by a call to eval have the same closure as the
4679     // context calling eval, not the anonymous closure containing the eval
4680     // code.  Fetch it from the context.
4681     __ ldr(ip, ContextOperand(cp, Context::CLOSURE_INDEX));
4682   } else {
4683     ASSERT(declaration_scope->is_function_scope());
4684     __ ldr(ip, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
4685   }
4686   __ push(ip);
4687 }
4688
4689
4690 // ----------------------------------------------------------------------------
4691 // Non-local control flow support.
4692
4693 void FullCodeGenerator::EnterFinallyBlock() {
4694   ASSERT(!result_register().is(r1));
4695   // Store result register while executing finally block.
4696   __ push(result_register());
4697   // Cook return address in link register to stack (smi encoded Code* delta)
4698   __ sub(r1, lr, Operand(masm_->CodeObject()));
4699   __ SmiTag(r1);
4700
4701   // Store result register while executing finally block.
4702   __ push(r1);
4703
4704   // Store pending message while executing finally block.
4705   ExternalReference pending_message_obj =
4706       ExternalReference::address_of_pending_message_obj(isolate());
4707   __ mov(ip, Operand(pending_message_obj));
4708   __ ldr(r1, MemOperand(ip));
4709   __ push(r1);
4710
4711   ExternalReference has_pending_message =
4712       ExternalReference::address_of_has_pending_message(isolate());
4713   __ mov(ip, Operand(has_pending_message));
4714   STATIC_ASSERT(sizeof(bool) == 1);   // NOLINT(runtime/sizeof)
4715   __ ldrb(r1, MemOperand(ip));
4716   __ SmiTag(r1);
4717   __ push(r1);
4718
4719   ExternalReference pending_message_script =
4720       ExternalReference::address_of_pending_message_script(isolate());
4721   __ mov(ip, Operand(pending_message_script));
4722   __ ldr(r1, MemOperand(ip));
4723   __ push(r1);
4724 }
4725
4726
4727 void FullCodeGenerator::ExitFinallyBlock() {
4728   ASSERT(!result_register().is(r1));
4729   // Restore pending message from stack.
4730   __ pop(r1);
4731   ExternalReference pending_message_script =
4732       ExternalReference::address_of_pending_message_script(isolate());
4733   __ mov(ip, Operand(pending_message_script));
4734   __ str(r1, MemOperand(ip));
4735
4736   __ pop(r1);
4737   __ SmiUntag(r1);
4738   ExternalReference has_pending_message =
4739       ExternalReference::address_of_has_pending_message(isolate());
4740   __ mov(ip, Operand(has_pending_message));
4741   STATIC_ASSERT(sizeof(bool) == 1);   // NOLINT(runtime/sizeof)
4742   __ strb(r1, MemOperand(ip));
4743
4744   __ pop(r1);
4745   ExternalReference pending_message_obj =
4746       ExternalReference::address_of_pending_message_obj(isolate());
4747   __ mov(ip, Operand(pending_message_obj));
4748   __ str(r1, MemOperand(ip));
4749
4750   // Restore result register from stack.
4751   __ pop(r1);
4752
4753   // Uncook return address and return.
4754   __ pop(result_register());
4755   __ SmiUntag(r1);
4756   __ add(pc, r1, Operand(masm_->CodeObject()));
4757 }
4758
4759
4760 #undef __
4761
4762 #define __ ACCESS_MASM(masm())
4763
4764 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
4765     int* stack_depth,
4766     int* context_length) {
4767   // The macros used here must preserve the result register.
4768
4769   // Because the handler block contains the context of the finally
4770   // code, we can restore it directly from there for the finally code
4771   // rather than iteratively unwinding contexts via their previous
4772   // links.
4773   __ Drop(*stack_depth);  // Down to the handler block.
4774   if (*context_length > 0) {
4775     // Restore the context to its dedicated register and the stack.
4776     __ ldr(cp, MemOperand(sp, StackHandlerConstants::kContextOffset));
4777     __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
4778   }
4779   __ PopTryHandler();
4780   __ bl(finally_entry_);
4781
4782   *stack_depth = 0;
4783   *context_length = 0;
4784   return previous_;
4785 }
4786
4787
4788 #undef __
4789
4790
4791 static Address GetInterruptImmediateLoadAddress(Address pc) {
4792   Address load_address = pc - 2 * Assembler::kInstrSize;
4793   if (!FLAG_enable_ool_constant_pool) {
4794     ASSERT(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(load_address)));
4795   } else if (Assembler::IsMovT(Memory::int32_at(load_address))) {
4796     load_address -= Assembler::kInstrSize;
4797     ASSERT(Assembler::IsMovW(Memory::int32_at(load_address)));
4798   } else {
4799     ASSERT(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(load_address)));
4800   }
4801   return load_address;
4802 }
4803
4804
4805 void BackEdgeTable::PatchAt(Code* unoptimized_code,
4806                             Address pc,
4807                             BackEdgeState target_state,
4808                             Code* replacement_code) {
4809   static const int kInstrSize = Assembler::kInstrSize;
4810   Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc);
4811   Address branch_address = pc_immediate_load_address - kInstrSize;
4812   CodePatcher patcher(branch_address, 1);
4813   switch (target_state) {
4814     case INTERRUPT:
4815     {
4816       //  <decrement profiling counter>
4817       //   bpl ok
4818       //   ; load interrupt stub address into ip - either of:
4819       //   ldr ip, [pc/pp, <constant pool offset>]  |   movw ip, <immed low>
4820       //                                            |   movt ip, <immed high>
4821       //   blx ip
4822       //  ok-label
4823
4824       // Calculate branch offet to the ok-label - this is the difference between
4825       // the branch address and |pc| (which points at <blx ip>) plus one instr.
4826       int branch_offset = pc + kInstrSize - branch_address;
4827       patcher.masm()->b(branch_offset, pl);
4828       break;
4829     }
4830     case ON_STACK_REPLACEMENT:
4831     case OSR_AFTER_STACK_CHECK:
4832       //  <decrement profiling counter>
4833       //   mov r0, r0 (NOP)
4834       //   ; load on-stack replacement address into ip - either of:
4835       //   ldr ip, [pc/pp, <constant pool offset>]  |   movw ip, <immed low>
4836       //                                            |   movt ip, <immed high>
4837       //   blx ip
4838       //  ok-label
4839       patcher.masm()->nop();
4840       break;
4841   }
4842
4843   // Replace the call address.
4844   Assembler::set_target_address_at(pc_immediate_load_address, unoptimized_code,
4845       replacement_code->entry());
4846
4847   unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
4848       unoptimized_code, pc_immediate_load_address, replacement_code);
4849 }
4850
4851
4852 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
4853     Isolate* isolate,
4854     Code* unoptimized_code,
4855     Address pc) {
4856   static const int kInstrSize = Assembler::kInstrSize;
4857   ASSERT(Memory::int32_at(pc - kInstrSize) == kBlxIp);
4858
4859   Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc);
4860   Address branch_address = pc_immediate_load_address - kInstrSize;
4861   Address interrupt_address = Assembler::target_address_at(
4862       pc_immediate_load_address, unoptimized_code);
4863
4864   if (Assembler::IsBranch(Assembler::instr_at(branch_address))) {
4865     ASSERT(interrupt_address ==
4866            isolate->builtins()->InterruptCheck()->entry());
4867     return INTERRUPT;
4868   }
4869
4870   ASSERT(Assembler::IsNop(Assembler::instr_at(branch_address)));
4871
4872   if (interrupt_address ==
4873       isolate->builtins()->OnStackReplacement()->entry()) {
4874     return ON_STACK_REPLACEMENT;
4875   }
4876
4877   ASSERT(interrupt_address ==
4878          isolate->builtins()->OsrAfterStackCheck()->entry());
4879   return OSR_AFTER_STACK_CHECK;
4880 }
4881
4882
4883 } }  // namespace v8::internal
4884
4885 #endif  // V8_TARGET_ARCH_ARM