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