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