1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#if V8_TARGET_ARCH_ARM
6
7#include "src/full-codegen/full-codegen.h"
8#include "src/ast/compile-time-value.h"
9#include "src/ast/scopes.h"
10#include "src/code-factory.h"
11#include "src/code-stubs.h"
12#include "src/codegen.h"
13#include "src/compilation-info.h"
14#include "src/compiler.h"
15#include "src/debug/debug.h"
16#include "src/ic/ic.h"
17
18#include "src/arm/code-stubs-arm.h"
19#include "src/arm/macro-assembler-arm.h"
20
21namespace v8 {
22namespace internal {
23
24#define __ ACCESS_MASM(masm())
25
26// A patch site is a location in the code which it is possible to patch. This
27// class has a number of methods to emit the code which is patchable and the
28// method EmitPatchInfo to record a marker back to the patchable code. This
29// marker is a cmp rx, #yyy instruction, and x * 0x00000fff + yyy (raw 12 bit
30// immediate value is used) is the delta from the pc to the first instruction of
31// the patchable code.
32class JumpPatchSite BASE_EMBEDDED {
33 public:
34  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
35#ifdef DEBUG
36    info_emitted_ = false;
37#endif
38  }
39
40  ~JumpPatchSite() {
41    DCHECK(patch_site_.is_bound() == info_emitted_);
42  }
43
44  // When initially emitting this ensure that a jump is always generated to skip
45  // the inlined smi code.
46  void EmitJumpIfNotSmi(Register reg, Label* target) {
47    DCHECK(!patch_site_.is_bound() && !info_emitted_);
48    Assembler::BlockConstPoolScope block_const_pool(masm_);
49    __ bind(&patch_site_);
50    __ cmp(reg, Operand(reg));
51    __ b(eq, target);  // Always taken before patched.
52  }
53
54  // When initially emitting this ensure that a jump is never generated to skip
55  // the inlined smi code.
56  void EmitJumpIfSmi(Register reg, Label* target) {
57    DCHECK(!patch_site_.is_bound() && !info_emitted_);
58    Assembler::BlockConstPoolScope block_const_pool(masm_);
59    __ bind(&patch_site_);
60    __ cmp(reg, Operand(reg));
61    __ b(ne, target);  // Never taken before patched.
62  }
63
64  void EmitPatchInfo() {
65    // Block literal pool emission whilst recording patch site information.
66    Assembler::BlockConstPoolScope block_const_pool(masm_);
67    if (patch_site_.is_bound()) {
68      int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_);
69      Register reg;
70      reg.set_code(delta_to_patch_site / kOff12Mask);
71      __ cmp_raw_immediate(reg, delta_to_patch_site % kOff12Mask);
72#ifdef DEBUG
73      info_emitted_ = true;
74#endif
75    } else {
76      __ nop();  // Signals no inlined code.
77    }
78  }
79
80 private:
81  MacroAssembler* masm() { return masm_; }
82  MacroAssembler* masm_;
83  Label patch_site_;
84#ifdef DEBUG
85  bool info_emitted_;
86#endif
87};
88
89
90// Generate code for a JS function.  On entry to the function the receiver
91// and arguments have been pushed on the stack left to right.  The actual
92// argument count matches the formal parameter count expected by the
93// function.
94//
95// The live registers are:
96//   o r1: the JS function object being called (i.e., ourselves)
97//   o r3: the new target value
98//   o cp: our context
99//   o pp: our caller's constant pool pointer (if enabled)
100//   o fp: our caller's frame pointer
101//   o sp: stack pointer
102//   o lr: return address
103//
104// The function builds a JS frame.  Please see JavaScriptFrameConstants in
105// frames-arm.h for its layout.
106void FullCodeGenerator::Generate() {
107  CompilationInfo* info = info_;
108  profiling_counter_ = isolate()->factory()->NewCell(
109      Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
110  SetFunctionPosition(literal());
111  Comment cmnt(masm_, "[ function compiled by full code generator");
112
113  ProfileEntryHookStub::MaybeCallEntryHook(masm_);
114
115  if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
116    int receiver_offset = info->scope()->num_parameters() * kPointerSize;
117    __ ldr(r2, MemOperand(sp, receiver_offset));
118    __ AssertNotSmi(r2);
119    __ CompareObjectType(r2, r2, no_reg, FIRST_JS_RECEIVER_TYPE);
120    __ Assert(ge, kSloppyFunctionExpectsJSReceiverReceiver);
121  }
122
123  // Open a frame scope to indicate that there is a frame on the stack.  The
124  // MANUAL indicates that the scope shouldn't actually generate code to set up
125  // the frame (that is done below).
126  FrameScope frame_scope(masm_, StackFrame::MANUAL);
127
128  info->set_prologue_offset(masm_->pc_offset());
129  __ Prologue(info->GeneratePreagedPrologue());
130
131  // Increment invocation count for the function.
132  {
133    Comment cmnt(masm_, "[ Increment invocation count");
134    __ ldr(r2, FieldMemOperand(r1, JSFunction::kLiteralsOffset));
135    __ ldr(r2, FieldMemOperand(r2, LiteralsArray::kFeedbackVectorOffset));
136    __ ldr(r9, FieldMemOperand(r2, TypeFeedbackVector::kInvocationCountIndex *
137                                           kPointerSize +
138                                       TypeFeedbackVector::kHeaderSize));
139    __ add(r9, r9, Operand(Smi::FromInt(1)));
140    __ str(r9, FieldMemOperand(r2, TypeFeedbackVector::kInvocationCountIndex *
141                                           kPointerSize +
142                                       TypeFeedbackVector::kHeaderSize));
143  }
144
145  { Comment cmnt(masm_, "[ Allocate locals");
146    int locals_count = info->scope()->num_stack_slots();
147    // Generators allocate locals, if any, in context slots.
148    DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0);
149    OperandStackDepthIncrement(locals_count);
150    if (locals_count > 0) {
151      if (locals_count >= 128) {
152        Label ok;
153        __ sub(r9, sp, Operand(locals_count * kPointerSize));
154        __ LoadRoot(r2, Heap::kRealStackLimitRootIndex);
155        __ cmp(r9, Operand(r2));
156        __ b(hs, &ok);
157        __ CallRuntime(Runtime::kThrowStackOverflow);
158        __ bind(&ok);
159      }
160      __ LoadRoot(r9, Heap::kUndefinedValueRootIndex);
161      int kMaxPushes = FLAG_optimize_for_size ? 4 : 32;
162      if (locals_count >= kMaxPushes) {
163        int loop_iterations = locals_count / kMaxPushes;
164        __ mov(r2, Operand(loop_iterations));
165        Label loop_header;
166        __ bind(&loop_header);
167        // Do pushes.
168        for (int i = 0; i < kMaxPushes; i++) {
169          __ push(r9);
170        }
171        // Continue loop if not done.
172        __ sub(r2, r2, Operand(1), SetCC);
173        __ b(&loop_header, ne);
174      }
175      int remaining = locals_count % kMaxPushes;
176      // Emit the remaining pushes.
177      for (int i  = 0; i < remaining; i++) {
178        __ push(r9);
179      }
180    }
181  }
182
183  bool function_in_register_r1 = true;
184
185  // Possibly allocate a local context.
186  if (info->scope()->NeedsContext()) {
187    // Argument to NewContext is the function, which is still in r1.
188    Comment cmnt(masm_, "[ Allocate context");
189    bool need_write_barrier = true;
190    int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
191    if (info->scope()->is_script_scope()) {
192      __ push(r1);
193      __ Push(info->scope()->scope_info());
194      __ CallRuntime(Runtime::kNewScriptContext);
195      PrepareForBailoutForId(BailoutId::ScriptContext(),
196                             BailoutState::TOS_REGISTER);
197      // The new target value is not used, clobbering is safe.
198      DCHECK_NULL(info->scope()->new_target_var());
199    } else {
200      if (info->scope()->new_target_var() != nullptr) {
201        __ push(r3);  // Preserve new target.
202      }
203      if (slots <= FastNewFunctionContextStub::kMaximumSlots) {
204        FastNewFunctionContextStub stub(isolate());
205        __ mov(FastNewFunctionContextDescriptor::SlotsRegister(),
206               Operand(slots));
207        __ CallStub(&stub);
208        // Result of FastNewFunctionContextStub is always in new space.
209        need_write_barrier = false;
210      } else {
211        __ push(r1);
212        __ CallRuntime(Runtime::kNewFunctionContext);
213      }
214      if (info->scope()->new_target_var() != nullptr) {
215        __ pop(r3);  // Preserve new target.
216      }
217    }
218    function_in_register_r1 = false;
219    // Context is returned in r0.  It replaces the context passed to us.
220    // It's saved in the stack and kept live in cp.
221    __ mov(cp, r0);
222    __ str(r0, MemOperand(fp, StandardFrameConstants::kContextOffset));
223    // Copy any necessary parameters into the context.
224    int num_parameters = info->scope()->num_parameters();
225    int first_parameter = info->scope()->has_this_declaration() ? -1 : 0;
226    for (int i = first_parameter; i < num_parameters; i++) {
227      Variable* var =
228          (i == -1) ? info->scope()->receiver() : info->scope()->parameter(i);
229      if (var->IsContextSlot()) {
230        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
231            (num_parameters - 1 - i) * kPointerSize;
232        // Load parameter from stack.
233        __ ldr(r0, MemOperand(fp, parameter_offset));
234        // Store it in the context.
235        MemOperand target = ContextMemOperand(cp, var->index());
236        __ str(r0, target);
237
238        // Update the write barrier.
239        if (need_write_barrier) {
240          __ RecordWriteContextSlot(cp, target.offset(), r0, r2,
241                                    kLRHasBeenSaved, kDontSaveFPRegs);
242        } else if (FLAG_debug_code) {
243          Label done;
244          __ JumpIfInNewSpace(cp, r0, &done);
245          __ Abort(kExpectedNewSpaceObject);
246          __ bind(&done);
247        }
248      }
249    }
250  }
251
252  // Register holding this function and new target are both trashed in case we
253  // bailout here. But since that can happen only when new target is not used
254  // and we allocate a context, the value of |function_in_register| is correct.
255  PrepareForBailoutForId(BailoutId::FunctionContext(),
256                         BailoutState::NO_REGISTERS);
257
258  // Possibly set up a local binding to the this function which is used in
259  // derived constructors with super calls.
260  Variable* this_function_var = info->scope()->this_function_var();
261  if (this_function_var != nullptr) {
262    Comment cmnt(masm_, "[ This function");
263    if (!function_in_register_r1) {
264      __ ldr(r1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
265      // The write barrier clobbers register again, keep it marked as such.
266    }
267    SetVar(this_function_var, r1, r0, r2);
268  }
269
270  // Possibly set up a local binding to the new target value.
271  Variable* new_target_var = info->scope()->new_target_var();
272  if (new_target_var != nullptr) {
273    Comment cmnt(masm_, "[ new.target");
274    SetVar(new_target_var, r3, r0, r2);
275  }
276
277  // Possibly allocate RestParameters
278  Variable* rest_param = info->scope()->rest_parameter();
279  if (rest_param != nullptr) {
280    Comment cmnt(masm_, "[ Allocate rest parameter array");
281    if (!function_in_register_r1) {
282      __ ldr(r1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
283    }
284    FastNewRestParameterStub stub(isolate());
285    __ CallStub(&stub);
286    function_in_register_r1 = false;
287    SetVar(rest_param, r0, r1, r2);
288  }
289
290  Variable* arguments = info->scope()->arguments();
291  if (arguments != NULL) {
292    // Function uses arguments object.
293    Comment cmnt(masm_, "[ Allocate arguments object");
294    if (!function_in_register_r1) {
295      // Load this again, if it's used by the local context below.
296      __ ldr(r1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
297    }
298    if (is_strict(language_mode()) || !has_simple_parameters()) {
299      FastNewStrictArgumentsStub stub(isolate());
300      __ CallStub(&stub);
301    } else if (literal()->has_duplicate_parameters()) {
302      __ Push(r1);
303      __ CallRuntime(Runtime::kNewSloppyArguments_Generic);
304    } else {
305      FastNewSloppyArgumentsStub stub(isolate());
306      __ CallStub(&stub);
307    }
308
309    SetVar(arguments, r0, r1, r2);
310  }
311
312  if (FLAG_trace) {
313    __ CallRuntime(Runtime::kTraceEnter);
314  }
315
316  // Visit the declarations and body.
317  PrepareForBailoutForId(BailoutId::FunctionEntry(),
318                         BailoutState::NO_REGISTERS);
319  {
320    Comment cmnt(masm_, "[ Declarations");
321    VisitDeclarations(scope()->declarations());
322  }
323
324  // Assert that the declarations do not use ICs. Otherwise the debugger
325  // won't be able to redirect a PC at an IC to the correct IC in newly
326  // recompiled code.
327  DCHECK_EQ(0, ic_total_count_);
328
329  {
330    Comment cmnt(masm_, "[ Stack check");
331    PrepareForBailoutForId(BailoutId::Declarations(),
332                           BailoutState::NO_REGISTERS);
333    Label ok;
334    __ LoadRoot(ip, Heap::kStackLimitRootIndex);
335    __ cmp(sp, Operand(ip));
336    __ b(hs, &ok);
337    Handle<Code> stack_check = isolate()->builtins()->StackCheck();
338    PredictableCodeSizeScope predictable(masm_);
339    predictable.ExpectSize(
340        masm_->CallSize(stack_check, RelocInfo::CODE_TARGET));
341    __ Call(stack_check, RelocInfo::CODE_TARGET);
342    __ bind(&ok);
343  }
344
345  {
346    Comment cmnt(masm_, "[ Body");
347    DCHECK(loop_depth() == 0);
348    VisitStatements(literal()->body());
349    DCHECK(loop_depth() == 0);
350  }
351
352  // Always emit a 'return undefined' in case control fell off the end of
353  // the body.
354  { Comment cmnt(masm_, "[ return <undefined>;");
355    __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
356  }
357  EmitReturnSequence();
358
359  // Force emit the constant pool, so it doesn't get emitted in the middle
360  // of the back edge table.
361  masm()->CheckConstPool(true, false);
362}
363
364void FullCodeGenerator::ClearAccumulator() { __ mov(r0, Operand(Smi::kZero)); }
365
366void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
367  __ mov(r2, Operand(profiling_counter_));
368  __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
369  __ sub(r3, r3, Operand(Smi::FromInt(delta)), SetCC);
370  __ str(r3, FieldMemOperand(r2, Cell::kValueOffset));
371}
372
373
374#ifdef CAN_USE_ARMV7_INSTRUCTIONS
375static const int kProfileCounterResetSequenceLength = 5 * Assembler::kInstrSize;
376#else
377static const int kProfileCounterResetSequenceLength = 7 * Assembler::kInstrSize;
378#endif
379
380
381void FullCodeGenerator::EmitProfilingCounterReset() {
382  Assembler::BlockConstPoolScope block_const_pool(masm_);
383  PredictableCodeSizeScope predictable_code_size_scope(
384      masm_, kProfileCounterResetSequenceLength);
385  Label start;
386  __ bind(&start);
387  int reset_value = FLAG_interrupt_budget;
388  __ mov(r2, Operand(profiling_counter_));
389  // The mov instruction above can be either 1 to 3 (for ARMv7) or 1 to 5
390  // instructions (for ARMv6) depending upon whether it is an extended constant
391  // pool - insert nop to compensate.
392  int expected_instr_count =
393      (kProfileCounterResetSequenceLength / Assembler::kInstrSize) - 2;
394  DCHECK(masm_->InstructionsGeneratedSince(&start) <= expected_instr_count);
395  while (masm_->InstructionsGeneratedSince(&start) != expected_instr_count) {
396    __ nop();
397  }
398  __ mov(r3, Operand(Smi::FromInt(reset_value)));
399  __ str(r3, FieldMemOperand(r2, Cell::kValueOffset));
400}
401
402
403void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
404                                                Label* back_edge_target) {
405  Comment cmnt(masm_, "[ Back edge bookkeeping");
406  // Block literal pools whilst emitting back edge code.
407  Assembler::BlockConstPoolScope block_const_pool(masm_);
408  Label ok;
409
410  DCHECK(back_edge_target->is_bound());
411  int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
412  int weight = Min(kMaxBackEdgeWeight,
413                   Max(1, distance / kCodeSizeMultiplier));
414  EmitProfilingCounterDecrement(weight);
415  __ b(pl, &ok);
416  __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
417
418  // Record a mapping of this PC offset to the OSR id.  This is used to find
419  // the AST id from the unoptimized code in order to use it as a key into
420  // the deoptimization input data found in the optimized code.
421  RecordBackEdge(stmt->OsrEntryId());
422
423  EmitProfilingCounterReset();
424
425  __ bind(&ok);
426  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
427  // Record a mapping of the OSR id to this PC.  This is used if the OSR
428  // entry becomes the target of a bailout.  We don't expect it to be, but
429  // we want it to work if it is.
430  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
431}
432
433void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
434    bool is_tail_call) {
435  // Pretend that the exit is a backwards jump to the entry.
436  int weight = 1;
437  if (info_->ShouldSelfOptimize()) {
438    weight = FLAG_interrupt_budget / FLAG_self_opt_count;
439  } else {
440    int distance = masm_->pc_offset();
441    weight = Min(kMaxBackEdgeWeight, Max(1, distance / kCodeSizeMultiplier));
442  }
443  EmitProfilingCounterDecrement(weight);
444  Label ok;
445  __ b(pl, &ok);
446  // Don't need to save result register if we are going to do a tail call.
447  if (!is_tail_call) {
448    __ push(r0);
449  }
450  __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
451  if (!is_tail_call) {
452    __ pop(r0);
453  }
454  EmitProfilingCounterReset();
455  __ bind(&ok);
456}
457
458void FullCodeGenerator::EmitReturnSequence() {
459  Comment cmnt(masm_, "[ Return sequence");
460  if (return_label_.is_bound()) {
461    __ b(&return_label_);
462  } else {
463    __ bind(&return_label_);
464    if (FLAG_trace) {
465      // Push the return value on the stack as the parameter.
466      // Runtime::TraceExit returns its parameter in r0.
467      __ push(r0);
468      __ CallRuntime(Runtime::kTraceExit);
469    }
470    EmitProfilingCounterHandlingForReturnSequence(false);
471
472    // Make sure that the constant pool is not emitted inside of the return
473    // sequence.
474    { Assembler::BlockConstPoolScope block_const_pool(masm_);
475      int32_t arg_count = info_->scope()->num_parameters() + 1;
476      int32_t sp_delta = arg_count * kPointerSize;
477      SetReturnPosition(literal());
478      // TODO(svenpanne) The code below is sometimes 4 words, sometimes 5!
479      PredictableCodeSizeScope predictable(masm_, -1);
480      __ LeaveFrame(StackFrame::JAVA_SCRIPT);
481      { ConstantPoolUnavailableScope constant_pool_unavailable(masm_);
482        __ add(sp, sp, Operand(sp_delta));
483        __ Jump(lr);
484      }
485    }
486  }
487}
488
489void FullCodeGenerator::RestoreContext() {
490  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
491}
492
493void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
494  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
495  codegen()->GetVar(result_register(), var);
496  codegen()->PushOperand(result_register());
497}
498
499
500void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
501}
502
503
504void FullCodeGenerator::AccumulatorValueContext::Plug(
505    Heap::RootListIndex index) const {
506  __ LoadRoot(result_register(), index);
507}
508
509
510void FullCodeGenerator::StackValueContext::Plug(
511    Heap::RootListIndex index) const {
512  __ LoadRoot(result_register(), index);
513  codegen()->PushOperand(result_register());
514}
515
516
517void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
518  codegen()->PrepareForBailoutBeforeSplit(condition(),
519                                          true,
520                                          true_label_,
521                                          false_label_);
522  if (index == Heap::kUndefinedValueRootIndex ||
523      index == Heap::kNullValueRootIndex ||
524      index == Heap::kFalseValueRootIndex) {
525    if (false_label_ != fall_through_) __ b(false_label_);
526  } else if (index == Heap::kTrueValueRootIndex) {
527    if (true_label_ != fall_through_) __ b(true_label_);
528  } else {
529    __ LoadRoot(result_register(), index);
530    codegen()->DoTest(this);
531  }
532}
533
534
535void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
536}
537
538
539void FullCodeGenerator::AccumulatorValueContext::Plug(
540    Handle<Object> lit) const {
541  __ mov(result_register(), Operand(lit));
542}
543
544
545void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
546  // Immediates cannot be pushed directly.
547  __ mov(result_register(), Operand(lit));
548  codegen()->PushOperand(result_register());
549}
550
551
552void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
553  codegen()->PrepareForBailoutBeforeSplit(condition(),
554                                          true,
555                                          true_label_,
556                                          false_label_);
557  DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) ||
558         !lit->IsUndetectable());
559  if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) ||
560      lit->IsFalse(isolate())) {
561    if (false_label_ != fall_through_) __ b(false_label_);
562  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
563    if (true_label_ != fall_through_) __ b(true_label_);
564  } else if (lit->IsString()) {
565    if (String::cast(*lit)->length() == 0) {
566      if (false_label_ != fall_through_) __ b(false_label_);
567    } else {
568      if (true_label_ != fall_through_) __ b(true_label_);
569    }
570  } else if (lit->IsSmi()) {
571    if (Smi::cast(*lit)->value() == 0) {
572      if (false_label_ != fall_through_) __ b(false_label_);
573    } else {
574      if (true_label_ != fall_through_) __ b(true_label_);
575    }
576  } else {
577    // For simplicity we always test the accumulator register.
578    __ mov(result_register(), Operand(lit));
579    codegen()->DoTest(this);
580  }
581}
582
583
584void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
585                                                       Register reg) const {
586  DCHECK(count > 0);
587  if (count > 1) codegen()->DropOperands(count - 1);
588  __ str(reg, MemOperand(sp, 0));
589}
590
591
592void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
593                                            Label* materialize_false) const {
594  DCHECK(materialize_true == materialize_false);
595  __ bind(materialize_true);
596}
597
598
599void FullCodeGenerator::AccumulatorValueContext::Plug(
600    Label* materialize_true,
601    Label* materialize_false) const {
602  Label done;
603  __ bind(materialize_true);
604  __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
605  __ jmp(&done);
606  __ bind(materialize_false);
607  __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
608  __ bind(&done);
609}
610
611
612void FullCodeGenerator::StackValueContext::Plug(
613    Label* materialize_true,
614    Label* materialize_false) const {
615  Label done;
616  __ bind(materialize_true);
617  __ LoadRoot(ip, Heap::kTrueValueRootIndex);
618  __ jmp(&done);
619  __ bind(materialize_false);
620  __ LoadRoot(ip, Heap::kFalseValueRootIndex);
621  __ bind(&done);
622  codegen()->PushOperand(ip);
623}
624
625
626void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
627                                          Label* materialize_false) const {
628  DCHECK(materialize_true == true_label_);
629  DCHECK(materialize_false == false_label_);
630}
631
632
633void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
634  Heap::RootListIndex value_root_index =
635      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
636  __ LoadRoot(result_register(), value_root_index);
637}
638
639
640void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
641  Heap::RootListIndex value_root_index =
642      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
643  __ LoadRoot(ip, value_root_index);
644  codegen()->PushOperand(ip);
645}
646
647
648void FullCodeGenerator::TestContext::Plug(bool flag) const {
649  codegen()->PrepareForBailoutBeforeSplit(condition(),
650                                          true,
651                                          true_label_,
652                                          false_label_);
653  if (flag) {
654    if (true_label_ != fall_through_) __ b(true_label_);
655  } else {
656    if (false_label_ != fall_through_) __ b(false_label_);
657  }
658}
659
660
661void FullCodeGenerator::DoTest(Expression* condition,
662                               Label* if_true,
663                               Label* if_false,
664                               Label* fall_through) {
665  Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
666  CallIC(ic, condition->test_id());
667  __ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
668  Split(eq, if_true, if_false, fall_through);
669}
670
671
672void FullCodeGenerator::Split(Condition cond,
673                              Label* if_true,
674                              Label* if_false,
675                              Label* fall_through) {
676  if (if_false == fall_through) {
677    __ b(cond, if_true);
678  } else if (if_true == fall_through) {
679    __ b(NegateCondition(cond), if_false);
680  } else {
681    __ b(cond, if_true);
682    __ b(if_false);
683  }
684}
685
686
687MemOperand FullCodeGenerator::StackOperand(Variable* var) {
688  DCHECK(var->IsStackAllocated());
689  // Offset is negative because higher indexes are at lower addresses.
690  int offset = -var->index() * kPointerSize;
691  // Adjust by a (parameter or local) base offset.
692  if (var->IsParameter()) {
693    offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
694  } else {
695    offset += JavaScriptFrameConstants::kLocal0Offset;
696  }
697  return MemOperand(fp, offset);
698}
699
700
701MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
702  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
703  if (var->IsContextSlot()) {
704    int context_chain_length = scope()->ContextChainLength(var->scope());
705    __ LoadContext(scratch, context_chain_length);
706    return ContextMemOperand(scratch, var->index());
707  } else {
708    return StackOperand(var);
709  }
710}
711
712
713void FullCodeGenerator::GetVar(Register dest, Variable* var) {
714  // Use destination as scratch.
715  MemOperand location = VarOperand(var, dest);
716  __ ldr(dest, location);
717}
718
719
720void FullCodeGenerator::SetVar(Variable* var,
721                               Register src,
722                               Register scratch0,
723                               Register scratch1) {
724  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
725  DCHECK(!scratch0.is(src));
726  DCHECK(!scratch0.is(scratch1));
727  DCHECK(!scratch1.is(src));
728  MemOperand location = VarOperand(var, scratch0);
729  __ str(src, location);
730
731  // Emit the write barrier code if the location is in the heap.
732  if (var->IsContextSlot()) {
733    __ RecordWriteContextSlot(scratch0,
734                              location.offset(),
735                              src,
736                              scratch1,
737                              kLRHasBeenSaved,
738                              kDontSaveFPRegs);
739  }
740}
741
742
743void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
744                                                     bool should_normalize,
745                                                     Label* if_true,
746                                                     Label* if_false) {
747  // Only prepare for bailouts before splits if we're in a test
748  // context. Otherwise, we let the Visit function deal with the
749  // preparation to avoid preparing with the same AST id twice.
750  if (!context()->IsTest()) return;
751
752  Label skip;
753  if (should_normalize) __ b(&skip);
754  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
755  if (should_normalize) {
756    __ LoadRoot(ip, Heap::kTrueValueRootIndex);
757    __ cmp(r0, ip);
758    Split(eq, if_true, if_false, NULL);
759    __ bind(&skip);
760  }
761}
762
763
764void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
765  // The variable in the declaration always resides in the current function
766  // context.
767  DCHECK_EQ(0, scope()->ContextChainLength(variable->scope()));
768  if (FLAG_debug_code) {
769    // Check that we're not inside a with or catch context.
770    __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset));
771    __ CompareRoot(r1, Heap::kWithContextMapRootIndex);
772    __ Check(ne, kDeclarationInWithContext);
773    __ CompareRoot(r1, Heap::kCatchContextMapRootIndex);
774    __ Check(ne, kDeclarationInCatchContext);
775  }
776}
777
778
779void FullCodeGenerator::VisitVariableDeclaration(
780    VariableDeclaration* declaration) {
781  VariableProxy* proxy = declaration->proxy();
782  Variable* variable = proxy->var();
783  switch (variable->location()) {
784    case VariableLocation::UNALLOCATED: {
785      DCHECK(!variable->binding_needs_init());
786      FeedbackVectorSlot slot = proxy->VariableFeedbackSlot();
787      DCHECK(!slot.IsInvalid());
788      globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
789      globals_->Add(isolate()->factory()->undefined_value(), zone());
790      break;
791    }
792    case VariableLocation::PARAMETER:
793    case VariableLocation::LOCAL:
794      if (variable->binding_needs_init()) {
795        Comment cmnt(masm_, "[ VariableDeclaration");
796        __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
797        __ str(r0, StackOperand(variable));
798      }
799      break;
800
801    case VariableLocation::CONTEXT:
802      if (variable->binding_needs_init()) {
803        Comment cmnt(masm_, "[ VariableDeclaration");
804        EmitDebugCheckDeclarationContext(variable);
805        __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
806        __ str(r0, ContextMemOperand(cp, variable->index()));
807        // No write barrier since the_hole_value is in old space.
808        PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
809      }
810      break;
811
812    case VariableLocation::LOOKUP: {
813      Comment cmnt(masm_, "[ VariableDeclaration");
814      DCHECK_EQ(VAR, variable->mode());
815      DCHECK(!variable->binding_needs_init());
816      __ mov(r2, Operand(variable->name()));
817      __ Push(r2);
818      __ CallRuntime(Runtime::kDeclareEvalVar);
819      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
820      break;
821    }
822
823    case VariableLocation::MODULE:
824      UNREACHABLE();
825  }
826}
827
828
829void FullCodeGenerator::VisitFunctionDeclaration(
830    FunctionDeclaration* declaration) {
831  VariableProxy* proxy = declaration->proxy();
832  Variable* variable = proxy->var();
833  switch (variable->location()) {
834    case VariableLocation::UNALLOCATED: {
835      FeedbackVectorSlot slot = proxy->VariableFeedbackSlot();
836      DCHECK(!slot.IsInvalid());
837      globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
838      Handle<SharedFunctionInfo> function =
839          Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
840      // Check for stack-overflow exception.
841      if (function.is_null()) return SetStackOverflow();
842      globals_->Add(function, zone());
843      break;
844    }
845
846    case VariableLocation::PARAMETER:
847    case VariableLocation::LOCAL: {
848      Comment cmnt(masm_, "[ FunctionDeclaration");
849      VisitForAccumulatorValue(declaration->fun());
850      __ str(result_register(), StackOperand(variable));
851      break;
852    }
853
854    case VariableLocation::CONTEXT: {
855      Comment cmnt(masm_, "[ FunctionDeclaration");
856      EmitDebugCheckDeclarationContext(variable);
857      VisitForAccumulatorValue(declaration->fun());
858      __ str(result_register(), ContextMemOperand(cp, variable->index()));
859      int offset = Context::SlotOffset(variable->index());
860      // We know that we have written a function, which is not a smi.
861      __ RecordWriteContextSlot(cp,
862                                offset,
863                                result_register(),
864                                r2,
865                                kLRHasBeenSaved,
866                                kDontSaveFPRegs,
867                                EMIT_REMEMBERED_SET,
868                                OMIT_SMI_CHECK);
869      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
870      break;
871    }
872
873    case VariableLocation::LOOKUP: {
874      Comment cmnt(masm_, "[ FunctionDeclaration");
875      __ mov(r2, Operand(variable->name()));
876      PushOperand(r2);
877      // Push initial value for function declaration.
878      VisitForStackValue(declaration->fun());
879      CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
880      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
881      break;
882    }
883
884    case VariableLocation::MODULE:
885      UNREACHABLE();
886  }
887}
888
889
890void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
891  // Call the runtime to declare the globals.
892  __ mov(r1, Operand(pairs));
893  __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags())));
894  __ EmitLoadTypeFeedbackVector(r2);
895  __ Push(r1, r0, r2);
896  __ CallRuntime(Runtime::kDeclareGlobals);
897  // Return value is ignored.
898}
899
900
901void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
902  Comment cmnt(masm_, "[ SwitchStatement");
903  Breakable nested_statement(this, stmt);
904  SetStatementPosition(stmt);
905
906  // Keep the switch value on the stack until a case matches.
907  VisitForStackValue(stmt->tag());
908  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
909
910  ZoneList<CaseClause*>* clauses = stmt->cases();
911  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
912
913  Label next_test;  // Recycled for each test.
914  // Compile all the tests with branches to their bodies.
915  for (int i = 0; i < clauses->length(); i++) {
916    CaseClause* clause = clauses->at(i);
917    clause->body_target()->Unuse();
918
919    // The default is not a test, but remember it as final fall through.
920    if (clause->is_default()) {
921      default_clause = clause;
922      continue;
923    }
924
925    Comment cmnt(masm_, "[ Case comparison");
926    __ bind(&next_test);
927    next_test.Unuse();
928
929    // Compile the label expression.
930    VisitForAccumulatorValue(clause->label());
931
932    // Perform the comparison as if via '==='.
933    __ ldr(r1, MemOperand(sp, 0));  // Switch value.
934    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
935    JumpPatchSite patch_site(masm_);
936    if (inline_smi_code) {
937      Label slow_case;
938      __ orr(r2, r1, r0);
939      patch_site.EmitJumpIfNotSmi(r2, &slow_case);
940
941      __ cmp(r1, r0);
942      __ b(ne, &next_test);
943      __ Drop(1);  // Switch value is no longer needed.
944      __ b(clause->body_target());
945      __ bind(&slow_case);
946    }
947
948    // Record position before stub call for type feedback.
949    SetExpressionPosition(clause);
950    Handle<Code> ic =
951        CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
952    CallIC(ic, clause->CompareId());
953    patch_site.EmitPatchInfo();
954
955    Label skip;
956    __ b(&skip);
957    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
958    __ LoadRoot(ip, Heap::kTrueValueRootIndex);
959    __ cmp(r0, ip);
960    __ b(ne, &next_test);
961    __ Drop(1);
962    __ jmp(clause->body_target());
963    __ bind(&skip);
964
965    __ cmp(r0, Operand::Zero());
966    __ b(ne, &next_test);
967    __ Drop(1);  // Switch value is no longer needed.
968    __ b(clause->body_target());
969  }
970
971  // Discard the test value and jump to the default if present, otherwise to
972  // the end of the statement.
973  __ bind(&next_test);
974  DropOperands(1);  // Switch value is no longer needed.
975  if (default_clause == NULL) {
976    __ b(nested_statement.break_label());
977  } else {
978    __ b(default_clause->body_target());
979  }
980
981  // Compile all the case bodies.
982  for (int i = 0; i < clauses->length(); i++) {
983    Comment cmnt(masm_, "[ Case body");
984    CaseClause* clause = clauses->at(i);
985    __ bind(clause->body_target());
986    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
987    VisitStatements(clause->statements());
988  }
989
990  __ bind(nested_statement.break_label());
991  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
992}
993
994
995void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
996  Comment cmnt(masm_, "[ ForInStatement");
997  SetStatementPosition(stmt, SKIP_BREAK);
998
999  FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
1000
1001  // Get the object to enumerate over.
1002  SetExpressionAsStatementPosition(stmt->enumerable());
1003  VisitForAccumulatorValue(stmt->enumerable());
1004  OperandStackDepthIncrement(5);
1005
1006  Label loop, exit;
1007  Iteration loop_statement(this, stmt);
1008  increment_loop_depth();
1009
1010  // If the object is null or undefined, skip over the loop, otherwise convert
1011  // it to a JS receiver.  See ECMA-262 version 5, section 12.6.4.
1012  Label convert, done_convert;
1013  __ JumpIfSmi(r0, &convert);
1014  __ CompareObjectType(r0, r1, r1, FIRST_JS_RECEIVER_TYPE);
1015  __ b(ge, &done_convert);
1016  __ CompareRoot(r0, Heap::kNullValueRootIndex);
1017  __ b(eq, &exit);
1018  __ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
1019  __ b(eq, &exit);
1020  __ bind(&convert);
1021  __ Call(isolate()->builtins()->ToObject(), RelocInfo::CODE_TARGET);
1022  RestoreContext();
1023  __ bind(&done_convert);
1024  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
1025  __ push(r0);
1026
1027  // Check cache validity in generated code. If we cannot guarantee cache
1028  // validity, call the runtime system to check cache validity or get the
1029  // property names in a fixed array. Note: Proxies never have an enum cache,
1030  // so will always take the slow path.
1031  Label call_runtime;
1032  __ CheckEnumCache(&call_runtime);
1033
1034  // The enum cache is valid.  Load the map of the object being
1035  // iterated over and use the cache for the iteration.
1036  Label use_cache;
1037  __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
1038  __ b(&use_cache);
1039
1040  // Get the set of properties to enumerate.
1041  __ bind(&call_runtime);
1042  __ push(r0);  // Duplicate the enumerable object on the stack.
1043  __ CallRuntime(Runtime::kForInEnumerate);
1044  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
1045
1046  // If we got a map from the runtime call, we can do a fast
1047  // modification check. Otherwise, we got a fixed array, and we have
1048  // to do a slow check.
1049  Label fixed_array;
1050  __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
1051  __ LoadRoot(ip, Heap::kMetaMapRootIndex);
1052  __ cmp(r2, ip);
1053  __ b(ne, &fixed_array);
1054
1055  // We got a map in register r0. Get the enumeration cache from it.
1056  Label no_descriptors;
1057  __ bind(&use_cache);
1058
1059  __ EnumLength(r1, r0);
1060  __ cmp(r1, Operand(Smi::kZero));
1061  __ b(eq, &no_descriptors);
1062
1063  __ LoadInstanceDescriptors(r0, r2);
1064  __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheOffset));
1065  __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheBridgeCacheOffset));
1066
1067  // Set up the four remaining stack slots.
1068  __ push(r0);  // Map.
1069  __ mov(r0, Operand(Smi::kZero));
1070  // Push enumeration cache, enumeration cache length (as smi) and zero.
1071  __ Push(r2, r1, r0);
1072  __ jmp(&loop);
1073
1074  __ bind(&no_descriptors);
1075  __ Drop(1);
1076  __ jmp(&exit);
1077
1078  // We got a fixed array in register r0. Iterate through that.
1079  __ bind(&fixed_array);
1080
1081  __ mov(r1, Operand(Smi::FromInt(1)));  // Smi(1) indicates slow check
1082  __ Push(r1, r0);  // Smi and array
1083  __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset));
1084  __ Push(r1);  // Fixed array length (as smi).
1085  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
1086  __ mov(r0, Operand(Smi::kZero));
1087  __ Push(r0);  // Initial index.
1088
1089  // Generate code for doing the condition check.
1090  __ bind(&loop);
1091  SetExpressionAsStatementPosition(stmt->each());
1092
1093  // Load the current count to r0, load the length to r1.
1094  __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
1095  __ cmp(r0, r1);  // Compare to the array length.
1096  __ b(hs, loop_statement.break_label());
1097
1098  // Get the current entry of the array into register r0.
1099  __ ldr(r2, MemOperand(sp, 2 * kPointerSize));
1100  __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1101  __ ldr(r0, MemOperand::PointerAddressFromSmiKey(r2, r0));
1102
1103  // Get the expected map from the stack or a smi in the
1104  // permanent slow case into register r2.
1105  __ ldr(r2, MemOperand(sp, 3 * kPointerSize));
1106
1107  // Check if the expected map still matches that of the enumerable.
1108  // If not, we may have to filter the key.
1109  Label update_each;
1110  __ ldr(r1, MemOperand(sp, 4 * kPointerSize));
1111  __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset));
1112  __ cmp(r4, Operand(r2));
1113  __ b(eq, &update_each);
1114
1115  // We need to filter the key, record slow-path here.
1116  int const vector_index = SmiFromSlot(slot)->value();
1117  __ EmitLoadTypeFeedbackVector(r3);
1118  __ mov(r2, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate())));
1119  __ str(r2, FieldMemOperand(r3, FixedArray::OffsetOfElementAt(vector_index)));
1120
1121  // r0 contains the key. The receiver in r1 is the second argument to the
1122  // ForInFilter. ForInFilter returns undefined if the receiver doesn't
1123  // have the key or returns the name-converted key.
1124  __ Call(isolate()->builtins()->ForInFilter(), RelocInfo::CODE_TARGET);
1125  RestoreContext();
1126  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
1127  __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex);
1128  __ b(eq, loop_statement.continue_label());
1129
1130  // Update the 'each' property or variable from the possibly filtered
1131  // entry in register r0.
1132  __ bind(&update_each);
1133
1134  // Perform the assignment as if via '='.
1135  { EffectContext context(this);
1136    EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
1137    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
1138  }
1139
1140  // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
1141  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
1142  // Generate code for the body of the loop.
1143  Visit(stmt->body());
1144
1145  // Generate code for the going to the next element by incrementing
1146  // the index (smi) stored on top of the stack.
1147  __ bind(loop_statement.continue_label());
1148  PrepareForBailoutForId(stmt->IncrementId(), BailoutState::NO_REGISTERS);
1149  __ pop(r0);
1150  __ add(r0, r0, Operand(Smi::FromInt(1)));
1151  __ push(r0);
1152
1153  EmitBackEdgeBookkeeping(stmt, &loop);
1154  __ b(&loop);
1155
1156  // Remove the pointers stored on the stack.
1157  __ bind(loop_statement.break_label());
1158  DropOperands(5);
1159
1160  // Exit and decrement the loop depth.
1161  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
1162  __ bind(&exit);
1163  decrement_loop_depth();
1164}
1165
1166
1167void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
1168                                          FeedbackVectorSlot slot) {
1169  DCHECK(NeedsHomeObject(initializer));
1170  __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
1171  __ ldr(StoreDescriptor::ValueRegister(),
1172         MemOperand(sp, offset * kPointerSize));
1173  CallStoreIC(slot, isolate()->factory()->home_object_symbol());
1174}
1175
1176
1177void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer,
1178                                                     int offset,
1179                                                     FeedbackVectorSlot slot) {
1180  DCHECK(NeedsHomeObject(initializer));
1181  __ Move(StoreDescriptor::ReceiverRegister(), r0);
1182  __ ldr(StoreDescriptor::ValueRegister(),
1183         MemOperand(sp, offset * kPointerSize));
1184  CallStoreIC(slot, isolate()->factory()->home_object_symbol());
1185}
1186
1187
1188void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
1189                                                      TypeofMode typeof_mode,
1190                                                      Label* slow) {
1191  Register current = cp;
1192  Register next = r1;
1193  Register temp = r2;
1194
1195  int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
1196  for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
1197    if (!s->NeedsContext()) continue;
1198    if (s->calls_sloppy_eval()) {
1199      // Check that extension is "the hole".
1200      __ ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
1201      __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
1202    }
1203    // Load next context in chain.
1204    __ ldr(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
1205    // Walk the rest of the chain without clobbering cp.
1206    current = next;
1207    to_check--;
1208  }
1209
1210  // All extension objects were empty and it is safe to use a normal global
1211  // load machinery.
1212  EmitGlobalVariableLoad(proxy, typeof_mode);
1213}
1214
1215
1216MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1217                                                                Label* slow) {
1218  DCHECK(var->IsContextSlot());
1219  Register context = cp;
1220  Register next = r3;
1221  Register temp = r4;
1222
1223  for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
1224    if (s->NeedsContext()) {
1225      if (s->calls_sloppy_eval()) {
1226        // Check that extension is "the hole".
1227        __ ldr(temp, ContextMemOperand(context, Context::EXTENSION_INDEX));
1228        __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
1229      }
1230      __ ldr(next, ContextMemOperand(context, Context::PREVIOUS_INDEX));
1231      // Walk the rest of the chain without clobbering cp.
1232      context = next;
1233    }
1234  }
1235  // Check that last extension is "the hole".
1236  __ ldr(temp, ContextMemOperand(context, Context::EXTENSION_INDEX));
1237  __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
1238
1239  // This function is used only for loads, not stores, so it's safe to
1240  // return an cp-based operand (the write barrier cannot be allowed to
1241  // destroy the cp register).
1242  return ContextMemOperand(context, var->index());
1243}
1244
1245
1246void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
1247                                                  TypeofMode typeof_mode,
1248                                                  Label* slow, Label* done) {
1249  // Generate fast-case code for variables that might be shadowed by
1250  // eval-introduced variables.  Eval is used a lot without
1251  // introducing variables.  In those cases, we do not want to
1252  // perform a runtime call for all variables in the scope
1253  // containing the eval.
1254  Variable* var = proxy->var();
1255  if (var->mode() == DYNAMIC_GLOBAL) {
1256    EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow);
1257    __ jmp(done);
1258  } else if (var->mode() == DYNAMIC_LOCAL) {
1259    Variable* local = var->local_if_not_shadowed();
1260    __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow));
1261    if (local->binding_needs_init()) {
1262      __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
1263      __ b(ne, done);
1264      __ mov(r0, Operand(var->name()));
1265      __ push(r0);
1266      __ CallRuntime(Runtime::kThrowReferenceError);
1267    } else {
1268      __ jmp(done);
1269    }
1270  }
1271}
1272
1273void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
1274                                         TypeofMode typeof_mode) {
1275  // Record position before possible IC call.
1276  SetExpressionPosition(proxy);
1277  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
1278  Variable* var = proxy->var();
1279
1280  // Three cases: global variables, lookup variables, and all other types of
1281  // variables.
1282  switch (var->location()) {
1283    case VariableLocation::UNALLOCATED: {
1284      Comment cmnt(masm_, "[ Global variable");
1285      EmitGlobalVariableLoad(proxy, typeof_mode);
1286      context()->Plug(r0);
1287      break;
1288    }
1289
1290    case VariableLocation::PARAMETER:
1291    case VariableLocation::LOCAL:
1292    case VariableLocation::CONTEXT: {
1293      DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode);
1294      Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
1295                                               : "[ Stack variable");
1296      if (proxy->hole_check_mode() == HoleCheckMode::kRequired) {
1297        // Throw a reference error when using an uninitialized let/const
1298        // binding in harmony mode.
1299        Label done;
1300        GetVar(r0, var);
1301        __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
1302        __ b(ne, &done);
1303        __ mov(r0, Operand(var->name()));
1304        __ push(r0);
1305        __ CallRuntime(Runtime::kThrowReferenceError);
1306        __ bind(&done);
1307        context()->Plug(r0);
1308        break;
1309      }
1310      context()->Plug(var);
1311      break;
1312    }
1313
1314    case VariableLocation::LOOKUP: {
1315      Comment cmnt(masm_, "[ Lookup variable");
1316      Label done, slow;
1317      // Generate code for loading from variables potentially shadowed
1318      // by eval-introduced variables.
1319      EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done);
1320      __ bind(&slow);
1321      __ Push(var->name());
1322      Runtime::FunctionId function_id =
1323          typeof_mode == NOT_INSIDE_TYPEOF
1324              ? Runtime::kLoadLookupSlot
1325              : Runtime::kLoadLookupSlotInsideTypeof;
1326      __ CallRuntime(function_id);
1327      __ bind(&done);
1328      context()->Plug(r0);
1329      break;
1330    }
1331
1332    case VariableLocation::MODULE:
1333      UNREACHABLE();
1334  }
1335}
1336
1337
1338void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
1339  Expression* expression = (property == NULL) ? NULL : property->value();
1340  if (expression == NULL) {
1341    __ LoadRoot(r1, Heap::kNullValueRootIndex);
1342    PushOperand(r1);
1343  } else {
1344    VisitForStackValue(expression);
1345    if (NeedsHomeObject(expression)) {
1346      DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
1347             property->kind() == ObjectLiteral::Property::SETTER);
1348      int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
1349      EmitSetHomeObject(expression, offset, property->GetSlot());
1350    }
1351  }
1352}
1353
1354
1355void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1356  Comment cmnt(masm_, "[ ObjectLiteral");
1357
1358  Handle<FixedArray> constant_properties = expr->constant_properties();
1359  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1360  __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
1361  __ mov(r1, Operand(constant_properties));
1362  int flags = expr->ComputeFlags();
1363  __ mov(r0, Operand(Smi::FromInt(flags)));
1364  if (MustCreateObjectLiteralWithRuntime(expr)) {
1365    __ Push(r3, r2, r1, r0);
1366    __ CallRuntime(Runtime::kCreateObjectLiteral);
1367  } else {
1368    FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
1369    __ CallStub(&stub);
1370    RestoreContext();
1371  }
1372  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
1373
1374  // If result_saved is true the result is on top of the stack.  If
1375  // result_saved is false the result is in r0.
1376  bool result_saved = false;
1377
1378  AccessorTable accessor_table(zone());
1379  int property_index = 0;
1380  for (; property_index < expr->properties()->length(); property_index++) {
1381    ObjectLiteral::Property* property = expr->properties()->at(property_index);
1382    if (property->is_computed_name()) break;
1383    if (property->IsCompileTimeValue()) continue;
1384
1385    Literal* key = property->key()->AsLiteral();
1386    Expression* value = property->value();
1387    if (!result_saved) {
1388      PushOperand(r0);  // Save result on stack
1389      result_saved = true;
1390    }
1391    switch (property->kind()) {
1392      case ObjectLiteral::Property::CONSTANT:
1393        UNREACHABLE();
1394      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1395        DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1396        // Fall through.
1397      case ObjectLiteral::Property::COMPUTED:
1398        // It is safe to use [[Put]] here because the boilerplate already
1399        // contains computed properties with an uninitialized value.
1400        if (key->IsStringLiteral()) {
1401          DCHECK(key->IsPropertyName());
1402          if (property->emit_store()) {
1403            VisitForAccumulatorValue(value);
1404            DCHECK(StoreDescriptor::ValueRegister().is(r0));
1405            __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
1406            CallStoreIC(property->GetSlot(0), key->value());
1407            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
1408
1409            if (NeedsHomeObject(value)) {
1410              EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
1411            }
1412          } else {
1413            VisitForEffect(value);
1414          }
1415          break;
1416        }
1417        // Duplicate receiver on stack.
1418        __ ldr(r0, MemOperand(sp));
1419        PushOperand(r0);
1420        VisitForStackValue(key);
1421        VisitForStackValue(value);
1422        if (property->emit_store()) {
1423          if (NeedsHomeObject(value)) {
1424            EmitSetHomeObject(value, 2, property->GetSlot());
1425          }
1426          __ mov(r0, Operand(Smi::FromInt(SLOPPY)));  // PropertyAttributes
1427          PushOperand(r0);
1428          CallRuntimeWithOperands(Runtime::kSetProperty);
1429        } else {
1430          DropOperands(3);
1431        }
1432        break;
1433      case ObjectLiteral::Property::PROTOTYPE:
1434        // Duplicate receiver on stack.
1435        __ ldr(r0, MemOperand(sp));
1436        PushOperand(r0);
1437        VisitForStackValue(value);
1438        DCHECK(property->emit_store());
1439        CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
1440        PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
1441                               BailoutState::NO_REGISTERS);
1442        break;
1443
1444      case ObjectLiteral::Property::GETTER:
1445        if (property->emit_store()) {
1446          AccessorTable::Iterator it = accessor_table.lookup(key);
1447          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
1448          it->second->getter = property;
1449        }
1450        break;
1451      case ObjectLiteral::Property::SETTER:
1452        if (property->emit_store()) {
1453          AccessorTable::Iterator it = accessor_table.lookup(key);
1454          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
1455          it->second->setter = property;
1456        }
1457        break;
1458    }
1459  }
1460
1461  // Emit code to define accessors, using only a single call to the runtime for
1462  // each pair of corresponding getters and setters.
1463  for (AccessorTable::Iterator it = accessor_table.begin();
1464       it != accessor_table.end();
1465       ++it) {
1466    __ ldr(r0, MemOperand(sp));  // Duplicate receiver.
1467    PushOperand(r0);
1468    VisitForStackValue(it->first);
1469    EmitAccessor(it->second->getter);
1470    EmitAccessor(it->second->setter);
1471    __ mov(r0, Operand(Smi::FromInt(NONE)));
1472    PushOperand(r0);
1473    CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
1474    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
1475  }
1476
1477  // Object literals have two parts. The "static" part on the left contains no
1478  // computed property names, and so we can compute its map ahead of time; see
1479  // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part
1480  // starts with the first computed property name, and continues with all
1481  // properties to its right.  All the code from above initializes the static
1482  // component of the object literal, and arranges for the map of the result to
1483  // reflect the static order in which the keys appear. For the dynamic
1484  // properties, we compile them into a series of "SetOwnProperty" runtime
1485  // calls. This will preserve insertion order.
1486  for (; property_index < expr->properties()->length(); property_index++) {
1487    ObjectLiteral::Property* property = expr->properties()->at(property_index);
1488
1489    Expression* value = property->value();
1490    if (!result_saved) {
1491      PushOperand(r0);  // Save result on the stack
1492      result_saved = true;
1493    }
1494
1495    __ ldr(r0, MemOperand(sp));  // Duplicate receiver.
1496    PushOperand(r0);
1497
1498    if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1499      DCHECK(!property->is_computed_name());
1500      VisitForStackValue(value);
1501      DCHECK(property->emit_store());
1502      CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
1503      PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
1504                             BailoutState::NO_REGISTERS);
1505    } else {
1506      EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
1507      VisitForStackValue(value);
1508      if (NeedsHomeObject(value)) {
1509        EmitSetHomeObject(value, 2, property->GetSlot());
1510      }
1511
1512      switch (property->kind()) {
1513        case ObjectLiteral::Property::CONSTANT:
1514        case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1515        case ObjectLiteral::Property::COMPUTED:
1516          if (property->emit_store()) {
1517            PushOperand(Smi::FromInt(NONE));
1518            PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
1519            CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
1520            PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
1521                                   BailoutState::NO_REGISTERS);
1522          } else {
1523            DropOperands(3);
1524          }
1525          break;
1526
1527        case ObjectLiteral::Property::PROTOTYPE:
1528          UNREACHABLE();
1529          break;
1530
1531        case ObjectLiteral::Property::GETTER:
1532          PushOperand(Smi::FromInt(NONE));
1533          CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked);
1534          break;
1535
1536        case ObjectLiteral::Property::SETTER:
1537          PushOperand(Smi::FromInt(NONE));
1538          CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked);
1539          break;
1540      }
1541    }
1542  }
1543
1544  if (result_saved) {
1545    context()->PlugTOS();
1546  } else {
1547    context()->Plug(r0);
1548  }
1549}
1550
1551
1552void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1553  Comment cmnt(masm_, "[ ArrayLiteral");
1554
1555  Handle<FixedArray> constant_elements = expr->constant_elements();
1556  bool has_fast_elements =
1557      IsFastObjectElementsKind(expr->constant_elements_kind());
1558  Handle<FixedArrayBase> constant_elements_values(
1559      FixedArrayBase::cast(constant_elements->get(1)));
1560
1561  AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1562  if (has_fast_elements && !FLAG_allocation_site_pretenuring) {
1563    // If the only customer of allocation sites is transitioning, then
1564    // we can turn it off if we don't have anywhere else to transition to.
1565    allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1566  }
1567
1568  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1569  __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
1570  __ mov(r1, Operand(constant_elements));
1571  if (MustCreateArrayLiteralWithRuntime(expr)) {
1572    __ mov(r0, Operand(Smi::FromInt(expr->ComputeFlags())));
1573    __ Push(r3, r2, r1, r0);
1574    __ CallRuntime(Runtime::kCreateArrayLiteral);
1575  } else {
1576    FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
1577    __ CallStub(&stub);
1578    RestoreContext();
1579  }
1580  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
1581
1582  bool result_saved = false;  // Is the result saved to the stack?
1583  ZoneList<Expression*>* subexprs = expr->values();
1584  int length = subexprs->length();
1585
1586  // Emit code to evaluate all the non-constant subexpressions and to store
1587  // them into the newly cloned array.
1588  for (int array_index = 0; array_index < length; array_index++) {
1589    Expression* subexpr = subexprs->at(array_index);
1590    DCHECK(!subexpr->IsSpread());
1591
1592    // If the subexpression is a literal or a simple materialized literal it
1593    // is already set in the cloned array.
1594    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1595
1596    if (!result_saved) {
1597      PushOperand(r0);
1598      result_saved = true;
1599    }
1600    VisitForAccumulatorValue(subexpr);
1601
1602    __ mov(StoreDescriptor::NameRegister(), Operand(Smi::FromInt(array_index)));
1603    __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp, 0));
1604    CallKeyedStoreIC(expr->LiteralFeedbackSlot());
1605
1606    PrepareForBailoutForId(expr->GetIdForElement(array_index),
1607                           BailoutState::NO_REGISTERS);
1608  }
1609
1610  if (result_saved) {
1611    context()->PlugTOS();
1612  } else {
1613    context()->Plug(r0);
1614  }
1615}
1616
1617
1618void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1619  DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
1620
1621  Comment cmnt(masm_, "[ Assignment");
1622
1623  Property* property = expr->target()->AsProperty();
1624  LhsKind assign_type = Property::GetAssignType(property);
1625
1626  // Evaluate LHS expression.
1627  switch (assign_type) {
1628    case VARIABLE:
1629      // Nothing to do here.
1630      break;
1631    case NAMED_PROPERTY:
1632      if (expr->is_compound()) {
1633        // We need the receiver both on the stack and in the register.
1634        VisitForStackValue(property->obj());
1635        __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
1636      } else {
1637        VisitForStackValue(property->obj());
1638      }
1639      break;
1640    case NAMED_SUPER_PROPERTY:
1641      VisitForStackValue(
1642          property->obj()->AsSuperPropertyReference()->this_var());
1643      VisitForAccumulatorValue(
1644          property->obj()->AsSuperPropertyReference()->home_object());
1645      PushOperand(result_register());
1646      if (expr->is_compound()) {
1647        const Register scratch = r1;
1648        __ ldr(scratch, MemOperand(sp, kPointerSize));
1649        PushOperand(scratch);
1650        PushOperand(result_register());
1651      }
1652      break;
1653    case KEYED_SUPER_PROPERTY:
1654      VisitForStackValue(
1655          property->obj()->AsSuperPropertyReference()->this_var());
1656      VisitForStackValue(
1657          property->obj()->AsSuperPropertyReference()->home_object());
1658      VisitForAccumulatorValue(property->key());
1659      PushOperand(result_register());
1660      if (expr->is_compound()) {
1661        const Register scratch = r1;
1662        __ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
1663        PushOperand(scratch);
1664        __ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
1665        PushOperand(scratch);
1666        PushOperand(result_register());
1667      }
1668      break;
1669    case KEYED_PROPERTY:
1670      if (expr->is_compound()) {
1671        VisitForStackValue(property->obj());
1672        VisitForStackValue(property->key());
1673        __ ldr(LoadDescriptor::ReceiverRegister(),
1674               MemOperand(sp, 1 * kPointerSize));
1675        __ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0));
1676      } else {
1677        VisitForStackValue(property->obj());
1678        VisitForStackValue(property->key());
1679      }
1680      break;
1681  }
1682
1683  // For compound assignments we need another deoptimization point after the
1684  // variable/property load.
1685  if (expr->is_compound()) {
1686    { AccumulatorValueContext context(this);
1687      switch (assign_type) {
1688        case VARIABLE:
1689          EmitVariableLoad(expr->target()->AsVariableProxy());
1690          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
1691          break;
1692        case NAMED_PROPERTY:
1693          EmitNamedPropertyLoad(property);
1694          PrepareForBailoutForId(property->LoadId(),
1695                                 BailoutState::TOS_REGISTER);
1696          break;
1697        case NAMED_SUPER_PROPERTY:
1698          EmitNamedSuperPropertyLoad(property);
1699          PrepareForBailoutForId(property->LoadId(),
1700                                 BailoutState::TOS_REGISTER);
1701          break;
1702        case KEYED_SUPER_PROPERTY:
1703          EmitKeyedSuperPropertyLoad(property);
1704          PrepareForBailoutForId(property->LoadId(),
1705                                 BailoutState::TOS_REGISTER);
1706          break;
1707        case KEYED_PROPERTY:
1708          EmitKeyedPropertyLoad(property);
1709          PrepareForBailoutForId(property->LoadId(),
1710                                 BailoutState::TOS_REGISTER);
1711          break;
1712      }
1713    }
1714
1715    Token::Value op = expr->binary_op();
1716    PushOperand(r0);  // Left operand goes on the stack.
1717    VisitForAccumulatorValue(expr->value());
1718
1719    AccumulatorValueContext context(this);
1720    if (ShouldInlineSmiCase(op)) {
1721      EmitInlineSmiBinaryOp(expr->binary_operation(),
1722                            op,
1723                            expr->target(),
1724                            expr->value());
1725    } else {
1726      EmitBinaryOp(expr->binary_operation(), op);
1727    }
1728
1729    // Deoptimization point in case the binary operation may have side effects.
1730    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
1731  } else {
1732    VisitForAccumulatorValue(expr->value());
1733  }
1734
1735  SetExpressionPosition(expr);
1736
1737  // Store the value.
1738  switch (assign_type) {
1739    case VARIABLE: {
1740      VariableProxy* proxy = expr->target()->AsVariableProxy();
1741      EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(),
1742                             proxy->hole_check_mode());
1743      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
1744      context()->Plug(r0);
1745      break;
1746    }
1747    case NAMED_PROPERTY:
1748      EmitNamedPropertyAssignment(expr);
1749      break;
1750    case NAMED_SUPER_PROPERTY:
1751      EmitNamedSuperPropertyStore(property);
1752      context()->Plug(r0);
1753      break;
1754    case KEYED_SUPER_PROPERTY:
1755      EmitKeyedSuperPropertyStore(property);
1756      context()->Plug(r0);
1757      break;
1758    case KEYED_PROPERTY:
1759      EmitKeyedPropertyAssignment(expr);
1760      break;
1761  }
1762}
1763
1764
1765void FullCodeGenerator::VisitYield(Yield* expr) {
1766  Comment cmnt(masm_, "[ Yield");
1767  SetExpressionPosition(expr);
1768
1769  // Evaluate yielded value first; the initial iterator definition depends on
1770  // this.  It stays on the stack while we update the iterator.
1771  VisitForStackValue(expr->expression());
1772
1773  Label suspend, continuation, post_runtime, resume, exception;
1774
1775  __ jmp(&suspend);
1776  __ bind(&continuation);
1777  // When we arrive here, r0 holds the generator object.
1778  __ RecordGeneratorContinuation();
1779  __ ldr(r1, FieldMemOperand(r0, JSGeneratorObject::kResumeModeOffset));
1780  __ ldr(r0, FieldMemOperand(r0, JSGeneratorObject::kInputOrDebugPosOffset));
1781  STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
1782  STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
1783  __ cmp(r1, Operand(Smi::FromInt(JSGeneratorObject::kReturn)));
1784  __ b(lt, &resume);
1785  __ Push(result_register());
1786  __ b(gt, &exception);
1787  EmitCreateIteratorResult(true);
1788  EmitUnwindAndReturn();
1789
1790  __ bind(&exception);
1791  __ CallRuntime(expr->rethrow_on_exception() ? Runtime::kReThrow
1792                                              : Runtime::kThrow);
1793
1794  __ bind(&suspend);
1795  OperandStackDepthIncrement(1);  // Not popped on this path.
1796  VisitForAccumulatorValue(expr->generator_object());
1797  DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
1798  __ mov(r1, Operand(Smi::FromInt(continuation.pos())));
1799  __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset));
1800  __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset));
1801  __ mov(r1, cp);
1802  __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2,
1803                      kLRHasBeenSaved, kDontSaveFPRegs);
1804  __ add(r1, fp, Operand(StandardFrameConstants::kExpressionsOffset));
1805  __ cmp(sp, r1);
1806  __ b(eq, &post_runtime);
1807  __ push(r0);  // generator object
1808  __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
1809  RestoreContext();
1810  __ bind(&post_runtime);
1811  PopOperand(result_register());
1812  EmitReturnSequence();
1813
1814  __ bind(&resume);
1815  context()->Plug(result_register());
1816}
1817
1818void FullCodeGenerator::PushOperands(Register reg1, Register reg2) {
1819  OperandStackDepthIncrement(2);
1820  __ Push(reg1, reg2);
1821}
1822
1823void FullCodeGenerator::PopOperands(Register reg1, Register reg2) {
1824  OperandStackDepthDecrement(2);
1825  __ Pop(reg1, reg2);
1826}
1827
1828void FullCodeGenerator::EmitOperandStackDepthCheck() {
1829  if (FLAG_debug_code) {
1830    int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp +
1831                        operand_stack_depth_ * kPointerSize;
1832    __ sub(r0, fp, sp);
1833    __ cmp(r0, Operand(expected_diff));
1834    __ Assert(eq, kUnexpectedStackDepth);
1835  }
1836}
1837
1838void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
1839  Label allocate, done_allocate;
1840
1841  __ Allocate(JSIteratorResult::kSize, r0, r2, r3, &allocate,
1842              NO_ALLOCATION_FLAGS);
1843  __ b(&done_allocate);
1844
1845  __ bind(&allocate);
1846  __ Push(Smi::FromInt(JSIteratorResult::kSize));
1847  __ CallRuntime(Runtime::kAllocateInNewSpace);
1848
1849  __ bind(&done_allocate);
1850  __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, r1);
1851  PopOperand(r2);
1852  __ LoadRoot(r3,
1853              done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex);
1854  __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex);
1855  __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
1856  __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset));
1857  __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
1858  __ str(r2, FieldMemOperand(r0, JSIteratorResult::kValueOffset));
1859  __ str(r3, FieldMemOperand(r0, JSIteratorResult::kDoneOffset));
1860}
1861
1862
1863void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
1864                                              Token::Value op,
1865                                              Expression* left_expr,
1866                                              Expression* right_expr) {
1867  Label done, smi_case, stub_call;
1868
1869  Register scratch1 = r2;
1870  Register scratch2 = r3;
1871
1872  // Get the arguments.
1873  Register left = r1;
1874  Register right = r0;
1875  PopOperand(left);
1876
1877  // Perform combined smi check on both operands.
1878  __ orr(scratch1, left, Operand(right));
1879  STATIC_ASSERT(kSmiTag == 0);
1880  JumpPatchSite patch_site(masm_);
1881  patch_site.EmitJumpIfSmi(scratch1, &smi_case);
1882
1883  __ bind(&stub_call);
1884  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
1885  CallIC(code, expr->BinaryOperationFeedbackId());
1886  patch_site.EmitPatchInfo();
1887  __ jmp(&done);
1888
1889  __ bind(&smi_case);
1890  // Smi case. This code works the same way as the smi-smi case in the type
1891  // recording binary operation stub, see
1892  switch (op) {
1893    case Token::SAR:
1894      __ GetLeastBitsFromSmi(scratch1, right, 5);
1895      __ mov(right, Operand(left, ASR, scratch1));
1896      __ bic(right, right, Operand(kSmiTagMask));
1897      break;
1898    case Token::SHL: {
1899      __ SmiUntag(scratch1, left);
1900      __ GetLeastBitsFromSmi(scratch2, right, 5);
1901      __ mov(scratch1, Operand(scratch1, LSL, scratch2));
1902      __ TrySmiTag(right, scratch1, &stub_call);
1903      break;
1904    }
1905    case Token::SHR: {
1906      __ SmiUntag(scratch1, left);
1907      __ GetLeastBitsFromSmi(scratch2, right, 5);
1908      __ mov(scratch1, Operand(scratch1, LSR, scratch2));
1909      __ tst(scratch1, Operand(0xc0000000));
1910      __ b(ne, &stub_call);
1911      __ SmiTag(right, scratch1);
1912      break;
1913    }
1914    case Token::ADD:
1915      __ add(scratch1, left, Operand(right), SetCC);
1916      __ b(vs, &stub_call);
1917      __ mov(right, scratch1);
1918      break;
1919    case Token::SUB:
1920      __ sub(scratch1, left, Operand(right), SetCC);
1921      __ b(vs, &stub_call);
1922      __ mov(right, scratch1);
1923      break;
1924    case Token::MUL: {
1925      __ SmiUntag(ip, right);
1926      __ smull(scratch1, scratch2, left, ip);
1927      __ mov(ip, Operand(scratch1, ASR, 31));
1928      __ cmp(ip, Operand(scratch2));
1929      __ b(ne, &stub_call);
1930      __ cmp(scratch1, Operand::Zero());
1931      __ mov(right, Operand(scratch1), LeaveCC, ne);
1932      __ b(ne, &done);
1933      __ add(scratch2, right, Operand(left), SetCC);
1934      __ mov(right, Operand(Smi::kZero), LeaveCC, pl);
1935      __ b(mi, &stub_call);
1936      break;
1937    }
1938    case Token::BIT_OR:
1939      __ orr(right, left, Operand(right));
1940      break;
1941    case Token::BIT_AND:
1942      __ and_(right, left, Operand(right));
1943      break;
1944    case Token::BIT_XOR:
1945      __ eor(right, left, Operand(right));
1946      break;
1947    default:
1948      UNREACHABLE();
1949  }
1950
1951  __ bind(&done);
1952  context()->Plug(r0);
1953}
1954
1955
1956void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
1957  for (int i = 0; i < lit->properties()->length(); i++) {
1958    ClassLiteral::Property* property = lit->properties()->at(i);
1959    Expression* value = property->value();
1960
1961    Register scratch = r1;
1962    if (property->is_static()) {
1963      __ ldr(scratch, MemOperand(sp, kPointerSize));  // constructor
1964    } else {
1965      __ ldr(scratch, MemOperand(sp, 0));  // prototype
1966    }
1967    PushOperand(scratch);
1968    EmitPropertyKey(property, lit->GetIdForProperty(i));
1969
1970    // The static prototype property is read only. We handle the non computed
1971    // property name case in the parser. Since this is the only case where we
1972    // need to check for an own read only property we special case this so we do
1973    // not need to do this for every property.
1974    if (property->is_static() && property->is_computed_name()) {
1975      __ CallRuntime(Runtime::kThrowIfStaticPrototype);
1976      __ push(r0);
1977    }
1978
1979    VisitForStackValue(value);
1980    if (NeedsHomeObject(value)) {
1981      EmitSetHomeObject(value, 2, property->GetSlot());
1982    }
1983
1984    switch (property->kind()) {
1985      case ClassLiteral::Property::METHOD:
1986        PushOperand(Smi::FromInt(DONT_ENUM));
1987        PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
1988        CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
1989        break;
1990
1991      case ClassLiteral::Property::GETTER:
1992        PushOperand(Smi::FromInt(DONT_ENUM));
1993        CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked);
1994        break;
1995
1996      case ClassLiteral::Property::SETTER:
1997        PushOperand(Smi::FromInt(DONT_ENUM));
1998        CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked);
1999        break;
2000
2001      case ClassLiteral::Property::FIELD:
2002      default:
2003        UNREACHABLE();
2004    }
2005  }
2006}
2007
2008
2009void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
2010  PopOperand(r1);
2011  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
2012  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
2013  CallIC(code, expr->BinaryOperationFeedbackId());
2014  patch_site.EmitPatchInfo();
2015  context()->Plug(r0);
2016}
2017
2018
2019void FullCodeGenerator::EmitAssignment(Expression* expr,
2020                                       FeedbackVectorSlot slot) {
2021  DCHECK(expr->IsValidReferenceExpressionOrThis());
2022
2023  Property* prop = expr->AsProperty();
2024  LhsKind assign_type = Property::GetAssignType(prop);
2025
2026  switch (assign_type) {
2027    case VARIABLE: {
2028      VariableProxy* proxy = expr->AsVariableProxy();
2029      EffectContext context(this);
2030      EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot,
2031                             proxy->hole_check_mode());
2032      break;
2033    }
2034    case NAMED_PROPERTY: {
2035      PushOperand(r0);  // Preserve value.
2036      VisitForAccumulatorValue(prop->obj());
2037      __ Move(StoreDescriptor::ReceiverRegister(), r0);
2038      PopOperand(StoreDescriptor::ValueRegister());  // Restore value.
2039      CallStoreIC(slot, prop->key()->AsLiteral()->value());
2040      break;
2041    }
2042    case NAMED_SUPER_PROPERTY: {
2043      PushOperand(r0);
2044      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
2045      VisitForAccumulatorValue(
2046          prop->obj()->AsSuperPropertyReference()->home_object());
2047      // stack: value, this; r0: home_object
2048      Register scratch = r2;
2049      Register scratch2 = r3;
2050      __ mov(scratch, result_register());              // home_object
2051      __ ldr(r0, MemOperand(sp, kPointerSize));        // value
2052      __ ldr(scratch2, MemOperand(sp, 0));             // this
2053      __ str(scratch2, MemOperand(sp, kPointerSize));  // this
2054      __ str(scratch, MemOperand(sp, 0));              // home_object
2055      // stack: this, home_object; r0: value
2056      EmitNamedSuperPropertyStore(prop);
2057      break;
2058    }
2059    case KEYED_SUPER_PROPERTY: {
2060      PushOperand(r0);
2061      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
2062      VisitForStackValue(
2063          prop->obj()->AsSuperPropertyReference()->home_object());
2064      VisitForAccumulatorValue(prop->key());
2065      Register scratch = r2;
2066      Register scratch2 = r3;
2067      __ ldr(scratch2, MemOperand(sp, 2 * kPointerSize));  // value
2068      // stack: value, this, home_object; r0: key, r3: value
2069      __ ldr(scratch, MemOperand(sp, kPointerSize));  // this
2070      __ str(scratch, MemOperand(sp, 2 * kPointerSize));
2071      __ ldr(scratch, MemOperand(sp, 0));  // home_object
2072      __ str(scratch, MemOperand(sp, kPointerSize));
2073      __ str(r0, MemOperand(sp, 0));
2074      __ Move(r0, scratch2);
2075      // stack: this, home_object, key; r0: value.
2076      EmitKeyedSuperPropertyStore(prop);
2077      break;
2078    }
2079    case KEYED_PROPERTY: {
2080      PushOperand(r0);  // Preserve value.
2081      VisitForStackValue(prop->obj());
2082      VisitForAccumulatorValue(prop->key());
2083      __ Move(StoreDescriptor::NameRegister(), r0);
2084      PopOperands(StoreDescriptor::ValueRegister(),
2085                  StoreDescriptor::ReceiverRegister());
2086      CallKeyedStoreIC(slot);
2087      break;
2088    }
2089  }
2090  context()->Plug(r0);
2091}
2092
2093
2094void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2095    Variable* var, MemOperand location) {
2096  __ str(result_register(), location);
2097  if (var->IsContextSlot()) {
2098    // RecordWrite may destroy all its register arguments.
2099    __ mov(r3, result_register());
2100    int offset = Context::SlotOffset(var->index());
2101    __ RecordWriteContextSlot(
2102        r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs);
2103  }
2104}
2105
2106void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
2107                                               FeedbackVectorSlot slot,
2108                                               HoleCheckMode hole_check_mode) {
2109  if (var->IsUnallocated()) {
2110    // Global var, const, or let.
2111    __ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
2112    CallStoreIC(slot, var->name());
2113
2114  } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
2115    DCHECK(!var->IsLookupSlot());
2116    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2117    MemOperand location = VarOperand(var, r1);
2118    // Perform an initialization check for lexically declared variables.
2119    if (hole_check_mode == HoleCheckMode::kRequired) {
2120      Label assign;
2121      __ ldr(r3, location);
2122      __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
2123      __ b(ne, &assign);
2124      __ mov(r3, Operand(var->name()));
2125      __ push(r3);
2126      __ CallRuntime(Runtime::kThrowReferenceError);
2127      __ bind(&assign);
2128    }
2129    if (var->mode() != CONST) {
2130      EmitStoreToStackLocalOrContextSlot(var, location);
2131    } else if (var->throw_on_const_assignment(language_mode())) {
2132      __ CallRuntime(Runtime::kThrowConstAssignError);
2133    }
2134  } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) {
2135    // Initializing assignment to const {this} needs a write barrier.
2136    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2137    Label uninitialized_this;
2138    MemOperand location = VarOperand(var, r1);
2139    __ ldr(r3, location);
2140    __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
2141    __ b(eq, &uninitialized_this);
2142    __ mov(r0, Operand(var->name()));
2143    __ Push(r0);
2144    __ CallRuntime(Runtime::kThrowReferenceError);
2145    __ bind(&uninitialized_this);
2146    EmitStoreToStackLocalOrContextSlot(var, location);
2147
2148  } else {
2149    DCHECK(var->mode() != CONST || op == Token::INIT);
2150    if (var->IsLookupSlot()) {
2151      // Assignment to var.
2152      __ Push(var->name());
2153      __ Push(r0);
2154      __ CallRuntime(is_strict(language_mode())
2155                         ? Runtime::kStoreLookupSlot_Strict
2156                         : Runtime::kStoreLookupSlot_Sloppy);
2157    } else {
2158      // Assignment to var or initializing assignment to let/const in harmony
2159      // mode.
2160      DCHECK((var->IsStackAllocated() || var->IsContextSlot()));
2161      MemOperand location = VarOperand(var, r1);
2162      if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) {
2163        // Check for an uninitialized let binding.
2164        __ ldr(r2, location);
2165        __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
2166        __ Check(eq, kLetBindingReInitialization);
2167      }
2168      EmitStoreToStackLocalOrContextSlot(var, location);
2169    }
2170  }
2171}
2172
2173
2174void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2175  // Assignment to a property, using a named store IC.
2176  Property* prop = expr->target()->AsProperty();
2177  DCHECK(prop != NULL);
2178  DCHECK(prop->key()->IsLiteral());
2179
2180  PopOperand(StoreDescriptor::ReceiverRegister());
2181  CallStoreIC(expr->AssignmentSlot(), prop->key()->AsLiteral()->value());
2182
2183  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2184  context()->Plug(r0);
2185}
2186
2187
2188void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
2189  // Assignment to named property of super.
2190  // r0 : value
2191  // stack : receiver ('this'), home_object
2192  DCHECK(prop != NULL);
2193  Literal* key = prop->key()->AsLiteral();
2194  DCHECK(key != NULL);
2195
2196  PushOperand(key->value());
2197  PushOperand(r0);
2198  CallRuntimeWithOperands(is_strict(language_mode())
2199                              ? Runtime::kStoreToSuper_Strict
2200                              : Runtime::kStoreToSuper_Sloppy);
2201}
2202
2203
2204void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
2205  // Assignment to named property of super.
2206  // r0 : value
2207  // stack : receiver ('this'), home_object, key
2208  DCHECK(prop != NULL);
2209
2210  PushOperand(r0);
2211  CallRuntimeWithOperands(is_strict(language_mode())
2212                              ? Runtime::kStoreKeyedToSuper_Strict
2213                              : Runtime::kStoreKeyedToSuper_Sloppy);
2214}
2215
2216
2217void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2218  // Assignment to a property, using a keyed store IC.
2219  PopOperands(StoreDescriptor::ReceiverRegister(),
2220              StoreDescriptor::NameRegister());
2221  DCHECK(StoreDescriptor::ValueRegister().is(r0));
2222
2223  CallKeyedStoreIC(expr->AssignmentSlot());
2224
2225  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2226  context()->Plug(r0);
2227}
2228
2229// Code common for calls using the IC.
2230void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
2231  Expression* callee = expr->expression();
2232
2233  // Get the target function.
2234  ConvertReceiverMode convert_mode;
2235  if (callee->IsVariableProxy()) {
2236    { StackValueContext context(this);
2237      EmitVariableLoad(callee->AsVariableProxy());
2238      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
2239    }
2240    // Push undefined as receiver. This is patched in the method prologue if it
2241    // is a sloppy mode method.
2242    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
2243    PushOperand(ip);
2244    convert_mode = ConvertReceiverMode::kNullOrUndefined;
2245  } else {
2246    // Load the function from the receiver.
2247    DCHECK(callee->IsProperty());
2248    DCHECK(!callee->AsProperty()->IsSuperAccess());
2249    __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
2250    EmitNamedPropertyLoad(callee->AsProperty());
2251    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
2252                           BailoutState::TOS_REGISTER);
2253    // Push the target function under the receiver.
2254    __ ldr(ip, MemOperand(sp, 0));
2255    PushOperand(ip);
2256    __ str(r0, MemOperand(sp, kPointerSize));
2257    convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
2258  }
2259
2260  EmitCall(expr, convert_mode);
2261}
2262
2263
2264void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
2265  Expression* callee = expr->expression();
2266  DCHECK(callee->IsProperty());
2267  Property* prop = callee->AsProperty();
2268  DCHECK(prop->IsSuperAccess());
2269  SetExpressionPosition(prop);
2270
2271  Literal* key = prop->key()->AsLiteral();
2272  DCHECK(!key->value()->IsSmi());
2273  // Load the function from the receiver.
2274  const Register scratch = r1;
2275  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
2276  VisitForStackValue(super_ref->home_object());
2277  VisitForAccumulatorValue(super_ref->this_var());
2278  PushOperand(r0);
2279  PushOperand(r0);
2280  __ ldr(scratch, MemOperand(sp, kPointerSize * 2));
2281  PushOperand(scratch);
2282  PushOperand(key->value());
2283
2284  // Stack here:
2285  //  - home_object
2286  //  - this (receiver)
2287  //  - this (receiver) <-- LoadFromSuper will pop here and below.
2288  //  - home_object
2289  //  - key
2290  CallRuntimeWithOperands(Runtime::kLoadFromSuper);
2291  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
2292
2293  // Replace home_object with target function.
2294  __ str(r0, MemOperand(sp, kPointerSize));
2295
2296  // Stack here:
2297  // - target function
2298  // - this (receiver)
2299  EmitCall(expr);
2300}
2301
2302
2303// Code common for calls using the IC.
2304void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2305                                                Expression* key) {
2306  // Load the key.
2307  VisitForAccumulatorValue(key);
2308
2309  Expression* callee = expr->expression();
2310
2311  // Load the function from the receiver.
2312  DCHECK(callee->IsProperty());
2313  __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
2314  __ Move(LoadDescriptor::NameRegister(), r0);
2315  EmitKeyedPropertyLoad(callee->AsProperty());
2316  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
2317                         BailoutState::TOS_REGISTER);
2318
2319  // Push the target function under the receiver.
2320  __ ldr(ip, MemOperand(sp, 0));
2321  PushOperand(ip);
2322  __ str(r0, MemOperand(sp, kPointerSize));
2323
2324  EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined);
2325}
2326
2327
2328void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
2329  Expression* callee = expr->expression();
2330  DCHECK(callee->IsProperty());
2331  Property* prop = callee->AsProperty();
2332  DCHECK(prop->IsSuperAccess());
2333
2334  SetExpressionPosition(prop);
2335  // Load the function from the receiver.
2336  const Register scratch = r1;
2337  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
2338  VisitForStackValue(super_ref->home_object());
2339  VisitForAccumulatorValue(super_ref->this_var());
2340  PushOperand(r0);
2341  PushOperand(r0);
2342  __ ldr(scratch, MemOperand(sp, kPointerSize * 2));
2343  PushOperand(scratch);
2344  VisitForStackValue(prop->key());
2345
2346  // Stack here:
2347  //  - home_object
2348  //  - this (receiver)
2349  //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
2350  //  - home_object
2351  //  - key
2352  CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
2353  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
2354
2355  // Replace home_object with target function.
2356  __ str(r0, MemOperand(sp, kPointerSize));
2357
2358  // Stack here:
2359  // - target function
2360  // - this (receiver)
2361  EmitCall(expr);
2362}
2363
2364
2365void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
2366  // Load the arguments.
2367  ZoneList<Expression*>* args = expr->arguments();
2368  int arg_count = args->length();
2369  for (int i = 0; i < arg_count; i++) {
2370    VisitForStackValue(args->at(i));
2371  }
2372
2373  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
2374  SetCallPosition(expr, expr->tail_call_mode());
2375  if (expr->tail_call_mode() == TailCallMode::kAllow) {
2376    if (FLAG_trace) {
2377      __ CallRuntime(Runtime::kTraceTailCall);
2378    }
2379    // Update profiling counters before the tail call since we will
2380    // not return to this function.
2381    EmitProfilingCounterHandlingForReturnSequence(true);
2382  }
2383  Handle<Code> code =
2384      CodeFactory::CallIC(isolate(), mode, expr->tail_call_mode()).code();
2385  __ mov(r3, Operand(SmiFromSlot(expr->CallFeedbackICSlot())));
2386  __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2387  __ mov(r0, Operand(arg_count));
2388  CallIC(code);
2389  OperandStackDepthDecrement(arg_count + 1);
2390
2391  RecordJSReturnSite(expr);
2392  RestoreContext();
2393  context()->DropAndPlug(1, r0);
2394}
2395
2396void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
2397  int arg_count = expr->arguments()->length();
2398  // r4: copy of the first argument or undefined if it doesn't exist.
2399  if (arg_count > 0) {
2400    __ ldr(r4, MemOperand(sp, arg_count * kPointerSize));
2401  } else {
2402    __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
2403  }
2404
2405  // r3: the receiver of the enclosing function.
2406  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
2407
2408  // r2: language mode.
2409  __ mov(r2, Operand(Smi::FromInt(language_mode())));
2410
2411  // r1: the start position of the scope the calls resides in.
2412  __ mov(r1, Operand(Smi::FromInt(scope()->start_position())));
2413
2414  // r0: the source position of the eval call.
2415  __ mov(r0, Operand(Smi::FromInt(expr->position())));
2416
2417  // Do the runtime call.
2418  __ Push(r4, r3, r2, r1, r0);
2419  __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
2420}
2421
2422
2423// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
2424void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
2425  VariableProxy* callee = expr->expression()->AsVariableProxy();
2426  if (callee->var()->IsLookupSlot()) {
2427    Label slow, done;
2428    SetExpressionPosition(callee);
2429    // Generate code for loading from variables potentially shadowed
2430    // by eval-introduced variables.
2431    EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
2432
2433    __ bind(&slow);
2434    // Call the runtime to find the function to call (returned in r0)
2435    // and the object holding it (returned in edx).
2436    __ Push(callee->name());
2437    __ CallRuntime(Runtime::kLoadLookupSlotForCall);
2438    PushOperands(r0, r1);  // Function, receiver.
2439    PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
2440
2441    // If fast case code has been generated, emit code to push the
2442    // function and receiver and have the slow path jump around this
2443    // code.
2444    if (done.is_linked()) {
2445      Label call;
2446      __ b(&call);
2447      __ bind(&done);
2448      // Push function.
2449      __ push(r0);
2450      // The receiver is implicitly the global receiver. Indicate this
2451      // by passing the hole to the call function stub.
2452      __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
2453      __ push(r1);
2454      __ bind(&call);
2455    }
2456  } else {
2457    VisitForStackValue(callee);
2458    // refEnv.WithBaseObject()
2459    __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
2460    PushOperand(r2);  // Reserved receiver slot.
2461  }
2462}
2463
2464
2465void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
2466  // In a call to eval, we first call
2467  // Runtime_ResolvePossiblyDirectEval to resolve the function we need
2468  // to call.  Then we call the resolved function using the given arguments.
2469  ZoneList<Expression*>* args = expr->arguments();
2470  int arg_count = args->length();
2471
2472  PushCalleeAndWithBaseObject(expr);
2473
2474  // Push the arguments.
2475  for (int i = 0; i < arg_count; i++) {
2476    VisitForStackValue(args->at(i));
2477  }
2478
2479  // Push a copy of the function (found below the arguments) and
2480  // resolve eval.
2481  __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2482  __ push(r1);
2483  EmitResolvePossiblyDirectEval(expr);
2484
2485  // Touch up the stack with the resolved function.
2486  __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
2487
2488  PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
2489
2490  // Record source position for debugger.
2491  SetCallPosition(expr);
2492  Handle<Code> code = CodeFactory::CallIC(isolate(), ConvertReceiverMode::kAny,
2493                                          expr->tail_call_mode())
2494                          .code();
2495  __ mov(r3, Operand(SmiFromSlot(expr->CallFeedbackICSlot())));
2496  __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2497  __ mov(r0, Operand(arg_count));
2498  __ Call(code, RelocInfo::CODE_TARGET);
2499  OperandStackDepthDecrement(arg_count + 1);
2500  RecordJSReturnSite(expr);
2501  RestoreContext();
2502  context()->DropAndPlug(1, r0);
2503}
2504
2505
2506void FullCodeGenerator::VisitCallNew(CallNew* expr) {
2507  Comment cmnt(masm_, "[ CallNew");
2508  // According to ECMA-262, section 11.2.2, page 44, the function
2509  // expression in new calls must be evaluated before the
2510  // arguments.
2511
2512  // Push constructor on the stack.  If it's not a function it's used as
2513  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
2514  // ignored.
2515  DCHECK(!expr->expression()->IsSuperPropertyReference());
2516  VisitForStackValue(expr->expression());
2517
2518  // Push the arguments ("left-to-right") on the stack.
2519  ZoneList<Expression*>* args = expr->arguments();
2520  int arg_count = args->length();
2521  for (int i = 0; i < arg_count; i++) {
2522    VisitForStackValue(args->at(i));
2523  }
2524
2525  // Call the construct call builtin that handles allocation and
2526  // constructor invocation.
2527  SetConstructCallPosition(expr);
2528
2529  // Load function and argument count into r1 and r0.
2530  __ mov(r0, Operand(arg_count));
2531  __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
2532
2533  // Record call targets in unoptimized code.
2534  __ EmitLoadTypeFeedbackVector(r2);
2535  __ mov(r3, Operand(SmiFromSlot(expr->CallNewFeedbackSlot())));
2536
2537  CallConstructStub stub(isolate());
2538  CallIC(stub.GetCode());
2539  OperandStackDepthDecrement(arg_count + 1);
2540  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
2541  RestoreContext();
2542  context()->Plug(r0);
2543}
2544
2545
2546void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
2547  SuperCallReference* super_call_ref =
2548      expr->expression()->AsSuperCallReference();
2549  DCHECK_NOT_NULL(super_call_ref);
2550
2551  // Push the super constructor target on the stack (may be null,
2552  // but the Construct builtin can deal with that properly).
2553  VisitForAccumulatorValue(super_call_ref->this_function_var());
2554  __ AssertFunction(result_register());
2555  __ ldr(result_register(),
2556         FieldMemOperand(result_register(), HeapObject::kMapOffset));
2557  __ ldr(result_register(),
2558         FieldMemOperand(result_register(), Map::kPrototypeOffset));
2559  PushOperand(result_register());
2560
2561  // Push the arguments ("left-to-right") on the stack.
2562  ZoneList<Expression*>* args = expr->arguments();
2563  int arg_count = args->length();
2564  for (int i = 0; i < arg_count; i++) {
2565    VisitForStackValue(args->at(i));
2566  }
2567
2568  // Call the construct call builtin that handles allocation and
2569  // constructor invocation.
2570  SetConstructCallPosition(expr);
2571
2572  // Load new target into r3.
2573  VisitForAccumulatorValue(super_call_ref->new_target_var());
2574  __ mov(r3, result_register());
2575
2576  // Load function and argument count into r1 and r0.
2577  __ mov(r0, Operand(arg_count));
2578  __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
2579
2580  __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
2581  OperandStackDepthDecrement(arg_count + 1);
2582
2583  RecordJSReturnSite(expr);
2584  RestoreContext();
2585  context()->Plug(r0);
2586}
2587
2588
2589void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2590  ZoneList<Expression*>* args = expr->arguments();
2591  DCHECK(args->length() == 1);
2592
2593  VisitForAccumulatorValue(args->at(0));
2594
2595  Label materialize_true, materialize_false;
2596  Label* if_true = NULL;
2597  Label* if_false = NULL;
2598  Label* fall_through = NULL;
2599  context()->PrepareTest(&materialize_true, &materialize_false,
2600                         &if_true, &if_false, &fall_through);
2601
2602  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2603  __ SmiTst(r0);
2604  Split(eq, if_true, if_false, fall_through);
2605
2606  context()->Plug(if_true, if_false);
2607}
2608
2609
2610void FullCodeGenerator::EmitIsJSReceiver(CallRuntime* expr) {
2611  ZoneList<Expression*>* args = expr->arguments();
2612  DCHECK(args->length() == 1);
2613
2614  VisitForAccumulatorValue(args->at(0));
2615
2616  Label materialize_true, materialize_false;
2617  Label* if_true = NULL;
2618  Label* if_false = NULL;
2619  Label* fall_through = NULL;
2620  context()->PrepareTest(&materialize_true, &materialize_false,
2621                         &if_true, &if_false, &fall_through);
2622
2623  __ JumpIfSmi(r0, if_false);
2624  __ CompareObjectType(r0, r1, r1, FIRST_JS_RECEIVER_TYPE);
2625  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2626  Split(ge, if_true, if_false, fall_through);
2627
2628  context()->Plug(if_true, if_false);
2629}
2630
2631
2632void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
2633  ZoneList<Expression*>* args = expr->arguments();
2634  DCHECK(args->length() == 1);
2635
2636  VisitForAccumulatorValue(args->at(0));
2637
2638  Label materialize_true, materialize_false;
2639  Label* if_true = NULL;
2640  Label* if_false = NULL;
2641  Label* fall_through = NULL;
2642  context()->PrepareTest(&materialize_true, &materialize_false,
2643                         &if_true, &if_false, &fall_through);
2644
2645  __ JumpIfSmi(r0, if_false);
2646  __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
2647  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2648  Split(eq, if_true, if_false, fall_through);
2649
2650  context()->Plug(if_true, if_false);
2651}
2652
2653
2654void FullCodeGenerator::EmitIsTypedArray(CallRuntime* expr) {
2655  ZoneList<Expression*>* args = expr->arguments();
2656  DCHECK(args->length() == 1);
2657
2658  VisitForAccumulatorValue(args->at(0));
2659
2660  Label materialize_true, materialize_false;
2661  Label* if_true = NULL;
2662  Label* if_false = NULL;
2663  Label* fall_through = NULL;
2664  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
2665                         &if_false, &fall_through);
2666
2667  __ JumpIfSmi(r0, if_false);
2668  __ CompareObjectType(r0, r1, r1, JS_TYPED_ARRAY_TYPE);
2669  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2670  Split(eq, if_true, if_false, fall_through);
2671
2672  context()->Plug(if_true, if_false);
2673}
2674
2675
2676void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
2677  ZoneList<Expression*>* args = expr->arguments();
2678  DCHECK(args->length() == 1);
2679
2680  VisitForAccumulatorValue(args->at(0));
2681
2682  Label materialize_true, materialize_false;
2683  Label* if_true = NULL;
2684  Label* if_false = NULL;
2685  Label* fall_through = NULL;
2686  context()->PrepareTest(&materialize_true, &materialize_false,
2687                         &if_true, &if_false, &fall_through);
2688
2689  __ JumpIfSmi(r0, if_false);
2690  __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
2691  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2692  Split(eq, if_true, if_false, fall_through);
2693
2694  context()->Plug(if_true, if_false);
2695}
2696
2697
2698void FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) {
2699  ZoneList<Expression*>* args = expr->arguments();
2700  DCHECK(args->length() == 1);
2701
2702  VisitForAccumulatorValue(args->at(0));
2703
2704  Label materialize_true, materialize_false;
2705  Label* if_true = NULL;
2706  Label* if_false = NULL;
2707  Label* fall_through = NULL;
2708  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
2709                         &if_false, &fall_through);
2710
2711  __ JumpIfSmi(r0, if_false);
2712  __ CompareObjectType(r0, r1, r1, JS_PROXY_TYPE);
2713  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2714  Split(eq, if_true, if_false, fall_through);
2715
2716  context()->Plug(if_true, if_false);
2717}
2718
2719
2720void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
2721  ZoneList<Expression*>* args = expr->arguments();
2722  DCHECK(args->length() == 1);
2723  Label done, null, function, non_function_constructor;
2724
2725  VisitForAccumulatorValue(args->at(0));
2726
2727  // If the object is not a JSReceiver, we return null.
2728  __ JumpIfSmi(r0, &null);
2729  STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
2730  __ CompareObjectType(r0, r0, r1, FIRST_JS_RECEIVER_TYPE);
2731  // Map is now in r0.
2732  __ b(lt, &null);
2733
2734  // Return 'Function' for JSFunction and JSBoundFunction objects.
2735  __ cmp(r1, Operand(FIRST_FUNCTION_TYPE));
2736  STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
2737  __ b(hs, &function);
2738
2739  // Check if the constructor in the map is a JS function.
2740  Register instance_type = r2;
2741  __ GetMapConstructor(r0, r0, r1, instance_type);
2742  __ cmp(instance_type, Operand(JS_FUNCTION_TYPE));
2743  __ b(ne, &non_function_constructor);
2744
2745  // r0 now contains the constructor function. Grab the
2746  // instance class name from there.
2747  __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
2748  __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset));
2749  __ b(&done);
2750
2751  // Functions have class 'Function'.
2752  __ bind(&function);
2753  __ LoadRoot(r0, Heap::kFunction_stringRootIndex);
2754  __ jmp(&done);
2755
2756  // Objects with a non-function constructor have class 'Object'.
2757  __ bind(&non_function_constructor);
2758  __ LoadRoot(r0, Heap::kObject_stringRootIndex);
2759  __ jmp(&done);
2760
2761  // Non-JS objects have class null.
2762  __ bind(&null);
2763  __ LoadRoot(r0, Heap::kNullValueRootIndex);
2764
2765  // All done.
2766  __ bind(&done);
2767
2768  context()->Plug(r0);
2769}
2770
2771
2772void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
2773  ZoneList<Expression*>* args = expr->arguments();
2774  DCHECK(args->length() == 2);
2775  VisitForStackValue(args->at(0));
2776  VisitForAccumulatorValue(args->at(1));
2777
2778  Register object = r1;
2779  Register index = r0;
2780  Register result = r3;
2781
2782  PopOperand(object);
2783
2784  Label need_conversion;
2785  Label index_out_of_range;
2786  Label done;
2787  StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
2788                                      &need_conversion, &index_out_of_range);
2789  generator.GenerateFast(masm_);
2790  __ jmp(&done);
2791
2792  __ bind(&index_out_of_range);
2793  // When the index is out of range, the spec requires us to return
2794  // NaN.
2795  __ LoadRoot(result, Heap::kNanValueRootIndex);
2796  __ jmp(&done);
2797
2798  __ bind(&need_conversion);
2799  // Load the undefined value into the result register, which will
2800  // trigger conversion.
2801  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
2802  __ jmp(&done);
2803
2804  NopRuntimeCallHelper call_helper;
2805  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
2806
2807  __ bind(&done);
2808  context()->Plug(result);
2809}
2810
2811
2812void FullCodeGenerator::EmitCall(CallRuntime* expr) {
2813  ZoneList<Expression*>* args = expr->arguments();
2814  DCHECK_LE(2, args->length());
2815  // Push target, receiver and arguments onto the stack.
2816  for (Expression* const arg : *args) {
2817    VisitForStackValue(arg);
2818  }
2819  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
2820  // Move target to r1.
2821  int const argc = args->length() - 2;
2822  __ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize));
2823  // Call the target.
2824  __ mov(r0, Operand(argc));
2825  __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
2826  OperandStackDepthDecrement(argc + 1);
2827  RestoreContext();
2828  // Discard the function left on TOS.
2829  context()->DropAndPlug(1, r0);
2830}
2831
2832void FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) {
2833  ZoneList<Expression*>* args = expr->arguments();
2834  DCHECK_EQ(1, args->length());
2835  VisitForAccumulatorValue(args->at(0));
2836  __ AssertFunction(r0);
2837  __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
2838  __ ldr(r0, FieldMemOperand(r0, Map::kPrototypeOffset));
2839  context()->Plug(r0);
2840}
2841
2842void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
2843  DCHECK(expr->arguments()->length() == 0);
2844  ExternalReference debug_is_active =
2845      ExternalReference::debug_is_active_address(isolate());
2846  __ mov(ip, Operand(debug_is_active));
2847  __ ldrb(r0, MemOperand(ip));
2848  __ SmiTag(r0);
2849  context()->Plug(r0);
2850}
2851
2852
2853void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
2854  ZoneList<Expression*>* args = expr->arguments();
2855  DCHECK_EQ(2, args->length());
2856  VisitForStackValue(args->at(0));
2857  VisitForStackValue(args->at(1));
2858
2859  Label runtime, done;
2860
2861  __ Allocate(JSIteratorResult::kSize, r0, r2, r3, &runtime,
2862              NO_ALLOCATION_FLAGS);
2863  __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, r1);
2864  __ pop(r3);
2865  __ pop(r2);
2866  __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex);
2867  __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2868  __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset));
2869  __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
2870  __ str(r2, FieldMemOperand(r0, JSIteratorResult::kValueOffset));
2871  __ str(r3, FieldMemOperand(r0, JSIteratorResult::kDoneOffset));
2872  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
2873  __ b(&done);
2874
2875  __ bind(&runtime);
2876  CallRuntimeWithOperands(Runtime::kCreateIterResultObject);
2877
2878  __ bind(&done);
2879  context()->Plug(r0);
2880}
2881
2882
2883void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
2884  // Push function.
2885  __ LoadNativeContextSlot(expr->context_index(), r0);
2886  PushOperand(r0);
2887
2888  // Push undefined as the receiver.
2889  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
2890  PushOperand(r0);
2891}
2892
2893
2894void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
2895  ZoneList<Expression*>* args = expr->arguments();
2896  int arg_count = args->length();
2897
2898  SetCallPosition(expr);
2899  __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2900  __ mov(r0, Operand(arg_count));
2901  __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
2902          RelocInfo::CODE_TARGET);
2903  OperandStackDepthDecrement(arg_count + 1);
2904  RestoreContext();
2905}
2906
2907
2908void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2909  switch (expr->op()) {
2910    case Token::DELETE: {
2911      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
2912      Property* property = expr->expression()->AsProperty();
2913      VariableProxy* proxy = expr->expression()->AsVariableProxy();
2914
2915      if (property != NULL) {
2916        VisitForStackValue(property->obj());
2917        VisitForStackValue(property->key());
2918        CallRuntimeWithOperands(is_strict(language_mode())
2919                                    ? Runtime::kDeleteProperty_Strict
2920                                    : Runtime::kDeleteProperty_Sloppy);
2921        context()->Plug(r0);
2922      } else if (proxy != NULL) {
2923        Variable* var = proxy->var();
2924        // Delete of an unqualified identifier is disallowed in strict mode but
2925        // "delete this" is allowed.
2926        bool is_this = var->is_this();
2927        DCHECK(is_sloppy(language_mode()) || is_this);
2928        if (var->IsUnallocated()) {
2929          __ LoadGlobalObject(r2);
2930          __ mov(r1, Operand(var->name()));
2931          __ Push(r2, r1);
2932          __ CallRuntime(Runtime::kDeleteProperty_Sloppy);
2933          context()->Plug(r0);
2934        } else if (var->IsStackAllocated() || var->IsContextSlot()) {
2935          // Result of deleting non-global, non-dynamic variables is false.
2936          // The subexpression does not have side effects.
2937          context()->Plug(is_this);
2938        } else {
2939          // Non-global variable.  Call the runtime to try to delete from the
2940          // context where the variable was introduced.
2941          __ Push(var->name());
2942          __ CallRuntime(Runtime::kDeleteLookupSlot);
2943          context()->Plug(r0);
2944        }
2945      } else {
2946        // Result of deleting non-property, non-variable reference is true.
2947        // The subexpression may have side effects.
2948        VisitForEffect(expr->expression());
2949        context()->Plug(true);
2950      }
2951      break;
2952    }
2953
2954    case Token::VOID: {
2955      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
2956      VisitForEffect(expr->expression());
2957      context()->Plug(Heap::kUndefinedValueRootIndex);
2958      break;
2959    }
2960
2961    case Token::NOT: {
2962      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2963      if (context()->IsEffect()) {
2964        // Unary NOT has no side effects so it's only necessary to visit the
2965        // subexpression.  Match the optimizing compiler by not branching.
2966        VisitForEffect(expr->expression());
2967      } else if (context()->IsTest()) {
2968        const TestContext* test = TestContext::cast(context());
2969        // The labels are swapped for the recursive call.
2970        VisitForControl(expr->expression(),
2971                        test->false_label(),
2972                        test->true_label(),
2973                        test->fall_through());
2974        context()->Plug(test->true_label(), test->false_label());
2975      } else {
2976        // We handle value contexts explicitly rather than simply visiting
2977        // for control and plugging the control flow into the context,
2978        // because we need to prepare a pair of extra administrative AST ids
2979        // for the optimizing compiler.
2980        DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue());
2981        Label materialize_true, materialize_false, done;
2982        VisitForControl(expr->expression(),
2983                        &materialize_false,
2984                        &materialize_true,
2985                        &materialize_true);
2986        if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
2987        __ bind(&materialize_true);
2988        PrepareForBailoutForId(expr->MaterializeTrueId(),
2989                               BailoutState::NO_REGISTERS);
2990        __ LoadRoot(r0, Heap::kTrueValueRootIndex);
2991        if (context()->IsStackValue()) __ push(r0);
2992        __ jmp(&done);
2993        __ bind(&materialize_false);
2994        PrepareForBailoutForId(expr->MaterializeFalseId(),
2995                               BailoutState::NO_REGISTERS);
2996        __ LoadRoot(r0, Heap::kFalseValueRootIndex);
2997        if (context()->IsStackValue()) __ push(r0);
2998        __ bind(&done);
2999      }
3000      break;
3001    }
3002
3003    case Token::TYPEOF: {
3004      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
3005      {
3006        AccumulatorValueContext context(this);
3007        VisitForTypeofValue(expr->expression());
3008      }
3009      __ mov(r3, r0);
3010      __ Call(isolate()->builtins()->Typeof(), RelocInfo::CODE_TARGET);
3011      context()->Plug(r0);
3012      break;
3013    }
3014
3015    default:
3016      UNREACHABLE();
3017  }
3018}
3019
3020
3021void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3022  DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
3023
3024  Comment cmnt(masm_, "[ CountOperation");
3025
3026  Property* prop = expr->expression()->AsProperty();
3027  LhsKind assign_type = Property::GetAssignType(prop);
3028
3029  // Evaluate expression and get value.
3030  if (assign_type == VARIABLE) {
3031    DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
3032    AccumulatorValueContext context(this);
3033    EmitVariableLoad(expr->expression()->AsVariableProxy());
3034  } else {
3035    // Reserve space for result of postfix operation.
3036    if (expr->is_postfix() && !context()->IsEffect()) {
3037      __ mov(ip, Operand(Smi::kZero));
3038      PushOperand(ip);
3039    }
3040    switch (assign_type) {
3041      case NAMED_PROPERTY: {
3042        // Put the object both on the stack and in the register.
3043        VisitForStackValue(prop->obj());
3044        __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
3045        EmitNamedPropertyLoad(prop);
3046        break;
3047      }
3048
3049      case NAMED_SUPER_PROPERTY: {
3050        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
3051        VisitForAccumulatorValue(
3052            prop->obj()->AsSuperPropertyReference()->home_object());
3053        PushOperand(result_register());
3054        const Register scratch = r1;
3055        __ ldr(scratch, MemOperand(sp, kPointerSize));
3056        PushOperand(scratch);
3057        PushOperand(result_register());
3058        EmitNamedSuperPropertyLoad(prop);
3059        break;
3060      }
3061
3062      case KEYED_SUPER_PROPERTY: {
3063        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
3064        VisitForStackValue(
3065            prop->obj()->AsSuperPropertyReference()->home_object());
3066        VisitForAccumulatorValue(prop->key());
3067        PushOperand(result_register());
3068        const Register scratch = r1;
3069        __ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
3070        PushOperand(scratch);
3071        __ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
3072        PushOperand(scratch);
3073        PushOperand(result_register());
3074        EmitKeyedSuperPropertyLoad(prop);
3075        break;
3076      }
3077
3078      case KEYED_PROPERTY: {
3079        VisitForStackValue(prop->obj());
3080        VisitForStackValue(prop->key());
3081        __ ldr(LoadDescriptor::ReceiverRegister(),
3082               MemOperand(sp, 1 * kPointerSize));
3083        __ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0));
3084        EmitKeyedPropertyLoad(prop);
3085        break;
3086      }
3087
3088      case VARIABLE:
3089        UNREACHABLE();
3090    }
3091  }
3092
3093  // We need a second deoptimization point after loading the value
3094  // in case evaluating the property load my have a side effect.
3095  if (assign_type == VARIABLE) {
3096    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
3097  } else {
3098    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
3099  }
3100
3101  // Inline smi case if we are in a loop.
3102  Label stub_call, done;
3103  JumpPatchSite patch_site(masm_);
3104
3105  int count_value = expr->op() == Token::INC ? 1 : -1;
3106  if (ShouldInlineSmiCase(expr->op())) {
3107    Label slow;
3108    patch_site.EmitJumpIfNotSmi(r0, &slow);
3109
3110    // Save result for postfix expressions.
3111    if (expr->is_postfix()) {
3112      if (!context()->IsEffect()) {
3113        // Save the result on the stack. If we have a named or keyed property
3114        // we store the result under the receiver that is currently on top
3115        // of the stack.
3116        switch (assign_type) {
3117          case VARIABLE:
3118            __ push(r0);
3119            break;
3120          case NAMED_PROPERTY:
3121            __ str(r0, MemOperand(sp, kPointerSize));
3122            break;
3123          case NAMED_SUPER_PROPERTY:
3124            __ str(r0, MemOperand(sp, 2 * kPointerSize));
3125            break;
3126          case KEYED_PROPERTY:
3127            __ str(r0, MemOperand(sp, 2 * kPointerSize));
3128            break;
3129          case KEYED_SUPER_PROPERTY:
3130            __ str(r0, MemOperand(sp, 3 * kPointerSize));
3131            break;
3132        }
3133      }
3134    }
3135
3136    __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC);
3137    __ b(vc, &done);
3138    // Call stub. Undo operation first.
3139    __ sub(r0, r0, Operand(Smi::FromInt(count_value)));
3140    __ jmp(&stub_call);
3141    __ bind(&slow);
3142  }
3143
3144  // Convert old value into a number.
3145  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
3146  RestoreContext();
3147  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
3148
3149  // Save result for postfix expressions.
3150  if (expr->is_postfix()) {
3151    if (!context()->IsEffect()) {
3152      // Save the result on the stack. If we have a named or keyed property
3153      // we store the result under the receiver that is currently on top
3154      // of the stack.
3155      switch (assign_type) {
3156        case VARIABLE:
3157          PushOperand(r0);
3158          break;
3159        case NAMED_PROPERTY:
3160          __ str(r0, MemOperand(sp, kPointerSize));
3161          break;
3162        case NAMED_SUPER_PROPERTY:
3163          __ str(r0, MemOperand(sp, 2 * kPointerSize));
3164          break;
3165        case KEYED_PROPERTY:
3166          __ str(r0, MemOperand(sp, 2 * kPointerSize));
3167          break;
3168        case KEYED_SUPER_PROPERTY:
3169          __ str(r0, MemOperand(sp, 3 * kPointerSize));
3170          break;
3171      }
3172    }
3173  }
3174
3175
3176  __ bind(&stub_call);
3177  __ mov(r1, r0);
3178  __ mov(r0, Operand(Smi::FromInt(count_value)));
3179
3180  SetExpressionPosition(expr);
3181
3182  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code();
3183  CallIC(code, expr->CountBinOpFeedbackId());
3184  patch_site.EmitPatchInfo();
3185  __ bind(&done);
3186
3187  // Store the value returned in r0.
3188  switch (assign_type) {
3189    case VARIABLE: {
3190      VariableProxy* proxy = expr->expression()->AsVariableProxy();
3191      if (expr->is_postfix()) {
3192        { EffectContext context(this);
3193          EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
3194                                 proxy->hole_check_mode());
3195          PrepareForBailoutForId(expr->AssignmentId(),
3196                                 BailoutState::TOS_REGISTER);
3197          context.Plug(r0);
3198        }
3199        // For all contexts except EffectConstant We have the result on
3200        // top of the stack.
3201        if (!context()->IsEffect()) {
3202          context()->PlugTOS();
3203        }
3204      } else {
3205        EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
3206                               proxy->hole_check_mode());
3207        PrepareForBailoutForId(expr->AssignmentId(),
3208                               BailoutState::TOS_REGISTER);
3209        context()->Plug(r0);
3210      }
3211      break;
3212    }
3213    case NAMED_PROPERTY: {
3214      PopOperand(StoreDescriptor::ReceiverRegister());
3215      CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value());
3216      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3217      if (expr->is_postfix()) {
3218        if (!context()->IsEffect()) {
3219          context()->PlugTOS();
3220        }
3221      } else {
3222        context()->Plug(r0);
3223      }
3224      break;
3225    }
3226    case NAMED_SUPER_PROPERTY: {
3227      EmitNamedSuperPropertyStore(prop);
3228      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3229      if (expr->is_postfix()) {
3230        if (!context()->IsEffect()) {
3231          context()->PlugTOS();
3232        }
3233      } else {
3234        context()->Plug(r0);
3235      }
3236      break;
3237    }
3238    case KEYED_SUPER_PROPERTY: {
3239      EmitKeyedSuperPropertyStore(prop);
3240      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3241      if (expr->is_postfix()) {
3242        if (!context()->IsEffect()) {
3243          context()->PlugTOS();
3244        }
3245      } else {
3246        context()->Plug(r0);
3247      }
3248      break;
3249    }
3250    case KEYED_PROPERTY: {
3251      PopOperands(StoreDescriptor::ReceiverRegister(),
3252                  StoreDescriptor::NameRegister());
3253      CallKeyedStoreIC(expr->CountSlot());
3254      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3255      if (expr->is_postfix()) {
3256        if (!context()->IsEffect()) {
3257          context()->PlugTOS();
3258        }
3259      } else {
3260        context()->Plug(r0);
3261      }
3262      break;
3263    }
3264  }
3265}
3266
3267
3268void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
3269                                                 Expression* sub_expr,
3270                                                 Handle<String> check) {
3271  Label materialize_true, materialize_false;
3272  Label* if_true = NULL;
3273  Label* if_false = NULL;
3274  Label* fall_through = NULL;
3275  context()->PrepareTest(&materialize_true, &materialize_false,
3276                         &if_true, &if_false, &fall_through);
3277
3278  { AccumulatorValueContext context(this);
3279    VisitForTypeofValue(sub_expr);
3280  }
3281  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3282
3283  Factory* factory = isolate()->factory();
3284  if (String::Equals(check, factory->number_string())) {
3285    __ JumpIfSmi(r0, if_true);
3286    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
3287    __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
3288    __ cmp(r0, ip);
3289    Split(eq, if_true, if_false, fall_through);
3290  } else if (String::Equals(check, factory->string_string())) {
3291    __ JumpIfSmi(r0, if_false);
3292    __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE);
3293    Split(lt, if_true, if_false, fall_through);
3294  } else if (String::Equals(check, factory->symbol_string())) {
3295    __ JumpIfSmi(r0, if_false);
3296    __ CompareObjectType(r0, r0, r1, SYMBOL_TYPE);
3297    Split(eq, if_true, if_false, fall_through);
3298  } else if (String::Equals(check, factory->boolean_string())) {
3299    __ CompareRoot(r0, Heap::kTrueValueRootIndex);
3300    __ b(eq, if_true);
3301    __ CompareRoot(r0, Heap::kFalseValueRootIndex);
3302    Split(eq, if_true, if_false, fall_through);
3303  } else if (String::Equals(check, factory->undefined_string())) {
3304    __ CompareRoot(r0, Heap::kNullValueRootIndex);
3305    __ b(eq, if_false);
3306    __ JumpIfSmi(r0, if_false);
3307    // Check for undetectable objects => true.
3308    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
3309    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
3310    __ tst(r1, Operand(1 << Map::kIsUndetectable));
3311    Split(ne, if_true, if_false, fall_through);
3312
3313  } else if (String::Equals(check, factory->function_string())) {
3314    __ JumpIfSmi(r0, if_false);
3315    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
3316    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
3317    __ and_(r1, r1,
3318            Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
3319    __ cmp(r1, Operand(1 << Map::kIsCallable));
3320    Split(eq, if_true, if_false, fall_through);
3321  } else if (String::Equals(check, factory->object_string())) {
3322    __ JumpIfSmi(r0, if_false);
3323    __ CompareRoot(r0, Heap::kNullValueRootIndex);
3324    __ b(eq, if_true);
3325    STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
3326    __ CompareObjectType(r0, r0, r1, FIRST_JS_RECEIVER_TYPE);
3327    __ b(lt, if_false);
3328    // Check for callable or undetectable objects => false.
3329    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
3330    __ tst(r1, Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
3331    Split(eq, if_true, if_false, fall_through);
3332// clang-format off
3333#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type)   \
3334  } else if (String::Equals(check, factory->type##_string())) { \
3335    __ JumpIfSmi(r0, if_false);                                 \
3336    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));    \
3337    __ CompareRoot(r0, Heap::k##Type##MapRootIndex);            \
3338    Split(eq, if_true, if_false, fall_through);
3339  SIMD128_TYPES(SIMD128_TYPE)
3340#undef SIMD128_TYPE
3341    // clang-format on
3342  } else {
3343    if (if_false != fall_through) __ jmp(if_false);
3344  }
3345  context()->Plug(if_true, if_false);
3346}
3347
3348
3349void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
3350  Comment cmnt(masm_, "[ CompareOperation");
3351
3352  // First we try a fast inlined version of the compare when one of
3353  // the operands is a literal.
3354  if (TryLiteralCompare(expr)) return;
3355
3356  // Always perform the comparison for its control flow.  Pack the result
3357  // into the expression's context after the comparison is performed.
3358  Label materialize_true, materialize_false;
3359  Label* if_true = NULL;
3360  Label* if_false = NULL;
3361  Label* fall_through = NULL;
3362  context()->PrepareTest(&materialize_true, &materialize_false,
3363                         &if_true, &if_false, &fall_through);
3364
3365  Token::Value op = expr->op();
3366  VisitForStackValue(expr->left());
3367  switch (op) {
3368    case Token::IN:
3369      VisitForStackValue(expr->right());
3370      SetExpressionPosition(expr);
3371      EmitHasProperty();
3372      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
3373      __ CompareRoot(r0, Heap::kTrueValueRootIndex);
3374      Split(eq, if_true, if_false, fall_through);
3375      break;
3376
3377    case Token::INSTANCEOF: {
3378      VisitForAccumulatorValue(expr->right());
3379      SetExpressionPosition(expr);
3380      PopOperand(r1);
3381      __ Call(isolate()->builtins()->InstanceOf(), RelocInfo::CODE_TARGET);
3382      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
3383      __ CompareRoot(r0, Heap::kTrueValueRootIndex);
3384      Split(eq, if_true, if_false, fall_through);
3385      break;
3386    }
3387
3388    default: {
3389      VisitForAccumulatorValue(expr->right());
3390      SetExpressionPosition(expr);
3391      Condition cond = CompareIC::ComputeCondition(op);
3392      PopOperand(r1);
3393
3394      bool inline_smi_code = ShouldInlineSmiCase(op);
3395      JumpPatchSite patch_site(masm_);
3396      if (inline_smi_code) {
3397        Label slow_case;
3398        __ orr(r2, r0, Operand(r1));
3399        patch_site.EmitJumpIfNotSmi(r2, &slow_case);
3400        __ cmp(r1, r0);
3401        Split(cond, if_true, if_false, NULL);
3402        __ bind(&slow_case);
3403      }
3404
3405      Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
3406      CallIC(ic, expr->CompareOperationFeedbackId());
3407      patch_site.EmitPatchInfo();
3408      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3409      __ cmp(r0, Operand::Zero());
3410      Split(cond, if_true, if_false, fall_through);
3411    }
3412  }
3413
3414  // Convert the result of the comparison into one expected for this
3415  // expression's context.
3416  context()->Plug(if_true, if_false);
3417}
3418
3419
3420void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
3421                                              Expression* sub_expr,
3422                                              NilValue nil) {
3423  Label materialize_true, materialize_false;
3424  Label* if_true = NULL;
3425  Label* if_false = NULL;
3426  Label* fall_through = NULL;
3427  context()->PrepareTest(&materialize_true, &materialize_false,
3428                         &if_true, &if_false, &fall_through);
3429
3430  VisitForAccumulatorValue(sub_expr);
3431  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3432  if (expr->op() == Token::EQ_STRICT) {
3433    Heap::RootListIndex nil_value = nil == kNullValue ?
3434        Heap::kNullValueRootIndex :
3435        Heap::kUndefinedValueRootIndex;
3436    __ LoadRoot(r1, nil_value);
3437    __ cmp(r0, r1);
3438    Split(eq, if_true, if_false, fall_through);
3439  } else {
3440    __ JumpIfSmi(r0, if_false);
3441    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
3442    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
3443    __ tst(r1, Operand(1 << Map::kIsUndetectable));
3444    Split(ne, if_true, if_false, fall_through);
3445  }
3446  context()->Plug(if_true, if_false);
3447}
3448
3449
3450Register FullCodeGenerator::result_register() {
3451  return r0;
3452}
3453
3454
3455Register FullCodeGenerator::context_register() {
3456  return cp;
3457}
3458
3459void FullCodeGenerator::LoadFromFrameField(int frame_offset, Register value) {
3460  DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
3461  __ ldr(value, MemOperand(fp, frame_offset));
3462}
3463
3464void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
3465  DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
3466  __ str(value, MemOperand(fp, frame_offset));
3467}
3468
3469
3470void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
3471  __ ldr(dst, ContextMemOperand(cp, context_index));
3472}
3473
3474
3475void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
3476  DeclarationScope* closure_scope = scope()->GetClosureScope();
3477  if (closure_scope->is_script_scope() ||
3478      closure_scope->is_module_scope()) {
3479    // Contexts nested in the native context have a canonical empty function
3480    // as their closure, not the anonymous closure containing the global
3481    // code.
3482    __ LoadNativeContextSlot(Context::CLOSURE_INDEX, ip);
3483  } else if (closure_scope->is_eval_scope()) {
3484    // Contexts created by a call to eval have the same closure as the
3485    // context calling eval, not the anonymous closure containing the eval
3486    // code.  Fetch it from the context.
3487    __ ldr(ip, ContextMemOperand(cp, Context::CLOSURE_INDEX));
3488  } else {
3489    DCHECK(closure_scope->is_function_scope());
3490    __ ldr(ip, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
3491  }
3492  PushOperand(ip);
3493}
3494
3495
3496// ----------------------------------------------------------------------------
3497// Non-local control flow support.
3498
3499void FullCodeGenerator::EnterFinallyBlock() {
3500  DCHECK(!result_register().is(r1));
3501  // Store pending message while executing finally block.
3502  ExternalReference pending_message_obj =
3503      ExternalReference::address_of_pending_message_obj(isolate());
3504  __ mov(ip, Operand(pending_message_obj));
3505  __ ldr(r1, MemOperand(ip));
3506  PushOperand(r1);
3507
3508  ClearPendingMessage();
3509}
3510
3511
3512void FullCodeGenerator::ExitFinallyBlock() {
3513  DCHECK(!result_register().is(r1));
3514  // Restore pending message from stack.
3515  PopOperand(r1);
3516  ExternalReference pending_message_obj =
3517      ExternalReference::address_of_pending_message_obj(isolate());
3518  __ mov(ip, Operand(pending_message_obj));
3519  __ str(r1, MemOperand(ip));
3520}
3521
3522
3523void FullCodeGenerator::ClearPendingMessage() {
3524  DCHECK(!result_register().is(r1));
3525  ExternalReference pending_message_obj =
3526      ExternalReference::address_of_pending_message_obj(isolate());
3527  __ LoadRoot(r1, Heap::kTheHoleValueRootIndex);
3528  __ mov(ip, Operand(pending_message_obj));
3529  __ str(r1, MemOperand(ip));
3530}
3531
3532
3533void FullCodeGenerator::DeferredCommands::EmitCommands() {
3534  DCHECK(!result_register().is(r1));
3535  __ Pop(result_register());  // Restore the accumulator.
3536  __ Pop(r1);                 // Get the token.
3537  for (DeferredCommand cmd : commands_) {
3538    Label skip;
3539    __ cmp(r1, Operand(Smi::FromInt(cmd.token)));
3540    __ b(ne, &skip);
3541    switch (cmd.command) {
3542      case kReturn:
3543        codegen_->EmitUnwindAndReturn();
3544        break;
3545      case kThrow:
3546        __ Push(result_register());
3547        __ CallRuntime(Runtime::kReThrow);
3548        break;
3549      case kContinue:
3550        codegen_->EmitContinue(cmd.target);
3551        break;
3552      case kBreak:
3553        codegen_->EmitBreak(cmd.target);
3554        break;
3555    }
3556    __ bind(&skip);
3557  }
3558}
3559
3560#undef __
3561
3562
3563static Address GetInterruptImmediateLoadAddress(Address pc) {
3564  Address load_address = pc - 2 * Assembler::kInstrSize;
3565  if (!FLAG_enable_embedded_constant_pool) {
3566    DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(load_address)));
3567  } else if (Assembler::IsLdrPpRegOffset(Memory::int32_at(load_address))) {
3568    // This is an extended constant pool lookup.
3569    if (CpuFeatures::IsSupported(ARMv7)) {
3570      load_address -= 2 * Assembler::kInstrSize;
3571      DCHECK(Assembler::IsMovW(Memory::int32_at(load_address)));
3572      DCHECK(Assembler::IsMovT(
3573          Memory::int32_at(load_address + Assembler::kInstrSize)));
3574    } else {
3575      load_address -= 4 * Assembler::kInstrSize;
3576      DCHECK(Assembler::IsMovImmed(Memory::int32_at(load_address)));
3577      DCHECK(Assembler::IsOrrImmed(
3578          Memory::int32_at(load_address + Assembler::kInstrSize)));
3579      DCHECK(Assembler::IsOrrImmed(
3580          Memory::int32_at(load_address + 2 * Assembler::kInstrSize)));
3581      DCHECK(Assembler::IsOrrImmed(
3582          Memory::int32_at(load_address + 3 * Assembler::kInstrSize)));
3583    }
3584  } else if (CpuFeatures::IsSupported(ARMv7) &&
3585             Assembler::IsMovT(Memory::int32_at(load_address))) {
3586    // This is a movw / movt immediate load.
3587    load_address -= Assembler::kInstrSize;
3588    DCHECK(Assembler::IsMovW(Memory::int32_at(load_address)));
3589  } else if (!CpuFeatures::IsSupported(ARMv7) &&
3590             Assembler::IsOrrImmed(Memory::int32_at(load_address))) {
3591    // This is a mov / orr immediate load.
3592    load_address -= 3 * Assembler::kInstrSize;
3593    DCHECK(Assembler::IsMovImmed(Memory::int32_at(load_address)));
3594    DCHECK(Assembler::IsOrrImmed(
3595        Memory::int32_at(load_address + Assembler::kInstrSize)));
3596    DCHECK(Assembler::IsOrrImmed(
3597        Memory::int32_at(load_address + 2 * Assembler::kInstrSize)));
3598  } else {
3599    // This is a small constant pool lookup.
3600    DCHECK(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(load_address)));
3601  }
3602  return load_address;
3603}
3604
3605
3606void BackEdgeTable::PatchAt(Code* unoptimized_code,
3607                            Address pc,
3608                            BackEdgeState target_state,
3609                            Code* replacement_code) {
3610  Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc);
3611  Address branch_address = pc_immediate_load_address - Assembler::kInstrSize;
3612  Isolate* isolate = unoptimized_code->GetIsolate();
3613  CodePatcher patcher(isolate, branch_address, 1);
3614  switch (target_state) {
3615    case INTERRUPT:
3616    {
3617      //  <decrement profiling counter>
3618      //   bpl ok
3619      //   ; load interrupt stub address into ip - either of (for ARMv7):
3620      //   ; <small cp load>      |  <extended cp load> |  <immediate load>
3621      //   ldr ip, [pc/pp, #imm]  |   movw ip, #imm     |   movw ip, #imm
3622      //                          |   movt ip, #imm     |   movw ip, #imm
3623      //                          |   ldr  ip, [pp, ip]
3624      //   ; or (for ARMv6):
3625      //   ; <small cp load>      |  <extended cp load> |  <immediate load>
3626      //   ldr ip, [pc/pp, #imm]  |   mov ip, #imm      |   mov ip, #imm
3627      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
3628      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
3629      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
3630      //   blx ip
3631      //  <reset profiling counter>
3632      //  ok-label
3633
3634      // Calculate branch offset to the ok-label - this is the difference
3635      // between the branch address and |pc| (which points at <blx ip>) plus
3636      // kProfileCounterResetSequence instructions
3637      int branch_offset = pc - Instruction::kPCReadOffset - branch_address +
3638                          kProfileCounterResetSequenceLength;
3639      patcher.masm()->b(branch_offset, pl);
3640      break;
3641    }
3642    case ON_STACK_REPLACEMENT:
3643      //  <decrement profiling counter>
3644      //   mov r0, r0 (NOP)
3645      //   ; load on-stack replacement address into ip - either of (for ARMv7):
3646      //   ; <small cp load>      |  <extended cp load> |  <immediate load>
3647      //   ldr ip, [pc/pp, #imm]  |   movw ip, #imm     |   movw ip, #imm
3648      //                          |   movt ip, #imm>    |   movw ip, #imm
3649      //                          |   ldr  ip, [pp, ip]
3650      //   ; or (for ARMv6):
3651      //   ; <small cp load>      |  <extended cp load> |  <immediate load>
3652      //   ldr ip, [pc/pp, #imm]  |   mov ip, #imm      |   mov ip, #imm
3653      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
3654      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
3655      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
3656      //   blx ip
3657      //  <reset profiling counter>
3658      //  ok-label
3659      patcher.masm()->nop();
3660      break;
3661  }
3662
3663  // Replace the call address.
3664  Assembler::set_target_address_at(isolate, pc_immediate_load_address,
3665                                   unoptimized_code, replacement_code->entry());
3666
3667  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
3668      unoptimized_code, pc_immediate_load_address, replacement_code);
3669}
3670
3671
3672BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
3673    Isolate* isolate,
3674    Code* unoptimized_code,
3675    Address pc) {
3676  DCHECK(Assembler::IsBlxIp(Memory::int32_at(pc - Assembler::kInstrSize)));
3677
3678  Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc);
3679  Address branch_address = pc_immediate_load_address - Assembler::kInstrSize;
3680#ifdef DEBUG
3681  Address interrupt_address = Assembler::target_address_at(
3682      pc_immediate_load_address, unoptimized_code);
3683#endif
3684
3685  if (Assembler::IsBranch(Assembler::instr_at(branch_address))) {
3686    DCHECK(interrupt_address ==
3687           isolate->builtins()->InterruptCheck()->entry());
3688    return INTERRUPT;
3689  }
3690
3691  DCHECK(Assembler::IsNop(Assembler::instr_at(branch_address)));
3692
3693  DCHECK(interrupt_address ==
3694         isolate->builtins()->OnStackReplacement()->entry());
3695  return ON_STACK_REPLACEMENT;
3696}
3697
3698
3699}  // namespace internal
3700}  // namespace v8
3701
3702#endif  // V8_TARGET_ARCH_ARM
3703