1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM64
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/ast/compile-time-value.h"
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ast/scopes.h"
962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/builtins/builtins-constructor.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
13f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/compilation-info.h"
14f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/compiler.h"
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h"
1662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/full-codegen/full-codegen.h"
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h"
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm64/code-stubs-arm64.h"
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/arm64/frames-arm64.h"
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm64/macro-assembler-arm64.h"
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
26109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define __ ACCESS_MASM(masm())
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass JumpPatchSite BASE_EMBEDDED {
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm), reg_(NoReg) {
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info_emitted_ = false;
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ~JumpPatchSite() {
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (patch_site_.is_bound()) {
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(info_emitted_);
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(reg_.IsNone());
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitJumpIfNotSmi(Register reg, Label* target) {
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This code will be patched by PatchInlinedSmiCode, in ic-arm64.cc.
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    InstructionAccurateScope scope(masm_, 1);
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!info_emitted_);
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(reg.Is64Bits());
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!reg.Is(csp));
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    reg_ = reg;
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&patch_site_);
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ tbz(xzr, 0, target);   // Always taken before patched.
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitJumpIfSmi(Register reg, Label* target) {
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This code will be patched by PatchInlinedSmiCode, in ic-arm64.cc.
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    InstructionAccurateScope scope(masm_, 1);
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!info_emitted_);
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(reg.Is64Bits());
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!reg.Is(csp));
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    reg_ = reg;
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&patch_site_);
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ tbnz(xzr, 0, target);  // Never taken before patched.
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitJumpIfEitherNotSmi(Register reg1, Register reg2, Label* target) {
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UseScratchRegisterScope temps(masm_);
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp = temps.AcquireX();
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Orr(temp, reg1, reg2);
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitJumpIfNotSmi(temp, target);
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitPatchInfo() {
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assembler::BlockPoolsScope scope(masm_);
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    InlineSmiCheckInfo::Emit(masm_, reg_, &patch_site_);
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info_emitted_ = true;
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
82109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  MacroAssembler* masm() { return masm_; }
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MacroAssembler* masm_;
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label patch_site_;
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg_;
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool info_emitted_;
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate code for a JS function. On entry to the function the receiver
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// and arguments have been pushed on the stack left to right. The actual
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// argument count matches the formal parameter count expected by the
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// function.
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The live registers are:
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//   - x1: the JS function object being called (i.e. ourselves).
99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//   - x3: the new target value
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//   - cp: our context.
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//   - fp: our caller's frame pointer.
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//   - jssp: stack pointer.
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//   - lr: return address.
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The function builds a JS frame. See JavaScriptFrameConstants in
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// frames-arm.h for its layout.
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::Generate() {
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompilationInfo* info = info_;
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  profiling_counter_ = isolate()->factory()->NewCell(
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetFunctionPosition(literal());
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ Function compiled by full code generator");
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProfileEntryHookStub::MaybeCallEntryHook(masm_);
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int receiver_offset = info->scope()->num_parameters() * kXRegSize;
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Peek(x10, receiver_offset);
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ AssertNotSmi(x10);
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CompareObjectType(x10, x10, x11, FIRST_JS_RECEIVER_TYPE);
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Assert(ge, kSloppyFunctionExpectsJSReceiverReceiver);
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Open a frame scope to indicate that there is a frame on the stack.
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The MANUAL indicates that the scope shouldn't actually generate code
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to set up the frame because we do it manually below.
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FrameScope frame_scope(masm_, StackFrame::MANUAL);
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This call emits the following sequence in a way that can be patched for
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // code ageing support:
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  Push(lr, fp, cp, x1);
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  Add(fp, jssp, 2 * kPointerSize);
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info->set_prologue_offset(masm_->pc_offset());
134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Prologue(info->GeneratePreagedPrologue());
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Increment invocation count for the function.
137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  {
138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Comment cmnt(masm_, "[ Increment invocation count");
13962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Ldr(x11, FieldMemOperand(x1, JSFunction::kFeedbackVectorOffset));
14062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Ldr(x11, FieldMemOperand(x11, Cell::kValueOffset));
14162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Ldr(x10, FieldMemOperand(
14262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    x11, FeedbackVector::kInvocationCountIndex * kPointerSize +
14362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             FeedbackVector::kHeaderSize));
144f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    __ Add(x10, x10, Operand(Smi::FromInt(1)));
14562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Str(x10, FieldMemOperand(
14662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    x11, FeedbackVector::kInvocationCountIndex * kPointerSize +
14762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             FeedbackVector::kHeaderSize));
148f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
149f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Reserve space on the stack for locals.
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { Comment cmnt(masm_, "[ Allocate locals");
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int locals_count = info->scope()->num_stack_slots();
153109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    OperandStackDepthIncrement(locals_count);
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (locals_count > 0) {
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (locals_count >= 128) {
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label ok;
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(jssp.Is(__ StackPointer()));
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Sub(x10, jssp, locals_count * kPointerSize);
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ CompareRoot(x10, Heap::kRealStackLimitRootIndex);
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ B(hs, &ok);
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ CallRuntime(Runtime::kThrowStackOverflow);
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Bind(&ok);
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(x10, Heap::kUndefinedValueRootIndex);
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (FLAG_optimize_for_size) {
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ PushMultipleTimes(x10 , locals_count);
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        const int kMaxPushes = 32;
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (locals_count >= kMaxPushes) {
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          int loop_iterations = locals_count / kMaxPushes;
171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ Mov(x2, loop_iterations);
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Label loop_header;
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Bind(&loop_header);
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // Do pushes.
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ PushMultipleTimes(x10 , kMaxPushes);
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ Subs(x2, x2, 1);
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ B(ne, &loop_header);
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int remaining = locals_count % kMaxPushes;
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Emit the remaining pushes.
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ PushMultipleTimes(x10 , remaining);
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool function_in_register_x1 = true;
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
188f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (info->scope()->NeedsContext()) {
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Argument to NewContext is the function, which is still in x1.
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment cmnt(masm_, "[ Allocate context");
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool need_write_barrier = true;
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (info->scope()->is_script_scope()) {
194f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      __ Mov(x10, Operand(info->scope()->scope_info()));
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(x1, x10);
196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ CallRuntime(Runtime::kNewScriptContext);
197bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(BailoutId::ScriptContext(),
198bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             BailoutState::TOS_REGISTER);
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // The new target value is not used, clobbering is safe.
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK_NULL(info->scope()->new_target_var());
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (info->scope()->new_target_var() != nullptr) {
203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ Push(x3);  // Preserve new target.
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
20562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (slots <=
20662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          ConstructorBuiltinsAssembler::MaximumFunctionContextSlots()) {
20762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Callable callable = CodeFactory::FastNewFunctionContext(
20862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            isolate(), info->scope()->scope_type());
209f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ Mov(FastNewFunctionContextDescriptor::SlotsRegister(), slots);
21062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ Call(callable.code(), RelocInfo::CODE_TARGET);
21162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // Result of the FastNewFunctionContext builtin is always in new space.
212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        need_write_barrier = false;
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ Push(x1);
21562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ Push(Smi::FromInt(info->scope()->scope_type()));
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ CallRuntime(Runtime::kNewFunctionContext);
217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (info->scope()->new_target_var() != nullptr) {
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ Pop(x3);  // Restore new target.
220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    function_in_register_x1 = false;
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Context is returned in x0.  It replaces the context passed to us.
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // It's saved in the stack and kept live in cp.
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Mov(cp, x0);
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Str(x0, MemOperand(fp, StandardFrameConstants::kContextOffset));
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Copy any necessary parameters into the context.
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int num_parameters = info->scope()->num_parameters();
229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int first_parameter = info->scope()->has_this_declaration() ? -1 : 0;
230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (int i = first_parameter; i < num_parameters; i++) {
231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Variable* var =
232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          (i == -1) ? info->scope()->receiver() : info->scope()->parameter(i);
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (var->IsContextSlot()) {
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            (num_parameters - 1 - i) * kPointerSize;
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Load parameter from stack.
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Ldr(x10, MemOperand(fp, parameter_offset));
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Store it in the context.
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        MemOperand target = ContextMemOperand(cp, var->index());
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Str(x10, target);
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Update the write barrier.
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (need_write_barrier) {
244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ RecordWriteContextSlot(cp, static_cast<int>(target.offset()), x10,
245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    x11, kLRHasBeenSaved, kDontSaveFPRegs);
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (FLAG_debug_code) {
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Label done;
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ JumpIfInNewSpace(cp, &done);
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Abort(kExpectedNewSpaceObject);
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ bind(&done);
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Register holding this function and new target are both trashed in case we
257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // bailout here. But since that can happen only when new target is not used
258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // and we allocate a context, the value of |function_in_register| is correct.
259bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(BailoutId::FunctionContext(),
260bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                         BailoutState::NO_REGISTERS);
261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
26262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // We don't support new.target and rest parameters here.
26362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_NULL(info->scope()->new_target_var());
26462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_NULL(info->scope()->rest_parameter());
26562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_NULL(info->scope()->this_function_var());
266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Variable* arguments = info->scope()->arguments();
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (arguments != NULL) {
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Function uses arguments object.
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment cmnt(masm_, "[ Allocate arguments object");
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!function_in_register_x1) {
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Load this again, if it's used by the local context below.
273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ Ldr(x1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
275109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (is_strict(language_mode()) || !has_simple_parameters()) {
27662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Callable callable = CodeFactory::FastNewStrictArguments(isolate());
27762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Call(callable.code(), RelocInfo::CODE_TARGET);
27862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      RestoreContext();
279109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    } else if (literal()->has_duplicate_parameters()) {
280109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Push(x1);
281109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ CallRuntime(Runtime::kNewSloppyArguments_Generic);
282109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    } else {
28362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Callable callable = CodeFactory::FastNewSloppyArguments(isolate());
28462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Call(callable.code(), RelocInfo::CODE_TARGET);
28562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      RestoreContext();
286109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SetVar(arguments, x0, x1, x2);
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_trace) {
292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallRuntime(Runtime::kTraceEnter);
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Visit the declarations and body.
296bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(BailoutId::FunctionEntry(),
297bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                         BailoutState::NO_REGISTERS);
2983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment cmnt(masm_, "[ Declarations");
3003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    VisitDeclarations(scope()->declarations());
3013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Assert that the declarations do not use ICs. Otherwise the debugger
3043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // won't be able to redirect a PC at an IC to the correct IC in newly
3053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // recompiled code.
3063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(0, ic_total_count_);
307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
3093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Comment cmnt(masm_, "[ Stack check");
310bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(BailoutId::Declarations(),
311bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           BailoutState::NO_REGISTERS);
3123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Label ok;
3133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(jssp.Is(__ StackPointer()));
3143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ CompareRoot(jssp, Heap::kStackLimitRootIndex);
3153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ B(hs, &ok);
3163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    PredictableCodeSizeScope predictable(masm_,
3173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                         Assembler::kCallSizeWithRelocation);
3183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ Call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET);
3193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ Bind(&ok);
3203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
3233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Comment cmnt(masm_, "[ Body");
3243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(loop_depth() == 0);
3253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    VisitStatements(literal()->body());
3263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(loop_depth() == 0);
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Always emit a 'return undefined' in case control fell off the end of
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the body.
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { Comment cmnt(masm_, "[ return <undefined>;");
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(x0, Heap::kUndefinedValueRootIndex);
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitReturnSequence();
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Force emission of the pools, so they don't get emitted in the middle
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // of the back edge table.
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm()->CheckVeneerPool(true, false);
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm()->CheckConstPool(true, false);
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
342c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid FullCodeGenerator::ClearAccumulator() { __ Mov(x0, Smi::kZero); }
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mov(x2, Operand(profiling_counter_));
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ldr(x3, FieldMemOperand(x2, Cell::kValueOffset));
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Subs(x3, x3, Smi::FromInt(delta));
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Str(x3, FieldMemOperand(x2, Cell::kValueOffset));
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitProfilingCounterReset() {
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int reset_value = FLAG_interrupt_budget;
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mov(x2, Operand(profiling_counter_));
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mov(x3, Smi::FromInt(reset_value));
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Str(x3, FieldMemOperand(x2, Cell::kValueOffset));
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Label* back_edge_target) {
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(jssp.Is(__ StackPointer()));
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ Back edge bookkeeping");
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Block literal pools whilst emitting back edge code.
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler::BlockPoolsScope block_const_pool(masm_);
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label ok;
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(back_edge_target->is_bound());
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We want to do a round rather than a floor of distance/kCodeSizeMultiplier
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to reduce the absolute error due to the integer division. To do that,
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // we add kCodeSizeMultiplier/2 to the distance (equivalent to adding 0.5 to
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the result).
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int distance =
374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      static_cast<int>(masm_->SizeOfCodeGeneratedSince(back_edge_target) +
375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       kCodeSizeMultiplier / 2);
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int weight = Min(kMaxBackEdgeWeight,
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Max(1, distance / kCodeSizeMultiplier));
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitProfilingCounterDecrement(weight);
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(pl, &ok);
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Record a mapping of this PC offset to the OSR id.  This is used to find
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the AST id from the unoptimized code in order to use it as a key into
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the deoptimization input data found in the optimized code.
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordBackEdge(stmt->OsrEntryId());
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitProfilingCounterReset();
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&ok);
390bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Record a mapping of the OSR id to this PC.  This is used if the OSR
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // entry becomes the target of a bailout.  We don't expect it to be, but
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // we want it to work if it is.
394bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
397109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
398109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    bool is_tail_call) {
399109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Pretend that the exit is a backwards jump to the entry.
400109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int weight = 1;
401109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (info_->ShouldSelfOptimize()) {
402109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    weight = FLAG_interrupt_budget / FLAG_self_opt_count;
403109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
404109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int distance = masm_->pc_offset() + kCodeSizeMultiplier / 2;
405109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    weight = Min(kMaxBackEdgeWeight, Max(1, distance / kCodeSizeMultiplier));
406109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
407109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  EmitProfilingCounterDecrement(weight);
408109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label ok;
409109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ B(pl, &ok);
410109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Don't need to save result register if we are going to do a tail call.
411109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!is_tail_call) {
412109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Push(x0);
413109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
414109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
415109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!is_tail_call) {
416109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Pop(x0);
417109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
418109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  EmitProfilingCounterReset();
419109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Bind(&ok);
420109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitReturnSequence() {
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ Return sequence");
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (return_label_.is_bound()) {
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ B(&return_label_);
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Bind(&return_label_);
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_trace) {
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Push the return value on the stack as the parameter.
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Runtime::TraceExit returns its parameter in x0.
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(result_register());
434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ CallRuntime(Runtime::kTraceExit);
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(x0.Is(result_register()));
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
437109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    EmitProfilingCounterHandlingForReturnSequence(false);
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SetReturnPosition(literal());
440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const Register& current_sp = __ StackPointer();
441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Nothing ensures 16 bytes alignment here.
442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!current_sp.Is(csp));
443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Mov(current_sp, fp);
444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ldp(fp, lr, MemOperand(current_sp, 2 * kXRegSize, PostIndex));
445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Drop the arguments and receiver and return.
446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // TODO(all): This implementation is overkill as it supports 2**31+1
447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // arguments, consider how to improve it without creating a security
448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // hole.
449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ldr_pcrel(ip0, (3 * kInstructionSize) >> kLoadLiteralScaleLog2);
450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Add(current_sp, current_sp, ip0);
451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ret();
452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int32_t arg_count = info_->scope()->num_parameters() + 1;
453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ dc64(kXRegSize * arg_count);
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
457bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid FullCodeGenerator::RestoreContext() {
458bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
459bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  codegen()->GetVar(result_register(), var);
464109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  codegen()->PushOperand(result_register());
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Root values have no side effects.
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Heap::RootListIndex index) const {
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(result_register(), index);
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::Plug(
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Heap::RootListIndex index) const {
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(result_register(), index);
482109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  codegen()->PushOperand(result_register());
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_label_,
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          false_label_);
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (index == Heap::kUndefinedValueRootIndex ||
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      index == Heap::kNullValueRootIndex ||
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      index == Heap::kFalseValueRootIndex) {
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (false_label_ != fall_through_) __ B(false_label_);
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (index == Heap::kTrueValueRootIndex) {
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (true_label_ != fall_through_) __ B(true_label_);
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(result_register(), index);
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    codegen()->DoTest(this);
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Object> lit) const {
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mov(result_register(), Operand(lit));
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Immediates cannot be pushed directly.
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mov(result_register(), Operand(lit));
515109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  codegen()->PushOperand(result_register());
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          true,
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          true_label_,
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          false_label_);
52462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(lit->IsNullOrUndefined(isolate()) || !lit->IsUndetectable());
52562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (lit->IsNullOrUndefined(isolate()) || lit->IsFalse(isolate())) {
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (false_label_ != fall_through_) __ B(false_label_);
52713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (true_label_ != fall_through_) __ B(true_label_);
529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (lit->IsString()) {
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (String::cast(*lit)->length() == 0) {
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (false_label_ != fall_through_) __ B(false_label_);
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (true_label_ != fall_through_) __ B(true_label_);
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (lit->IsSmi()) {
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (Smi::cast(*lit)->value() == 0) {
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (false_label_ != fall_through_) __ B(false_label_);
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (true_label_ != fall_through_) __ B(true_label_);
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // For simplicity we always test the accumulator register.
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Mov(result_register(), Operand(lit));
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    codegen()->DoTest(this);
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count,
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                       Register reg) const {
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(count > 0);
552109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (count > 1) codegen()->DropOperands(count - 1);
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Poke(reg, 0);
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            Label* materialize_false) const {
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(materialize_true == materialize_false);
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(materialize_true);
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* materialize_true,
566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* materialize_false) const {
567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(materialize_true);
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(&done);
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(materialize_false);
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&done);
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::Plug(
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* materialize_true,
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* materialize_false) const {
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(materialize_true);
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(x10, Heap::kTrueValueRootIndex);
583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(&done);
584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(materialize_false);
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(x10, Heap::kFalseValueRootIndex);
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&done);
587109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  codegen()->PushOperand(x10);
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true,
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label* materialize_false) const {
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(materialize_true == true_label_);
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(materialize_false == false_label_);
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap::RootListIndex value_root_index =
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(result_register(), value_root_index);
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const {
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap::RootListIndex value_root_index =
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(x10, value_root_index);
609109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  codegen()->PushOperand(x10);
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::TestContext::Plug(bool flag) const {
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          true,
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          true_label_,
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          false_label_);
618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (flag) {
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (true_label_ != fall_through_) {
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ B(true_label_);
621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (false_label_ != fall_through_) {
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ B(false_label_);
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::DoTest(Expression* condition,
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* if_true,
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* if_false,
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* fall_through) {
6343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(ic, condition->test_id());
636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Split(eq, if_true, if_false, fall_through);
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// If (cond), branch to if_true.
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// If (!cond), branch to if_false.
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// fall_through is used as an optimization in cases where only one branch
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// instruction is necessary.
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::Split(Condition cond,
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* if_true,
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* if_false,
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* fall_through) {
649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (if_false == fall_through) {
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ B(cond, if_true);
651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (if_true == fall_through) {
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(if_false != fall_through);
653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ B(NegateCondition(cond), if_false);
654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ B(cond, if_true);
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ B(if_false);
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) {
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Offset is negative because higher indexes are at lower addresses.
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int offset = -var->index() * kXRegSize;
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Adjust by a (parameter or local) base offset.
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (var->IsParameter()) {
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    offset += JavaScriptFrameConstants::kLocal0Offset;
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return MemOperand(fp, offset);
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (var->IsContextSlot()) {
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int context_chain_length = scope()->ContextChainLength(var->scope());
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadContext(scratch, context_chain_length);
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return ContextMemOperand(scratch, var->index());
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return StackOperand(var);
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) {
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Use destination as scratch.
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemOperand location = VarOperand(var, dest);
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ldr(dest, location);
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::SetVar(Variable* var,
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register src,
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register scratch0,
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register scratch1) {
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(src, scratch0, scratch1));
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemOperand location = VarOperand(var, scratch0);
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Str(src, location);
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emit the write barrier code if the location is in the heap.
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (var->IsContextSlot()) {
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // scratch0 contains the correct context.
705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ RecordWriteContextSlot(scratch0, static_cast<int>(location.offset()),
706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              src, scratch1, kLRHasBeenSaved, kDontSaveFPRegs);
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     bool should_normalize,
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label* if_true,
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label* if_false) {
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Only prepare for bailouts before splits if we're in a test
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // context. Otherwise, we let the Visit function deal with the
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // preparation to avoid preparing with the same AST id twice.
718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!context()->IsTest()) return;
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(all): Investigate to see if there is something to work on here.
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label skip;
722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (should_normalize) {
723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ B(&skip);
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
725bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (should_normalize) {
727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(x0, Heap::kTrueValueRootIndex);
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Split(eq, if_true, if_false, NULL);
729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Bind(&skip);
730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The variable in the declaration always resides in the current function
736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // context.
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, scope()->ContextChainLength(variable->scope()));
738109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (FLAG_debug_code) {
739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check that we're not inside a with or catch context.
740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Ldr(x1, FieldMemOperand(cp, HeapObject::kMapOffset));
741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(x1, Heap::kWithContextMapRootIndex);
742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(ne, kDeclarationInWithContext);
743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(x1, Heap::kCatchContextMapRootIndex);
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(ne, kDeclarationInCatchContext);
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitVariableDeclaration(
750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VariableDeclaration* declaration) {
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VariableProxy* proxy = declaration->proxy();
752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Variable* variable = proxy->var();
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (variable->location()) {
754f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case VariableLocation::UNALLOCATED: {
755bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      DCHECK(!variable->binding_needs_init());
75662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      globals_->Add(variable->name(), zone());
75762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      FeedbackSlot slot = proxy->VariableFeedbackSlot();
758f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK(!slot.IsInvalid());
759f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
760bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      globals_->Add(isolate()->factory()->undefined_value(), zone());
76162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      globals_->Add(isolate()->factory()->undefined_value(), zone());
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
763f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::PARAMETER:
765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::LOCAL:
766f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (variable->binding_needs_init()) {
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment cmnt(masm_, "[ VariableDeclaration");
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ LoadRoot(x10, Heap::kTheHoleValueRootIndex);
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Str(x10, StackOperand(variable));
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
773014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::CONTEXT:
774f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (variable->binding_needs_init()) {
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment cmnt(masm_, "[ VariableDeclaration");
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        EmitDebugCheckDeclarationContext(variable);
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ LoadRoot(x10, Heap::kTheHoleValueRootIndex);
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Str(x10, ContextMemOperand(cp, variable->index()));
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // No write barrier since the_hole_value is in old space.
780bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
78462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VariableLocation::LOOKUP:
785f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case VariableLocation::MODULE:
786f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UNREACHABLE();
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitFunctionDeclaration(
792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FunctionDeclaration* declaration) {
793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VariableProxy* proxy = declaration->proxy();
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Variable* variable = proxy->var();
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (variable->location()) {
796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::UNALLOCATED: {
79762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      globals_->Add(variable->name(), zone());
79862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      FeedbackSlot slot = proxy->VariableFeedbackSlot();
79962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      DCHECK(!slot.IsInvalid());
80062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
80162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
80262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // We need the slot where the literals array lives, too.
80362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      slot = declaration->fun()->LiteralFeedbackSlot();
804f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK(!slot.IsInvalid());
805f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
80662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<SharedFunctionInfo> function =
808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Check for stack overflow exception.
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (function.is_null()) return SetStackOverflow();
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      globals_->Add(function, zone());
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::PARAMETER:
816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::LOCAL: {
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ Function Declaration");
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(declaration->fun());
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Str(result_register(), StackOperand(variable));
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::CONTEXT: {
824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ Function Declaration");
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitDebugCheckDeclarationContext(variable);
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(declaration->fun());
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Str(result_register(), ContextMemOperand(cp, variable->index()));
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int offset = Context::SlotOffset(variable->index());
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // We know that we have written a function, which is not a smi.
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ RecordWriteContextSlot(cp,
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                offset,
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                result_register(),
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                x2,
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                kLRHasBeenSaved,
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                kDontSaveFPRegs,
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                EMIT_REMEMBERED_SET,
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                OMIT_SMI_CHECK);
838bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
84262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VariableLocation::LOOKUP:
843f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case VariableLocation::MODULE:
844f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UNREACHABLE();
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Call the runtime to declare the globals.
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mov(x11, Operand(pairs));
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register flags = xzr;
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (Smi::FromInt(DeclareGlobalsFlags())) {
854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    flags = x10;
855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mov(flags, Smi::FromInt(DeclareGlobalsFlags()));
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
85762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ EmitLoadFeedbackVector(x12);
858f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ Push(x11, flags, x12);
859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CallRuntime(Runtime::kDeclareGlobals);
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return value is ignored.
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ASM_LOCATION("FullCodeGenerator::VisitSwitchStatement");
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ SwitchStatement");
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Breakable nested_statement(this, stmt);
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetStatementPosition(stmt);
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Keep the switch value on the stack until a case matches.
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(stmt->tag());
872bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<CaseClause*>* clauses = stmt->cases();
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label next_test;  // Recycled for each test.
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compile all the tests with branches to their bodies.
879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < clauses->length(); i++) {
880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CaseClause* clause = clauses->at(i);
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    clause->body_target()->Unuse();
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The default is not a test, but remember it as final fall through.
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (clause->is_default()) {
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      default_clause = clause;
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      continue;
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment cmnt(masm_, "[ Case comparison");
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Bind(&next_test);
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    next_test.Unuse();
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Compile the label expression.
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VisitForAccumulatorValue(clause->label());
895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Perform the comparison as if via '==='.
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Peek(x1, 0);   // Switch value.
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JumpPatchSite patch_site(masm_);
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (ShouldInlineSmiCase(Token::EQ_STRICT)) {
901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label slow_case;
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      patch_site.EmitJumpIfEitherNotSmi(x0, x1, &slow_case);
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Cmp(x1, x0);
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ B(ne, &next_test);
905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Drop(1);  // Switch value is no longer needed.
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ B(clause->body_target());
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Bind(&slow_case);
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Record position before stub call for type feedback.
911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SetExpressionPosition(clause);
912109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Handle<Code> ic =
913109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallIC(ic, clause->CompareId());
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patch_site.EmitPatchInfo();
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label skip;
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ B(&skip);
919bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfNotRoot(x0, Heap::kTrueValueRootIndex, &next_test);
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Drop(1);
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ B(clause->body_target());
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Bind(&skip);
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Cbnz(x0, &next_test);
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Drop(1);  // Switch value is no longer needed.
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ B(clause->body_target());
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Discard the test value and jump to the default if present, otherwise to
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the end of the statement.
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&next_test);
933109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DropOperands(1);  // Switch value is no longer needed.
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (default_clause == NULL) {
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ B(nested_statement.break_label());
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ B(default_clause->body_target());
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compile all the case bodies.
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < clauses->length(); i++) {
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment cmnt(masm_, "[ Case body");
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CaseClause* clause = clauses->at(i);
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Bind(clause->body_target());
945bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VisitStatements(clause->statements());
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(nested_statement.break_label());
950bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ASM_LOCATION("FullCodeGenerator::VisitForInStatement");
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ ForInStatement");
957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetStatementPosition(stmt, SKIP_BREAK);
958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
95962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  FeedbackSlot slot = stmt->ForInFeedbackSlot();
960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(all): This visitor probably needs better comments and a revisit.
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
963109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Get the object to enumerate over.
964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionAsStatementPosition(stmt->enumerable());
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(stmt->enumerable());
9663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  OperandStackDepthIncrement(5);
9673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
9683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label loop, exit;
9693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Iteration loop_statement(this, stmt);
9703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  increment_loop_depth();
971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
972109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // If the object is null or undefined, skip over the loop, otherwise convert
973109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // it to a JS receiver.  See ECMA-262 version 5, section 12.6.4.
974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label convert, done_convert;
975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(x0, &convert);
976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ JumpIfObjectType(x0, x10, x11, FIRST_JS_RECEIVER_TYPE, &done_convert, ge);
977109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ JumpIfRoot(x0, Heap::kNullValueRootIndex, &exit);
978109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex, &exit);
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&convert);
980c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Call(isolate()->builtins()->ToObject(), RelocInfo::CODE_TARGET);
981f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RestoreContext();
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&done_convert);
983bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(x0);
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
986bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Check cache validity in generated code. If we cannot guarantee cache
987bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // validity, call the runtime system to check cache validity or get the
988bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // property names in a fixed array. Note: Proxies never have an enum cache,
989bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // so will always take the slow path.
990109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label call_runtime;
991109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CheckEnumCache(x0, x15, x10, x11, x12, x13, &call_runtime);
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The enum cache is valid.  Load the map of the object being
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // iterated over and use the cache for the iteration.
995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label use_cache;
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset));
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(&use_cache);
998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the set of properties to enumerate.
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&call_runtime);
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(x0);  // Duplicate the enumerable object on the stack.
1002109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CallRuntime(Runtime::kForInEnumerate);
1003bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If we got a map from the runtime call, we can do a fast
1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // modification check. Otherwise, we got a fixed array, and we have
1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to do a slow check.
1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label fixed_array, no_descriptors;
1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ldr(x2, FieldMemOperand(x0, HeapObject::kMapOffset));
1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfNotRoot(x2, Heap::kMetaMapRootIndex, &fixed_array);
1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We got a map in register x0. Get the enumeration cache from it.
1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&use_cache);
1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ EnumLengthUntagged(x1, x0);
1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cbz(x1, &no_descriptors);
1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadInstanceDescriptors(x0, x2);
1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ldr(x2, FieldMemOperand(x2, DescriptorArray::kEnumCacheOffset));
1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ldr(x2,
1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldMemOperand(x2, DescriptorArray::kEnumCacheBridgeCacheOffset));
1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set up the four remaining stack slots.
1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTag(x1);
1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Map, enumeration cache, enum cache length, zero (both last as smis).
1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(x0, x2, x1, xzr);
1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(&loop);
1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&no_descriptors);
1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Drop(1);
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(&exit);
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We got a fixed array in register x0. Iterate through that.
1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&fixed_array);
1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Mov(x1, Smi::FromInt(1));  // Smi(1) indicates slow check.
1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ldr(x2, FieldMemOperand(x0, FixedArray::kLengthOffset));
1038109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Push(x1, x0, x2);  // Smi and array, fixed array length (as smi).
1039bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
1040109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Push(xzr);  // Initial index.
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generate code for doing the condition check.
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&loop);
1044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionAsStatementPosition(stmt->each());
1045958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the current count to x0, load the length to x1.
1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PeekPair(x0, x1, 0);
1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cmp(x0, x1);  // Compare to the array length.
1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(hs, loop_statement.break_label());
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1051f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Get the current entry of the array into register x0.
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Peek(x10, 2 * kXRegSize);
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Add(x10, x10, Operand::UntagSmiAndScale(x0, kPointerSizeLog2));
1054f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ Ldr(x0, MemOperand(x10, FixedArray::kHeaderSize - kHeapObjectTag));
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the expected map from the stack or a smi in the
1057f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // permanent slow case into register x2.
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Peek(x2, 3 * kXRegSize);
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if the expected map still matches that of the enumerable.
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If not, we may have to filter the key.
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label update_each;
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Peek(x1, 4 * kXRegSize);
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ldr(x11, FieldMemOperand(x1, HeapObject::kMapOffset));
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cmp(x11, x2);
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(eq, &update_each);
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // We need to filter the key, record slow-path here.
10693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int const vector_index = SmiFromSlot(slot)->value();
107062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ EmitLoadFeedbackVector(x3);
107162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Mov(x10, Operand(FeedbackVector::MegamorphicSentinel(isolate())));
1072f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ Str(x10, FieldMemOperand(x3, FixedArray::OffsetOfElementAt(vector_index)));
1073109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1074f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // x0 contains the key. The receiver in x1 is the second argument to the
1075c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // ForInFilter. ForInFilter returns undefined if the receiver doesn't
1076f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // have the key or returns the name-converted key.
1077c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Call(isolate()->builtins()->ForInFilter(), RelocInfo::CODE_TARGET);
1078f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RestoreContext();
1079bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
1080f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex);
1081f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ B(eq, loop_statement.continue_label());
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update the 'each' property or variable from the possibly filtered
1084f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // entry in register x0.
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&update_each);
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Perform the assignment as if via '='.
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { EffectContext context(this);
1088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
1089bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
1093bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generate code for the body of the loop.
1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Visit(stmt->body());
1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generate code for going to the next element by incrementing
1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the index (smi) stored on top of the stack.
1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(loop_statement.continue_label());
1100f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  PrepareForBailoutForId(stmt->IncrementId(), BailoutState::NO_REGISTERS);
1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(all): We could use a callee saved register to avoid popping.
1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(x0);
1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Add(x0, x0, Smi::FromInt(1));
1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(x0);
1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBackEdgeBookkeeping(stmt, &loop);
1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(&loop);
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Remove the pointers stored on the stack.
1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(loop_statement.break_label());
1111109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DropOperands(5);
1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Exit and decrement the loop depth.
1114bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&exit);
1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  decrement_loop_depth();
1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
112062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                          FeedbackSlot slot) {
1121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(NeedsHomeObject(initializer));
1122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Peek(StoreDescriptor::ReceiverRegister(), 0);
1123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Peek(StoreDescriptor::ValueRegister(), offset * kPointerSize);
1124f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CallStoreIC(slot, isolate()->factory()->home_object_symbol());
1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer,
1128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                     int offset,
112962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                     FeedbackSlot slot) {
1130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(NeedsHomeObject(initializer));
1131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Move(StoreDescriptor::ReceiverRegister(), x0);
1132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Peek(StoreDescriptor::ValueRegister(), offset * kPointerSize);
1133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CallStoreIC(slot, isolate()->factory()->home_object_symbol());
1134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
1137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                         TypeofMode typeof_mode) {
1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Record position before possible IC call.
1139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionPosition(proxy);
1140bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Variable* var = proxy->var();
1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
114362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Two cases: global variables and all other types of variables.
1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (var->location()) {
1145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::UNALLOCATED: {
1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "Global variable");
1147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      EmitGlobalVariableLoad(proxy, typeof_mode);
1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context()->Plug(x0);
1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::PARAMETER:
1153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::LOCAL:
1154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::CONTEXT: {
1155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode);
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, var->IsContextSlot()
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              ? "Context variable"
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              : "Stack variable");
1159c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (proxy->hole_check_mode() == HoleCheckMode::kRequired) {
1160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        // Throw a reference error when using an uninitialized let/const
1161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        // binding in harmony mode.
1162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Label done;
1163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        GetVar(x0, var);
1164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &done);
1165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ Mov(x0, Operand(var->name()));
1166f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ Push(x0);
1167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ CallRuntime(Runtime::kThrowReferenceError);
1168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ Bind(&done);
1169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        context()->Plug(x0);
1170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context()->Plug(var);
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
117662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VariableLocation::LOOKUP:
1177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case VariableLocation::MODULE:
1178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UNREACHABLE();
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
1184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Expression* expression = (property == NULL) ? NULL : property->value();
1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expression == NULL) {
1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(x10, Heap::kNullValueRootIndex);
1187109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(x10);
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VisitForStackValue(expression);
1190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (NeedsHomeObject(expression)) {
1191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
1192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             property->kind() == ObjectLiteral::Property::SETTER);
1193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
1194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      EmitSetHomeObject(expression, offset, property->GetSlot());
1195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ ObjectLiteral");
1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
120362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<BoilerplateDescription> constant_properties =
120462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      expr->GetOrBuildConstantProperties(isolate());
1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ldr(x3, MemOperand(fp,  JavaScriptFrameConstants::kFunctionOffset));
120662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Mov(x2, SmiFromSlot(expr->literal_slot()));
1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mov(x1, Operand(constant_properties));
1208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int flags = expr->ComputeFlags();
1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mov(x0, Smi::FromInt(flags));
1210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (MustCreateObjectLiteralWithRuntime(expr)) {
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(x3, x2, x1, x0);
1212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallRuntime(Runtime::kCreateObjectLiteral);
1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
121462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Callable callable = CodeFactory::FastCloneShallowObject(
121562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate(), expr->properties_count());
121662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Call(callable.code(), RelocInfo::CODE_TARGET);
1217bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    RestoreContext();
1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1219bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If result_saved is true the result is on top of the stack.  If
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // result_saved is false the result is in x0.
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool result_saved = false;
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AccessorTable accessor_table(zone());
122662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  for (int i = 0; i < expr->properties()->length(); i++) {
122762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ObjectLiteral::Property* property = expr->properties()->at(i);
122862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(!property->is_computed_name());
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (property->IsCompileTimeValue()) continue;
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Literal* key = property->key()->AsLiteral();
1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Expression* value = property->value();
1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!result_saved) {
1234109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(x0);  // Save result on stack
1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      result_saved = true;
1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (property->kind()) {
123862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case ObjectLiteral::Property::SPREAD:
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case ObjectLiteral::Property::CONSTANT:
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        UNREACHABLE();
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Fall through.
1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case ObjectLiteral::Property::COMPUTED:
1245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // It is safe to use [[Put]] here because the boilerplate already
1246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // contains computed properties with an uninitialized value.
1247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if (key->IsStringLiteral()) {
1248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          DCHECK(key->IsPropertyName());
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (property->emit_store()) {
1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            VisitForAccumulatorValue(value);
1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            DCHECK(StoreDescriptor::ValueRegister().is(x0));
1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ Peek(StoreDescriptor::ReceiverRegister(), 0);
125362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            CallStoreIC(property->GetSlot(0), key->value(), true);
1254bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
1255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            if (NeedsHomeObject(value)) {
1257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
1258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            }
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else {
1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            VisitForEffect(value);
1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          }
1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
1264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ Peek(x0, 0);
1265109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(x0);
1266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        VisitForStackValue(key);
1267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        VisitForStackValue(value);
1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (property->emit_store()) {
1269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (NeedsHomeObject(value)) {
1270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            EmitSetHomeObject(value, 2, property->GetSlot());
1271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
1272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ Mov(x0, Smi::FromInt(SLOPPY));  // Language mode
1273109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          PushOperand(x0);
1274109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          CallRuntimeWithOperands(Runtime::kSetProperty);
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
1276109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          DropOperands(3);
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case ObjectLiteral::Property::PROTOTYPE:
1280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(property->emit_store());
1281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Duplicate receiver on stack.
1282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ Peek(x0, 0);
1283109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(x0);
1284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        VisitForStackValue(value);
1285109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
128662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        PrepareForBailoutForId(expr->GetIdForPropertySet(i),
1287bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                               BailoutState::NO_REGISTERS);
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case ObjectLiteral::Property::GETTER:
1290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (property->emit_store()) {
129113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          AccessorTable::Iterator it = accessor_table.lookup(key);
129262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          it->second->bailout_id = expr->GetIdForPropertySet(i);
129313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          it->second->getter = property;
1294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case ObjectLiteral::Property::SETTER:
1297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (property->emit_store()) {
129813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          AccessorTable::Iterator it = accessor_table.lookup(key);
129962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          it->second->bailout_id = expr->GetIdForPropertySet(i);
130013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          it->second->setter = property;
1301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emit code to define accessors, using only a single call to the runtime for
1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // each pair of corresponding getters and setters.
1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (AccessorTable::Iterator it = accessor_table.begin();
1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       it != accessor_table.end();
1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       ++it) {
131113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    __ Peek(x10, 0);  // Duplicate receiver.
131213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    PushOperand(x10);
131313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    VisitForStackValue(it->first);
131413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    EmitAccessor(it->second->getter);
131513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    EmitAccessor(it->second->setter);
131613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    __ Mov(x10, Smi::FromInt(NONE));
131713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    PushOperand(x10);
131813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
131913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
1320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (result_saved) {
1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context()->PlugTOS();
1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context()->Plug(x0);
1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ ArrayLiteral");
1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
133362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<ConstantElementsPair> constant_elements =
133462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      expr->GetOrBuildConstantElements(isolate());
1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
133762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Mov(x2, SmiFromSlot(expr->literal_slot()));
1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mov(x1, Operand(constant_elements));
1339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (MustCreateArrayLiteralWithRuntime(expr)) {
1340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Mov(x0, Smi::FromInt(expr->ComputeFlags()));
1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(x3, x2, x1, x0);
1342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallRuntime(Runtime::kCreateArrayLiteral);
1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
134462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Callable callable =
134562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        CodeFactory::FastCloneShallowArray(isolate(), TRACK_ALLOCATION_SITE);
134662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Call(callable.code(), RelocInfo::CODE_TARGET);
1347f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    RestoreContext();
1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1349bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool result_saved = false;  // Is the result saved to the stack?
1352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneList<Expression*>* subexprs = expr->values();
1353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int length = subexprs->length();
1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emit code to evaluate all the non-constant subexpressions and to store
1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // them into the newly cloned array.
1357f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  for (int array_index = 0; array_index < length; array_index++) {
1358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Expression* subexpr = subexprs->at(array_index);
1359109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(!subexpr->IsSpread());
1360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If the subexpression is a literal or a simple materialized literal it
1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // is already set in the cloned array.
1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!result_saved) {
1366109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(x0);
1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      result_saved = true;
1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VisitForAccumulatorValue(subexpr);
1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Mov(StoreDescriptor::NameRegister(), Smi::FromInt(array_index));
1372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Peek(StoreDescriptor::ReceiverRegister(), 0);
1373f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    CallKeyedStoreIC(expr->LiteralFeedbackSlot());
1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1375bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(expr->GetIdForElement(array_index),
1376bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           BailoutState::NO_REGISTERS);
1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (result_saved) {
1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context()->PlugTOS();
1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context()->Plug(x0);
1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ Assignment");
1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Property* property = expr->target()->AsProperty();
1393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LhsKind assign_type = Property::GetAssignType(property);
1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Evaluate LHS expression.
1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (assign_type) {
1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case VARIABLE:
1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Nothing to do here.
1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case NAMED_PROPERTY:
1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (expr->is_compound()) {
1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // We need the receiver both on the stack and in the register.
1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->obj());
1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Peek(LoadDescriptor::ReceiverRegister(), 0);
1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->obj());
1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case KEYED_PROPERTY:
1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (expr->is_compound()) {
1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->obj());
1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->key());
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Peek(LoadDescriptor::ReceiverRegister(), 1 * kPointerSize);
1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Peek(LoadDescriptor::NameRegister(), 0);
1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->obj());
1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->key());
1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
142062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case NAMED_SUPER_PROPERTY:
142162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case KEYED_SUPER_PROPERTY:
142262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      UNREACHABLE();
142362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For compound assignments we need another deoptimization point after the
1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // variable/property load.
1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expr->is_compound()) {
1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    { AccumulatorValueContext context(this);
1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      switch (assign_type) {
1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case VARIABLE:
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          EmitVariableLoad(expr->target()->AsVariableProxy());
1433bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case NAMED_PROPERTY:
1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          EmitNamedPropertyLoad(property);
1437bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          PrepareForBailoutForId(property->LoadId(),
1438bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                 BailoutState::TOS_REGISTER);
1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case KEYED_PROPERTY:
1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          EmitKeyedPropertyLoad(property);
1442bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          PrepareForBailoutForId(property->LoadId(),
1443bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                 BailoutState::TOS_REGISTER);
1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
144562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case NAMED_SUPER_PROPERTY:
144662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case KEYED_SUPER_PROPERTY:
144762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          UNREACHABLE();
144862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          break;
1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Token::Value op = expr->binary_op();
1453109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(x0);  // Left operand goes on the stack.
1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VisitForAccumulatorValue(expr->value());
1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AccumulatorValueContext context(this);
1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (ShouldInlineSmiCase(op)) {
1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitInlineSmiBinaryOp(expr->binary_operation(),
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            op,
1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            expr->target(),
1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            expr->value());
1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      EmitBinaryOp(expr->binary_operation(), op);
1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Deoptimization point in case the binary operation may have side effects.
1467bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VisitForAccumulatorValue(expr->value());
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionPosition(expr);
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Store the value.
1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (assign_type) {
1476c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    case VARIABLE: {
1477c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      VariableProxy* proxy = expr->target()->AsVariableProxy();
1478c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(),
1479c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                             proxy->hole_check_mode());
1480bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context()->Plug(x0);
1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1483c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case NAMED_PROPERTY:
1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitNamedPropertyAssignment(expr);
1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case KEYED_PROPERTY:
1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitKeyedPropertyAssignment(expr);
1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
149062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case NAMED_SUPER_PROPERTY:
149162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case KEYED_SUPER_PROPERTY:
149262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      UNREACHABLE();
149362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Token::Value op,
1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Expression* left_expr,
1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Expression* right_expr) {
1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, both_smis, stub_call;
1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the arguments.
1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register left = x1;
1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register right = x0;
1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = x0;
1508109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(left);
1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Perform combined smi check on both operands.
1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Orr(x10, left, right);
1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpPatchSite patch_site(masm_);
1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  patch_site.EmitJumpIfSmi(x10, &both_smis);
1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&stub_call);
1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1517109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assembler::BlockPoolsScope scope(masm_);
1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallIC(code, expr->BinaryOperationFeedbackId());
1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patch_site.EmitPatchInfo();
1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(&done);
1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&both_smis);
1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Smi case. This code works in the same way as the smi-smi case in the type
1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // recording binary operation stub, see
1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // BinaryOpStub::GenerateSmiSmiOperation for comments.
1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(all): That doesn't exist any more. Where are the comments?
1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The set of operations that needs to be supported here is controlled by
1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // FullCodeGenerator::ShouldInlineSmiCase().
1533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (op) {
1534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::SAR:
1535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Ubfx(right, right, kSmiShift, 5);
1536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Asr(result, left, right);
1537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Bic(result, result, kSmiShiftMask);
1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::SHL:
1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Ubfx(right, right, kSmiShift, 5);
1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Lsl(result, left, right);
1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::SHR:
1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // If `left >>> right` >= 0x80000000, the result is not representable in a
1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // signed 32-bit smi.
1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Ubfx(right, right, kSmiShift, 5);
1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Lsr(x10, left, right);
1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Tbnz(x10, kXSignBit, &stub_call);
1549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Bic(result, x10, kSmiShiftMask);
1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::ADD:
1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Adds(x10, left, right);
1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ B(vs, &stub_call);
1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Mov(result, x10);
1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::SUB:
1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Subs(x10, left, right);
1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ B(vs, &stub_call);
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Mov(result, x10);
1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::MUL: {
1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label not_minus_zero, done;
1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      STATIC_ASSERT(static_cast<unsigned>(kSmiShift) == (kXRegSizeInBits / 2));
1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      STATIC_ASSERT(kSmiTag == 0);
1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Smulh(x10, left, right);
1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Cbnz(x10, &not_minus_zero);
1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Eor(x11, left, right);
1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Tbnz(x11, kXSignBit, &stub_call);
1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Mov(result, x10);
1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ B(&done);
1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Bind(&not_minus_zero);
1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Cls(x11, x10);
1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Cmp(x11, kXRegSizeInBits - kSmiShift);
1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ B(lt, &stub_call);
1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ SmiTag(result, x10);
1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Bind(&done);
1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::BIT_OR:
1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Orr(result, left, right);
1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::BIT_AND:
1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ And(result, left, right);
1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::BIT_XOR:
1586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Eor(result, left, right);
1587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&done);
1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(x0);
1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
1598109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(x1);
1599109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpPatchSite patch_site(masm_);    // Unbound, signals no inlined smi code.
1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assembler::BlockPoolsScope scope(masm_);
1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallIC(code, expr->BinaryOperationFeedbackId());
1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patch_site.EmitPatchInfo();
1605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(x0);
1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
160962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr, FeedbackSlot slot) {
1610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(expr->IsValidReferenceExpressionOrThis());
1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Property* prop = expr->AsProperty();
1613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LhsKind assign_type = Property::GetAssignType(prop);
1614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (assign_type) {
1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case VARIABLE: {
1617c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      VariableProxy* proxy = expr->AsVariableProxy();
1618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EffectContext context(this);
1619c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot,
1620c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                             proxy->hole_check_mode());
1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case NAMED_PROPERTY: {
1624109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(x0);  // Preserve value.
1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(prop->obj());
1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // TODO(all): We could introduce a VisitForRegValue(reg, expr) to avoid
1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // this copy.
1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Mov(StoreDescriptor::ReceiverRegister(), x0);
1629109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(StoreDescriptor::ValueRegister());  // Restore value.
1630f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      CallStoreIC(slot, prop->key()->AsLiteral()->value());
1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case KEYED_PROPERTY: {
1634109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(x0);  // Preserve value.
1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForStackValue(prop->obj());
1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(prop->key());
1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Mov(StoreDescriptor::NameRegister(), x0);
1638109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperands(StoreDescriptor::ReceiverRegister(),
1639109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                  StoreDescriptor::ValueRegister());
1640f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      CallKeyedStoreIC(slot);
1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
164362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case NAMED_SUPER_PROPERTY:
164462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case KEYED_SUPER_PROPERTY:
164562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      UNREACHABLE();
164662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(x0);
1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Variable* var, MemOperand location) {
1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Str(result_register(), location);
1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (var->IsContextSlot()) {
1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // RecordWrite may destroy all its register arguments.
1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Mov(x10, result_register());
1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int offset = Context::SlotOffset(var->index());
1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ RecordWriteContextSlot(
1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        x1, offset, x10, x11, kLRHasBeenSaved, kDontSaveFPRegs);
1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
166562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                               FeedbackSlot slot,
1666c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                               HoleCheckMode hole_check_mode) {
1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment");
1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (var->IsUnallocated()) {
1669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Global var, const, or let.
1670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
1671f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    CallStoreIC(slot, var->name());
1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1673f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
1674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!var->IsLookupSlot());
1675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
1676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MemOperand location = VarOperand(var, x1);
1677f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Perform an initialization check for lexically declared variables.
1678f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (var->binding_needs_init()) {
1679f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Label assign;
1680f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ Ldr(x10, location);
1681f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &assign);
1682f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ Mov(x10, Operand(var->name()));
1683f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ Push(x10);
1684f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ CallRuntime(Runtime::kThrowReferenceError);
1685f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ Bind(&assign);
1686f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1687f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (var->mode() != CONST) {
1688f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      EmitStoreToStackLocalOrContextSlot(var, location);
1689f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    } else if (var->throw_on_const_assignment(language_mode())) {
1690f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      __ CallRuntime(Runtime::kThrowConstAssignError);
1691f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) {
1693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Initializing assignment to const {this} needs a write barrier.
1694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
1695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label uninitialized_this;
1696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MemOperand location = VarOperand(var, x1);
1697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ldr(x10, location);
1698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ JumpIfRoot(x10, Heap::kTheHoleValueRootIndex, &uninitialized_this);
1699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Mov(x0, Operand(var->name()));
1700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Push(x0);
1701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallRuntime(Runtime::kThrowReferenceError);
1702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&uninitialized_this);
1703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    EmitStoreToStackLocalOrContextSlot(var, location);
1704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1705f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } else {
1706f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK(var->mode() != CONST || op == Token::INIT);
170762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
170862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(!var->IsLookupSlot());
170962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Assignment to var or initializing assignment to let/const in harmony
171062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // mode.
171162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    MemOperand location = VarOperand(var, x1);
171262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) {
171362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Ldr(x10, location);
171462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ CompareRoot(x10, Heap::kTheHoleValueRootIndex);
171562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Check(eq, kLetBindingReInitialization);
1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
171762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    EmitStoreToStackLocalOrContextSlot(var, location);
1718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ASM_LOCATION("FullCodeGenerator::EmitNamedPropertyAssignment");
1724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Assignment to a property, using a named store IC.
1725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Property* prop = expr->target()->AsProperty();
1726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(prop != NULL);
1727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(prop->key()->IsLiteral());
1728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1729109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(StoreDescriptor::ReceiverRegister());
1730f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CallStoreIC(expr->AssignmentSlot(), prop->key()->AsLiteral()->value());
1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1732bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(x0);
1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ASM_LOCATION("FullCodeGenerator::EmitKeyedPropertyAssignment");
1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Assignment to a property, using a keyed store IC.
1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(all): Could we pass this in registers rather than on the stack?
1742109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperands(StoreDescriptor::NameRegister(),
1743109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch              StoreDescriptor::ReceiverRegister());
1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(StoreDescriptor::ValueRegister().is(x0));
1745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1746f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CallKeyedStoreIC(expr->AssignmentSlot());
1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1748bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
1749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->Plug(x0);
1750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC.
1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
1754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ASM_LOCATION("FullCodeGenerator::EmitCallWithLoadIC");
1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Expression* callee = expr->expression();
1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the target function.
1758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ConvertReceiverMode convert_mode;
1759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (callee->IsVariableProxy()) {
1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    { StackValueContext context(this);
1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitVariableLoad(callee->AsVariableProxy());
1762bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push undefined as receiver. This is patched in the method prologue if it
1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // is a sloppy mode method.
1766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    {
1767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      UseScratchRegisterScope temps(masm_);
1768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Register temp = temps.AcquireX();
1769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ LoadRoot(temp, Heap::kUndefinedValueRootIndex);
1770109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(temp);
1771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    convert_mode = ConvertReceiverMode::kNullOrUndefined;
1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load the function from the receiver.
1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(callee->IsProperty());
1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!callee->AsProperty()->IsSuperAccess());
1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Peek(LoadDescriptor::ReceiverRegister(), 0);
1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitNamedPropertyLoad(callee->AsProperty());
1779bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
1780bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           BailoutState::TOS_REGISTER);
1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push the target function under the receiver.
1782109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PopOperand(x10);
1783109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperands(x0, x10);
1784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitCall(expr, convert_mode);
1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC.
1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Expression* key) {
1794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ASM_LOCATION("FullCodeGenerator::EmitKeyedCallWithLoadIC");
1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the key.
1796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(key);
1797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Expression* callee = expr->expression();
1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the function from the receiver.
1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(callee->IsProperty());
1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Peek(LoadDescriptor::ReceiverRegister(), 0);
1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(LoadDescriptor::NameRegister(), x0);
1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitKeyedPropertyLoad(callee->AsProperty());
1805bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
1806bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                         BailoutState::TOS_REGISTER);
1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push the target function under the receiver.
1809109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(x10);
1810109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperands(x0, x10);
1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined);
1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
1817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ASM_LOCATION("FullCodeGenerator::EmitCall");
1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the arguments.
1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int arg_count = args->length();
1821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (int i = 0; i < arg_count; i++) {
1822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    VisitForStackValue(args->at(i));
1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1825bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
18263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  SetCallPosition(expr, expr->tail_call_mode());
1827109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (expr->tail_call_mode() == TailCallMode::kAllow) {
1828109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (FLAG_trace) {
1829109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ CallRuntime(Runtime::kTraceTailCall);
1830109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
1831109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Update profiling counters before the tail call since we will
1832109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // not return to this function.
1833109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    EmitProfilingCounterHandlingForReturnSequence(true);
1834109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
1835c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<Code> code =
183662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      CodeFactory::CallICTrampoline(isolate(), mode, expr->tail_call_mode())
183762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          .code();
183862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Mov(x3, IntFromSlot(expr->CallFeedbackICSlot()));
1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Peek(x1, (arg_count + 1) * kXRegSize);
1840c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Mov(x0, arg_count);
1841c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CallIC(code);
1842109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(arg_count + 1);
1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordJSReturnSite(expr);
1845bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  RestoreContext();
1846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->DropAndPlug(1, x0);
1847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ CallNew");
1851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // According to ECMA-262, section 11.2.2, page 44, the function
1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // expression in new calls must be evaluated before the
1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // arguments.
1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push constructor on the stack.  If it's not a function it's used as
1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ignored.
1858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!expr->expression()->IsSuperPropertyReference());
1859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForStackValue(expr->expression());
1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push the arguments ("left-to-right") on the stack.
1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int arg_count = args->length();
1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < arg_count; i++) {
1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VisitForStackValue(args->at(i));
1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Call the construct call builtin that handles allocation and
1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // constructor invocation.
1870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetConstructCallPosition(expr);
1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load function and argument count into x1 and x0.
1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mov(x0, arg_count);
1874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Peek(x1, arg_count * kXRegSize);
1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Record call targets in unoptimized code.
187762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ EmitLoadFeedbackVector(x2);
1878958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Mov(x3, SmiFromSlot(expr->CallNewFeedbackSlot()));
1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallConstructStub stub(isolate());
1881c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CallIC(stub.GetCode());
1882109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(arg_count + 1);
1883bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
1884bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  RestoreContext();
1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(x0);
1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(0));
1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label materialize_true, materialize_false;
1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_true = NULL;
1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_false = NULL;
1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* fall_through = NULL;
1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         &if_true, &if_false, &fall_through);
1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
1903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ TestAndSplit(x0, kSmiTagMask, if_true, if_false, fall_through);
1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(if_true, if_false);
1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsJSReceiver(CallRuntime* expr) {
1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(0));
1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label materialize_true, materialize_false;
1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_true = NULL;
1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_false = NULL;
1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* fall_through = NULL;
1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         &if_true, &if_false, &fall_through);
1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(x0, if_false);
1923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareObjectType(x0, x10, x11, FIRST_JS_RECEIVER_TYPE);
1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
1925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Split(ge, if_true, if_false, fall_through);
1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(if_true, if_false);
1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(0));
1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label materialize_true, materialize_false;
1938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_true = NULL;
1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_false = NULL;
1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* fall_through = NULL;
1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         &if_true, &if_false, &fall_through);
1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(x0, if_false);
1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CompareObjectType(x0, x10, x11, JS_ARRAY_TYPE);
1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Split(eq, if_true, if_false, fall_through);
1948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(if_true, if_false);
1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsTypedArray(CallRuntime* expr) {
1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(0));
1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label materialize_true, materialize_false;
1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_true = NULL;
1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_false = NULL;
1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* fall_through = NULL;
1963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
1964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         &if_false, &fall_through);
1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(x0, if_false);
1967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareObjectType(x0, x10, x11, JS_TYPED_ARRAY_TYPE);
1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Split(eq, if_true, if_false, fall_through);
1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(if_true, if_false);
1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) {
1976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
1977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(args->length() == 1);
1978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForAccumulatorValue(args->at(0));
1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label materialize_true, materialize_false;
1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_true = NULL;
1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_false = NULL;
1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* fall_through = NULL;
1985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
1986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         &if_false, &fall_through);
1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ JumpIfSmi(x0, if_false);
1989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareObjectType(x0, x10, x11, JS_PROXY_TYPE);
1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Split(eq, if_true, if_false, fall_through);
1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(if_true, if_false);
1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ASM_LOCATION("FullCodeGenerator::EmitClassOf");
1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, null, function, non_function_constructor;
2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(0));
2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // If the object is not a JSReceiver, we return null.
2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(x0, &null);
2007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
2008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareObjectType(x0, x10, x11, FIRST_JS_RECEIVER_TYPE);
2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // x10: object's map.
2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // x11: object's type.
2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(lt, &null);
2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Return 'Function' for JSFunction objects.
20143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Cmp(x11, FIRST_FUNCTION_TYPE);
20153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
20163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ B(hs, &function);
2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if the constructor in the map is a JS function.
2019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register instance_type = x14;
2020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ GetMapConstructor(x12, x10, x13, instance_type);
2021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Cmp(instance_type, JS_FUNCTION_TYPE);
2022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ B(ne, &non_function_constructor);
2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // x12 now contains the constructor function. Grab the
2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // instance class name from there.
2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ldr(x13, FieldMemOperand(x12, JSFunction::kSharedFunctionInfoOffset));
2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ldr(x0,
2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldMemOperand(x13, SharedFunctionInfo::kInstanceClassNameOffset));
2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(&done);
2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Functions have class 'Function'.
2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&function);
2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(x0, Heap::kFunction_stringRootIndex);
2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(&done);
2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Objects with a non-function constructor have class 'Object'.
2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&non_function_constructor);
2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(x0, Heap::kObject_stringRootIndex);
2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(&done);
2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Non-JS objects have class null.
2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&null);
2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(x0, Heap::kNullValueRootIndex);
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All done.
2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&done);
2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(x0);
2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(args->at(0));
2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(1));
2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register object = x1;
2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register index = x0;
2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = x3;
2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2063109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(object);
2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label need_conversion;
2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label index_out_of_range;
2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
206813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
206913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                      &need_conversion, &index_out_of_range);
2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  generator.GenerateFast(masm_);
2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(&done);
2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&index_out_of_range);
2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // When the index is out of range, the spec requires us to return NaN.
2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(result, Heap::kNanValueRootIndex);
2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(&done);
2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&need_conversion);
2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the undefined value into the result register, which will
2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // trigger conversion.
2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ B(&done);
2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NopRuntimeCallHelper call_helper;
2085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&done);
2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(result);
2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCall(CallRuntime* expr) {
2093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ASM_LOCATION("FullCodeGenerator::EmitCall");
2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_LE(2, args->length());
2096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push target, receiver and arguments onto the stack.
2097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (Expression* const arg : *args) {
2098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    VisitForStackValue(arg);
2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2100bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
2101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Move target to x1.
2102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int const argc = args->length() - 2;
2103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Peek(x1, (argc + 1) * kXRegSize);
2104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Call the target.
2105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Mov(x0, argc);
2106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
2107109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(argc + 1);
2108bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  RestoreContext();
2109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Discard the function left on TOS.
2110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->DropAndPlug(1, x0);
2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) {
2114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
2115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, args->length());
2116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForAccumulatorValue(args->at(0));
2117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ AssertFunction(x0);
2118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset));
2119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Ldr(x0, FieldMemOperand(x0, Map::kPrototypeOffset));
2120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->Plug(x0);
2121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->arguments()->length() == 0);
2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference debug_is_active =
2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::debug_is_active_address(isolate());
2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mov(x10, debug_is_active);
2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ldrb(x0, MemOperand(x10));
2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTag(x0);
2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(x0);
2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
2136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(2, args->length());
2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForStackValue(args->at(0));
2138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForStackValue(args->at(1));
2139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label runtime, done;
2141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register result = x0;
2143bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ Allocate(JSIteratorResult::kSize, result, x10, x11, &runtime,
2144bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              NO_ALLOCATION_FLAGS);
2145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register map_reg = x1;
2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register result_value = x2;
2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register boolean_done = x3;
2148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register empty_fixed_array = x4;
2149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register untagged_result = x5;
2150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, map_reg);
2151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Pop(boolean_done);
2152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Pop(result_value);
2153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(empty_fixed_array, Heap::kEmptyFixedArrayRootIndex);
2154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSObject::kPropertiesOffset + kPointerSize ==
2155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                JSObject::kElementsOffset);
2156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSIteratorResult::kValueOffset + kPointerSize ==
2157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                JSIteratorResult::kDoneOffset);
2158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ObjectUntag(untagged_result, result);
2159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Str(map_reg, MemOperand(untagged_result, HeapObject::kMapOffset));
2160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Stp(empty_fixed_array, empty_fixed_array,
2161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         MemOperand(untagged_result, JSObject::kPropertiesOffset));
2162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Stp(result_value, boolean_done,
2163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         MemOperand(untagged_result, JSIteratorResult::kValueOffset));
2164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
2165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ B(&done);
2166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Bind(&runtime);
2168109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CallRuntimeWithOperands(Runtime::kCreateIterResultObject);
2169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Bind(&done);
2171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->Plug(x0);
2172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
21763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Push function.
21773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ LoadNativeContextSlot(expr->context_index(), x0);
21783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  PushOperand(x0);
21793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push undefined as the receiver.
2181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(x0, Heap::kUndefinedValueRootIndex);
2182109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(x0);
2183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int arg_count = args->length();
2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetCallPosition(expr);
2191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Peek(x1, (arg_count + 1) * kPointerSize);
2192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Mov(x0, arg_count);
2193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
2194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          RelocInfo::CODE_TARGET);
2195109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(arg_count + 1);
2196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  RestoreContext();
2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (expr->op()) {
2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::DELETE: {
2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Property* property = expr->expression()->AsProperty();
2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VariableProxy* proxy = expr->expression()->AsVariableProxy();
2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (property != NULL) {
2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->obj());
2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->key());
2210109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        CallRuntimeWithOperands(is_strict(language_mode())
2211109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                    ? Runtime::kDeleteProperty_Strict
2212109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                    : Runtime::kDeleteProperty_Sloppy);
2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        context()->Plug(x0);
2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else if (proxy != NULL) {
2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Variable* var = proxy->var();
2216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Delete of an unqualified identifier is disallowed in strict mode but
2217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // "delete this" is allowed.
2218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        bool is_this = var->is_this();
2219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(is_sloppy(language_mode()) || is_this);
2220f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        if (var->IsUnallocated()) {
2221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ LoadGlobalObject(x12);
2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Mov(x11, Operand(var->name()));
2223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ Push(x12, x11);
2224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ CallRuntime(Runtime::kDeleteProperty_Sloppy);
2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          context()->Plug(x0);
222662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        } else {
222762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          DCHECK(!var->IsLookupSlot());
222862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // Result of deleting non-global, non-dynamic variables is false.
2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // The subexpression does not have side effects.
2231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          context()->Plug(is_this);
2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Result of deleting non-property, non-variable reference is true.
2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // The subexpression may have side effects.
2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForEffect(expr->expression());
2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        context()->Plug(true);
2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::VOID: {
2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForEffect(expr->expression());
2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context()->Plug(Heap::kUndefinedValueRootIndex);
2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::NOT: {
2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (context()->IsEffect()) {
2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Unary NOT has no side effects so it's only necessary to visit the
2252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // subexpression.  Match the optimizing compiler by not branching.
2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForEffect(expr->expression());
2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else if (context()->IsTest()) {
2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        const TestContext* test = TestContext::cast(context());
2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // The labels are swapped for the recursive call.
2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForControl(expr->expression(),
2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        test->false_label(),
2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        test->true_label(),
2260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        test->fall_through());
2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        context()->Plug(test->true_label(), test->false_label());
2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue());
2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // TODO(jbramley): This could be much more efficient using (for
2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // example) the CSEL instruction.
2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label materialize_true, materialize_false, done;
2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForControl(expr->expression(),
2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        &materialize_false,
2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        &materialize_true,
2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        &materialize_true);
2271109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Bind(&materialize_true);
2274bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        PrepareForBailoutForId(expr->MaterializeTrueId(),
2275bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                               BailoutState::NO_REGISTERS);
2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ B(&done);
2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Bind(&materialize_false);
2280bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        PrepareForBailoutForId(expr->MaterializeFalseId(),
2281bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                               BailoutState::NO_REGISTERS);
2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ B(&done);
2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Bind(&done);
2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (context()->IsStackValue()) {
2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Push(result_register());
2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::TYPEOF: {
2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      {
2295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AccumulatorValueContext context(this);
2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForTypeofValue(expr->expression());
2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ Mov(x3, x0);
2299c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      __ Call(isolate()->builtins()->Typeof(), RelocInfo::CODE_TARGET);
2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context()->Plug(x0);
2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
2310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ CountOperation");
2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Property* prop = expr->expression()->AsProperty();
2315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LhsKind assign_type = Property::GetAssignType(prop);
2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Evaluate expression and get value.
2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (assign_type == VARIABLE) {
2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AccumulatorValueContext context(this);
2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitVariableLoad(expr->expression()->AsVariableProxy());
2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Reserve space for result of postfix operation.
2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (expr->is_postfix() && !context()->IsEffect()) {
2325109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(xzr);
2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (assign_type) {
2328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case NAMED_PROPERTY: {
2329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Put the object both on the stack and in the register.
2330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        VisitForStackValue(prop->obj());
2331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ Peek(LoadDescriptor::ReceiverRegister(), 0);
2332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        EmitNamedPropertyLoad(prop);
2333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
2334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
2335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case KEYED_PROPERTY: {
2337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        VisitForStackValue(prop->obj());
2338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        VisitForStackValue(prop->key());
2339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ Peek(LoadDescriptor::ReceiverRegister(), 1 * kPointerSize);
2340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ Peek(LoadDescriptor::NameRegister(), 0);
2341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        EmitKeyedPropertyLoad(prop);
2342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
2343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
2344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
234562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case NAMED_SUPER_PROPERTY:
234662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case KEYED_SUPER_PROPERTY:
2347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case VARIABLE:
2348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        UNREACHABLE();
2349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We need a second deoptimization point after loading the value
2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // in case evaluating the property load my have a side effect.
2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (assign_type == VARIABLE) {
2355bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2357bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Inline smi case if we are in a loop.
2361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label stub_call, done;
2362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpPatchSite patch_site(masm_);
2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int count_value = expr->op() == Token::INC ? 1 : -1;
2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (ShouldInlineSmiCase(expr->op())) {
2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label slow;
2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patch_site.EmitJumpIfNotSmi(x0, &slow);
2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Save result for postfix expressions.
2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (expr->is_postfix()) {
2371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!context()->IsEffect()) {
2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Save the result on the stack. If we have a named or keyed property we
2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // store the result under the receiver that is currently on top of the
2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // stack.
2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        switch (assign_type) {
2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          case VARIABLE:
2377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ Push(x0);
2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
2379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          case NAMED_PROPERTY:
2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ Poke(x0, kPointerSize);
2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
2382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          case KEYED_PROPERTY:
2383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ Poke(x0, kPointerSize * 2);
2384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
238562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          case NAMED_SUPER_PROPERTY:
2386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case KEYED_SUPER_PROPERTY:
238762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            UNREACHABLE();
2388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            break;
2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Adds(x0, x0, Smi::FromInt(count_value));
2394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ B(vc, &done);
2395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Call stub. Undo operation first.
2396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Sub(x0, x0, Smi::FromInt(count_value));
2397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ B(&stub_call);
2398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Bind(&slow);
2399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
24003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
24013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Convert old value into a number.
240213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
2403f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RestoreContext();
2404bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Save result for postfix expressions.
2407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expr->is_postfix()) {
2408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!context()->IsEffect()) {
2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Save the result on the stack. If we have a named or keyed property
2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // we store the result under the receiver that is currently on top
2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // of the stack.
2412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      switch (assign_type) {
2413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case VARIABLE:
2414109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          PushOperand(x0);
2415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case NAMED_PROPERTY:
2417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Poke(x0, kXRegSize);
2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case KEYED_PROPERTY:
2420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Poke(x0, 2 * kXRegSize);
2421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
242262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case NAMED_SUPER_PROPERTY:
2423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        case KEYED_SUPER_PROPERTY:
242462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          UNREACHABLE();
2425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          break;
2426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&stub_call);
2431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mov(x1, x0);
2432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mov(x0, Smi::FromInt(count_value));
2433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionPosition(expr);
2435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
2437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assembler::BlockPoolsScope scope(masm_);
2438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code();
2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallIC(code, expr->CountBinOpFeedbackId());
2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patch_site.EmitPatchInfo();
2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Bind(&done);
2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Store the value returned in x0.
2445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (assign_type) {
2446c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    case VARIABLE: {
2447c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      VariableProxy* proxy = expr->expression()->AsVariableProxy();
2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (expr->is_postfix()) {
2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        { EffectContext context(this);
2450c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
2451c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                 proxy->hole_check_mode());
2452bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          PrepareForBailoutForId(expr->AssignmentId(),
2453bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                 BailoutState::TOS_REGISTER);
2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          context.Plug(x0);
2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // For all contexts except EffectConstant We have the result on
2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // top of the stack.
2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (!context()->IsEffect()) {
2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          context()->PlugTOS();
2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
2462c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
2463c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                               proxy->hole_check_mode());
2464bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        PrepareForBailoutForId(expr->AssignmentId(),
2465bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                               BailoutState::TOS_REGISTER);
2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        context()->Plug(x0);
2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2469c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case NAMED_PROPERTY: {
2471109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(StoreDescriptor::ReceiverRegister());
2472f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value());
2473bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (expr->is_postfix()) {
2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (!context()->IsEffect()) {
2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          context()->PlugTOS();
2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        context()->Plug(x0);
2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case KEYED_PROPERTY: {
2484109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(StoreDescriptor::NameRegister());
2485109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(StoreDescriptor::ReceiverRegister());
2486f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      CallKeyedStoreIC(expr->CountSlot());
2487bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (expr->is_postfix()) {
2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (!context()->IsEffect()) {
2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          context()->PlugTOS();
2491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        context()->Plug(x0);
2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
249762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case NAMED_SUPER_PROPERTY:
249862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case KEYED_SUPER_PROPERTY:
249962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      UNREACHABLE();
250062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Expression* sub_expr,
2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Handle<String> check) {
2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof");
2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ EmitLiteralCompareTypeof");
2510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label materialize_true, materialize_false;
2511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_true = NULL;
2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_false = NULL;
2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* fall_through = NULL;
2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         &if_true, &if_false, &fall_through);
2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { AccumulatorValueContext context(this);
2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VisitForTypeofValue(sub_expr);
2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate()->factory();
2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (String::Equals(check, factory->number_string())) {
2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof number_string");
2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(x0, if_true);
2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset));
2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(x0, Heap::kHeapNumberMapRootIndex);
2528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Split(eq, if_true, if_false, fall_through);
2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->string_string())) {
2530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof string_string");
2531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(x0, if_false);
2532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CompareObjectType(x0, x0, x1, FIRST_NONSTRING_TYPE);
2533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Split(lt, if_true, if_false, fall_through);
2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->symbol_string())) {
2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof symbol_string");
2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(x0, if_false);
2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareObjectType(x0, x0, x1, SYMBOL_TYPE);
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Split(eq, if_true, if_false, fall_through);
2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->boolean_string())) {
2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof boolean_string");
2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfRoot(x0, Heap::kTrueValueRootIndex, if_true);
2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(x0, Heap::kFalseValueRootIndex);
2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Split(eq, if_true, if_false, fall_through);
2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->undefined_string())) {
2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ASM_LOCATION(
2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "FullCodeGenerator::EmitLiteralCompareTypeof undefined_string");
2547109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ JumpIfRoot(x0, Heap::kNullValueRootIndex, if_false);
2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(x0, if_false);
2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check for undetectable objects => true.
2550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset));
2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset));
2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ TestAndSplit(x1, 1 << Map::kIsUndetectable, if_false, if_true,
2553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    fall_through);
2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->function_string())) {
2555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof function_string");
2556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(x0, if_false);
2557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset));
2558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset));
2559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ And(x1, x1, (1 << Map::kIsCallable) | (1 << Map::kIsUndetectable));
2560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CompareAndSplit(x1, Operand(1 << Map::kIsCallable), eq, if_true,
2561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       if_false, fall_through);
2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->object_string())) {
2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof object_string");
2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(x0, if_false);
2565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfRoot(x0, Heap::kNullValueRootIndex, if_true);
2566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
2567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ JumpIfObjectType(x0, x10, x11, FIRST_JS_RECEIVER_TYPE, if_false, lt);
2568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Check for callable or undetectable objects => false.
2569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ldrb(x10, FieldMemOperand(x10, Map::kBitFieldOffset));
2570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ TestAndSplit(x10, (1 << Map::kIsCallable) | (1 << Map::kIsUndetectable),
2571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    if_true, if_false, fall_through);
2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof other");
2574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (if_false != fall_through) __ B(if_false);
2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(if_true, if_false);
2577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ CompareOperation");
2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Try to generate an optimized comparison with a literal value.
2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(jbramley): This only checks common values like NaN or undefined.
2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Should it also handle ARM64 immediate operands?
2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (TryLiteralCompare(expr)) {
2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Assign labels according to context()->PrepareTest.
2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label materialize_true;
2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label materialize_false;
2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_true = NULL;
2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_false = NULL;
2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* fall_through = NULL;
2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         &if_true, &if_false, &fall_through);
2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Token::Value op = expr->op();
2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(expr->left());
2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (op) {
2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::IN:
2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForStackValue(expr->right());
2604bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      SetExpressionPosition(expr);
2605bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      EmitHasProperty();
2606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CompareRoot(x0, Heap::kTrueValueRootIndex);
2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Split(eq, if_true, if_false, fall_through);
2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::INSTANCEOF: {
2612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      VisitForAccumulatorValue(expr->right());
2613bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      SetExpressionPosition(expr);
2614109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(x1);
2615c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      __ Call(isolate()->builtins()->InstanceOf(), RelocInfo::CODE_TARGET);
261662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      RestoreContext();
2617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
2618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ CompareRoot(x0, Heap::kTrueValueRootIndex);
2619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Split(eq, if_true, if_false, fall_through);
2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default: {
2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(expr->right());
2625bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      SetExpressionPosition(expr);
2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Condition cond = CompareIC::ComputeCondition(op);
2627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Pop the stack value.
2629109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(x1);
2630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      JumpPatchSite patch_site(masm_);
2632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (ShouldInlineSmiCase(op)) {
2633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label slow_case;
2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        patch_site.EmitJumpIfEitherNotSmi(x0, x1, &slow_case);
2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Cmp(x1, x0);
2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Split(cond, if_true, if_false, NULL);
2637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Bind(&slow_case);
2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2640109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallIC(ic, expr->CompareOperationFeedbackId());
2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      patch_site.EmitPatchInfo();
2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CompareAndSplit(x0, 0, cond, if_true, if_false, fall_through);
2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Convert the result of the comparison into one expected for this
2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // expression's context.
2650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(if_true, if_false);
2651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Expression* sub_expr,
2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              NilValue nil) {
2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareNil");
2658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label materialize_true, materialize_false;
2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_true = NULL;
2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_false = NULL;
2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* fall_through = NULL;
2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         &if_true, &if_false, &fall_through);
2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(sub_expr);
2666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expr->op() == Token::EQ_STRICT) {
2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Heap::RootListIndex nil_value = nil == kNullValue ?
2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Heap::kNullValueRootIndex :
2671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Heap::kUndefinedValueRootIndex;
2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(x0, nil_value);
2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Split(eq, if_true, if_false, fall_through);
2674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
26753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ JumpIfSmi(x0, if_false);
26763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset));
26773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset));
26783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ TestAndSplit(x1, 1 << Map::kIsUndetectable, if_false, if_true,
26793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                    fall_through);
2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(if_true, if_false);
2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitYield(Yield* expr) {
268762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Resumable functions are not supported.
268862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  UNREACHABLE();
2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2691109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::PushOperands(Register reg1, Register reg2) {
2692109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthIncrement(2);
2693109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Push(reg1, reg2);
2694109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
2695109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2696109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::PushOperands(Register reg1, Register reg2,
2697109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                     Register reg3) {
2698109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthIncrement(3);
2699109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Push(reg1, reg2, reg3);
2700109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
2701109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2702109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::PopOperands(Register reg1, Register reg2) {
2703109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(2);
2704109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Pop(reg1, reg2);
2705109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
2706109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2707109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::EmitOperandStackDepthCheck() {
2708109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (FLAG_debug_code) {
2709109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp +
2710109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                        operand_stack_depth_ * kPointerSize;
2711109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Sub(x0, fp, jssp);
2712109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Cmp(x0, Operand(expected_diff));
2713109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Assert(eq, kUnexpectedStackDepth);
2714109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
2715109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCreateIteratorResult(bool done) {
2718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label allocate, done_allocate;
2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate and populate an object with this form: { value: VAL, done: DONE }
2721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = x0;
2723bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ Allocate(JSIteratorResult::kSize, result, x10, x11, &allocate,
2724bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              NO_ALLOCATION_FLAGS);
2725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ B(&done_allocate);
2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Bind(&allocate);
2728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Push(Smi::FromInt(JSIteratorResult::kSize));
2729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace);
2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Bind(&done_allocate);
2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register map_reg = x1;
2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result_value = x2;
2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register boolean_done = x3;
2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register empty_fixed_array = x4;
2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register untagged_result = x5;
2737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, map_reg);
27383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  PopOperand(result_value);
2739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(boolean_done,
2740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex);
2741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(empty_fixed_array, Heap::kEmptyFixedArrayRootIndex);
2742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(JSObject::kPropertiesOffset + kPointerSize ==
2743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                JSObject::kElementsOffset);
2744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSIteratorResult::kValueOffset + kPointerSize ==
2745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                JSIteratorResult::kDoneOffset);
2746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ObjectUntag(untagged_result, result);
2747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Str(map_reg, MemOperand(untagged_result, HeapObject::kMapOffset));
2748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Stp(empty_fixed_array, empty_fixed_array,
2749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         MemOperand(untagged_result, JSObject::kPropertiesOffset));
2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Stp(result_value, boolean_done,
2751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         MemOperand(untagged_result, JSIteratorResult::kValueOffset));
2752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(all): I don't like this method.
2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// It seems to me that in too many places x0 is used in place of this.
2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Also, this function is not suitable for all places where x0 should be
2759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// abstracted (eg. when used as an argument). But some places assume that the
2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// first argument register is x0, and use this function instead.
2761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Considering that most of the register allocation is hard-coded in the
2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// FullCodeGen, that it is unlikely we will need to change it extensively, and
2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// that abstracting the allocation through functions would not yield any
2764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// performance benefit, I think the existence of this function is debatable.
2765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister FullCodeGenerator::result_register() {
2766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return x0;
2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister FullCodeGenerator::context_register() {
2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return cp;
2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
27743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid FullCodeGenerator::LoadFromFrameField(int frame_offset, Register value) {
27753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(POINTER_SIZE_ALIGN(frame_offset) == frame_offset);
27763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Ldr(value, MemOperand(fp, frame_offset));
27773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(POINTER_SIZE_ALIGN(frame_offset) == frame_offset);
2781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Str(value, MemOperand(fp, frame_offset));
2782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
2786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ldr(dst, ContextMemOperand(cp, context_index));
2787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
2791f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeclarationScope* closure_scope = scope()->GetClosureScope();
2792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (closure_scope->is_script_scope() ||
2793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      closure_scope->is_module_scope()) {
2794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Contexts nested in the native context have a canonical empty function
2795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // as their closure, not the anonymous closure containing the global
2796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // code.
2797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kSmiTag == 0);
2798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadNativeContextSlot(Context::CLOSURE_INDEX, x10);
2799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (closure_scope->is_eval_scope()) {
2800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Contexts created by a call to eval have the same closure as the
2801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // context calling eval, not the anonymous closure containing the eval
2802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // code.  Fetch it from the context.
2803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Ldr(x10, ContextMemOperand(cp, Context::CLOSURE_INDEX));
2804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(closure_scope->is_function_scope());
2806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Ldr(x10, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2808109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(x10);
2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __
2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BackEdgeTable::PatchAt(Code* unoptimized_code,
2816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Address pc,
2817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            BackEdgeState target_state,
2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Code* replacement_code) {
2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Turn the jump into a nop.
2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address branch_address = pc - 3 * kInstructionSize;
2821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Isolate* isolate = unoptimized_code->GetIsolate();
2822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  PatchingAssembler patcher(isolate, branch_address, 1);
2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Instruction::Cast(branch_address)
2825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             ->IsNop(Assembler::INTERRUPT_CODE_NOP) ||
2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         (Instruction::Cast(branch_address)->IsCondBranchImm() &&
2827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Instruction::Cast(branch_address)->ImmPCOffset() ==
2828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              6 * kInstructionSize));
2829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (target_state) {
2831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case INTERRUPT:
2832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  <decrement profiling counter>
2833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  .. .. .. ..       b.pl ok
2834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  .. .. .. ..       ldr x16, pc+<interrupt stub address>
2835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  .. .. .. ..       blr x16
2836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  ... more instructions.
2837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  ok-label
2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Jump offset is 6 instructions.
2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      patcher.b(6, pl);
2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case ON_STACK_REPLACEMENT:
2842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  <decrement profiling counter>
2843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  .. .. .. ..       mov x0, x0 (NOP)
2844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  .. .. .. ..       ldr x16, pc+<on-stack replacement address>
2845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  .. .. .. ..       blr x16
2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      patcher.nop(Assembler::INTERRUPT_CODE_NOP);
2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Replace the call address.
2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Instruction* load = Instruction::Cast(pc)->preceding(2);
2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address interrupt_address_pointer =
2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<Address>(load) + load->ImmPCOffset();
2854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((Memory::uint64_at(interrupt_address_pointer) ==
2855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          reinterpret_cast<uint64_t>(
2856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              isolate->builtins()->OnStackReplacement()->entry())) ||
2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         (Memory::uint64_at(interrupt_address_pointer) ==
2858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          reinterpret_cast<uint64_t>(
2859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              isolate->builtins()->InterruptCheck()->entry())) ||
2860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         (Memory::uint64_at(interrupt_address_pointer) ==
2861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          reinterpret_cast<uint64_t>(
2862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              isolate->builtins()->OnStackReplacement()->entry())));
2863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Memory::uint64_at(interrupt_address_pointer) =
2864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<uint64_t>(replacement_code->entry());
2865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      unoptimized_code, reinterpret_cast<Address>(load), replacement_code);
2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Isolate* isolate,
2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Code* unoptimized_code,
2874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Address pc) {
2875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(jbramley): There should be some extra assertions here (as in the ARM
2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // back-end), but this function is gone in bleeding_edge so it might not
2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // matter anyway.
2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Instruction* jump_or_nop = Instruction::Cast(pc)->preceding(3);
2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (jump_or_nop->IsNop(Assembler::INTERRUPT_CODE_NOP)) {
2881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Instruction* load = Instruction::Cast(pc)->preceding(2);
2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint64_t entry = Memory::uint64_at(reinterpret_cast<Address>(load) +
2883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       load->ImmPCOffset());
2884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (entry == reinterpret_cast<uint64_t>(
2885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate->builtins()->OnStackReplacement()->entry())) {
2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return ON_STACK_REPLACEMENT;
2887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
2889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return INTERRUPT;
2893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
2897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
2898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_TARGET_ARCH_ARM64
2900