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