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