13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/full-codegen/full-codegen.h"
8f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/ast/compile-time-value.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ast/scopes.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
13f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/compilation-info.h"
14f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/compiler.h"
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h"
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h"
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/code-stubs-arm.h"
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/macro-assembler-arm.h"
209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 {
223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal {
233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
24109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define __ ACCESS_MASM(masm())
251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// A patch site is a location in the code which it is possible to patch. This
271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// class has a number of methods to emit the code which is patchable and the
281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// method EmitPatchInfo to record a marker back to the patchable code. This
291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// marker is a cmp rx, #yyy instruction, and x * 0x00000fff + yyy (raw 12 bit
301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// immediate value is used) is the delta from the pc to the first instruction of
311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// the patchable code.
321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass JumpPatchSite BASE_EMBEDDED {
331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    info_emitted_ = false;
371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ~JumpPatchSite() {
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(patch_site_.is_bound() == info_emitted_);
421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // When initially emitting this ensure that a jump is always generated to skip
451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the inlined smi code.
461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EmitJumpIfNotSmi(Register reg, Label* target) {
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!patch_site_.is_bound() && !info_emitted_);
48db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch    Assembler::BlockConstPoolScope block_const_pool(masm_);
491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&patch_site_);
501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cmp(reg, Operand(reg));
511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(eq, target);  // Always taken before patched.
521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // When initially emitting this ensure that a jump is never generated to skip
551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the inlined smi code.
561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EmitJumpIfSmi(Register reg, Label* target) {
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!patch_site_.is_bound() && !info_emitted_);
58db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch    Assembler::BlockConstPoolScope block_const_pool(masm_);
591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&patch_site_);
601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cmp(reg, Operand(reg));
611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(ne, target);  // Never taken before patched.
621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EmitPatchInfo() {
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Block literal pool emission whilst recording patch site information.
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assembler::BlockConstPoolScope block_const_pool(masm_);
673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (patch_site_.is_bound()) {
683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_);
693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Register reg;
703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      reg.set_code(delta_to_patch_site / kOff12Mask);
713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ cmp_raw_immediate(reg, delta_to_patch_site % kOff12Mask);
721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      info_emitted_ = true;
741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ nop();  // Signals no inlined code.
773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
81109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  MacroAssembler* masm() { return masm_; }
821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  MacroAssembler* masm_;
831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Label patch_site_;
841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool info_emitted_;
861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function.  On entry to the function the receiver
913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right.  The actual
923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// argument count matches the formal parameter count expected by the
933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// function.
943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are:
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   o r1: the JS function object being called (i.e., ourselves)
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//   o r3: the new target value
983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o cp: our context
99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//   o pp: our caller's constant pool pointer (if enabled)
1003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o fp: our caller's frame pointer
1013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o sp: stack pointer
1023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o lr: return address
1033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
1043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame.  Please see JavaScriptFrameConstants in
1053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-arm.h for its layout.
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::Generate() {
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompilationInfo* info = info_;
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  profiling_counter_ = isolate()->factory()->NewCell(
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetFunctionPosition(literal());
1116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comment cmnt(masm_, "[ function compiled by full code generator");
1123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProfileEntryHookStub::MaybeCallEntryHook(masm_);
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
1163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int receiver_offset = info->scope()->num_parameters() * kPointerSize;
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(r2, MemOperand(sp, receiver_offset));
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ AssertNotSmi(r2);
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CompareObjectType(r2, r2, no_reg, FIRST_JS_RECEIVER_TYPE);
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Assert(ge, kSloppyFunctionExpectsJSReceiverReceiver);
121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Open a frame scope to indicate that there is a frame on the stack.  The
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // MANUAL indicates that the scope shouldn't actually generate code to set up
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the frame (that is done below).
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameScope frame_scope(masm_, StackFrame::MANUAL);
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info->set_prologue_offset(masm_->pc_offset());
129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Prologue(info->GeneratePreagedPrologue());
1303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Increment invocation count for the function.
132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  {
133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Comment cmnt(masm_, "[ Increment invocation count");
134f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    __ ldr(r2, FieldMemOperand(r1, JSFunction::kLiteralsOffset));
135f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    __ ldr(r2, FieldMemOperand(r2, LiteralsArray::kFeedbackVectorOffset));
136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    __ ldr(r9, FieldMemOperand(r2, TypeFeedbackVector::kInvocationCountIndex *
137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                           kPointerSize +
138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                       TypeFeedbackVector::kHeaderSize));
139f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    __ add(r9, r9, Operand(Smi::FromInt(1)));
140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    __ str(r9, FieldMemOperand(r2, TypeFeedbackVector::kInvocationCountIndex *
141f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                           kPointerSize +
142f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                       TypeFeedbackVector::kHeaderSize));
143f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
144f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
145756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  { Comment cmnt(masm_, "[ Allocate locals");
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int locals_count = info->scope()->num_stack_slots();
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Generators allocate locals, if any, in context slots.
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0);
149109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    OperandStackDepthIncrement(locals_count);
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (locals_count > 0) {
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (locals_count >= 128) {
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label ok;
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ sub(r9, sp, Operand(locals_count * kPointerSize));
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ LoadRoot(r2, Heap::kRealStackLimitRootIndex);
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmp(r9, Operand(r2));
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ b(hs, &ok);
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ CallRuntime(Runtime::kThrowStackOverflow);
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ bind(&ok);
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(r9, Heap::kUndefinedValueRootIndex);
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int kMaxPushes = FLAG_optimize_for_size ? 4 : 32;
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (locals_count >= kMaxPushes) {
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int loop_iterations = locals_count / kMaxPushes;
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov(r2, Operand(loop_iterations));
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label loop_header;
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ bind(&loop_header);
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Do pushes.
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        for (int i = 0; i < kMaxPushes; i++) {
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ push(r9);
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Continue loop if not done.
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ sub(r2, r2, Operand(1), SetCC);
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ b(&loop_header, ne);
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int remaining = locals_count % kMaxPushes;
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Emit the remaining pushes.
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (int i  = 0; i < remaining; i++) {
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ push(r9);
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
181756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool function_in_register_r1 = true;
1844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
185756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate a local context.
186f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (info->scope()->NeedsContext()) {
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Argument to NewContext is the function, which is still in r1.
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment cmnt(masm_, "[ Allocate context");
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool need_write_barrier = true;
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (info->scope()->is_script_scope()) {
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ push(r1);
193f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      __ Push(info->scope()->scope_info());
194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ CallRuntime(Runtime::kNewScriptContext);
195bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(BailoutId::ScriptContext(),
196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             BailoutState::TOS_REGISTER);
197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // The new target value is not used, clobbering is safe.
198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK_NULL(info->scope()->new_target_var());
199756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (info->scope()->new_target_var() != nullptr) {
201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ push(r3);  // Preserve new target.
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (slots <= FastNewFunctionContextStub::kMaximumSlots) {
204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        FastNewFunctionContextStub stub(isolate());
205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ mov(FastNewFunctionContextDescriptor::SlotsRegister(),
206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch               Operand(slots));
207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ CallStub(&stub);
208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        // Result of FastNewFunctionContextStub is always in new space.
209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        need_write_barrier = false;
210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ push(r1);
212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ CallRuntime(Runtime::kNewFunctionContext);
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (info->scope()->new_target_var() != nullptr) {
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ pop(r3);  // Preserve new target.
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
217756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    function_in_register_r1 = false;
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Context is returned in r0.  It replaces the context passed to us.
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // It's saved in the stack and kept live in cp.
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(cp, r0);
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ str(r0, MemOperand(fp, StandardFrameConstants::kContextOffset));
223756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Copy any necessary parameters into the context.
2243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int num_parameters = info->scope()->num_parameters();
225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int first_parameter = info->scope()->has_this_declaration() ? -1 : 0;
226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (int i = first_parameter; i < num_parameters; i++) {
227f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Variable* var =
228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          (i == -1) ? info->scope()->receiver() : info->scope()->parameter(i);
229589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (var->IsContextSlot()) {
230756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
231756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick            (num_parameters - 1 - i) * kPointerSize;
232756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Load parameter from stack.
233756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ ldr(r0, MemOperand(fp, parameter_offset));
234756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Store it in the context.
235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        MemOperand target = ContextMemOperand(cp, var->index());
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ str(r0, target);
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Update the write barrier.
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (need_write_barrier) {
240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ RecordWriteContextSlot(cp, target.offset(), r0, r2,
241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    kLRHasBeenSaved, kDontSaveFPRegs);
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (FLAG_debug_code) {
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Label done;
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ JumpIfInNewSpace(cp, r0, &done);
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Abort(kExpectedNewSpaceObject);
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ bind(&done);
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
250756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Register holding this function and new target are both trashed in case we
253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // bailout here. But since that can happen only when new target is not used
254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // and we allocate a context, the value of |function_in_register| is correct.
255bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(BailoutId::FunctionContext(),
256bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                         BailoutState::NO_REGISTERS);
257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Possibly set up a local binding to the this function which is used in
259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // derived constructors with super calls.
260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Variable* this_function_var = info->scope()->this_function_var();
261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (this_function_var != nullptr) {
262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Comment cmnt(masm_, "[ This function");
263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!function_in_register_r1) {
264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ ldr(r1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // The write barrier clobbers register again, keep it marked as such.
266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SetVar(this_function_var, r1, r0, r2);
268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Possibly set up a local binding to the new target value.
271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Variable* new_target_var = info->scope()->new_target_var();
272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (new_target_var != nullptr) {
273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Comment cmnt(masm_, "[ new.target");
274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SetVar(new_target_var, r3, r0, r2);
275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Possibly allocate RestParameters
278f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Variable* rest_param = info->scope()->rest_parameter();
279f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (rest_param != nullptr) {
280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Comment cmnt(masm_, "[ Allocate rest parameter array");
281109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (!function_in_register_r1) {
282109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ ldr(r1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
283109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
284109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    FastNewRestParameterStub stub(isolate());
285f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch    __ CallStub(&stub);
286109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    function_in_register_r1 = false;
287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SetVar(rest_param, r0, r1, r2);
288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
290f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Variable* arguments = info->scope()->arguments();
291756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (arguments != NULL) {
292756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Function uses arguments object.
293756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate arguments object");
294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!function_in_register_r1) {
295756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      // Load this again, if it's used by the local context below.
296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ ldr(r1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
298109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (is_strict(language_mode()) || !has_simple_parameters()) {
299109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      FastNewStrictArgumentsStub stub(isolate());
300109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ CallStub(&stub);
301109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    } else if (literal()->has_duplicate_parameters()) {
302109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Push(r1);
303109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ CallRuntime(Runtime::kNewSloppyArguments_Generic);
304109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    } else {
305109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      FastNewSloppyArgumentsStub stub(isolate());
306109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ CallStub(&stub);
307109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
30844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
309589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SetVar(arguments, r0, r1, r2);
310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace) {
313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallRuntime(Runtime::kTraceEnter);
314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Visit the declarations and body.
317bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(BailoutId::FunctionEntry(),
318bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                         BailoutState::NO_REGISTERS);
3193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Comment cmnt(masm_, "[ Declarations");
3213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    VisitDeclarations(scope()->declarations());
3223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Assert that the declarations do not use ICs. Otherwise the debugger
3253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // won't be able to redirect a PC at an IC to the correct IC in newly
3263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // recompiled code.
3273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(0, ic_total_count_);
3283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
3303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Comment cmnt(masm_, "[ Stack check");
331bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(BailoutId::Declarations(),
332bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           BailoutState::NO_REGISTERS);
3333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Label ok;
3343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ LoadRoot(ip, Heap::kStackLimitRootIndex);
3353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ cmp(sp, Operand(ip));
3363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ b(hs, &ok);
3373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Handle<Code> stack_check = isolate()->builtins()->StackCheck();
3383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    PredictableCodeSizeScope predictable(masm_);
3393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    predictable.ExpectSize(
3403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        masm_->CallSize(stack_check, RelocInfo::CODE_TARGET));
3413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ Call(stack_check, RelocInfo::CODE_TARGET);
3423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ bind(&ok);
3433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
3463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Comment cmnt(masm_, "[ Body");
3473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(loop_depth() == 0);
3483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    VisitStatements(literal()->body());
3493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(loop_depth() == 0);
3503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
3513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
352e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Always emit a 'return undefined' in case control fell off the end of
353e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the body.
3543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
3553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  EmitReturnSequence();
358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Force emit the constant pool, so it doesn't get emitted in the middle
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // of the back edge table.
361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  masm()->CheckConstPool(true, false);
362d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
364c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid FullCodeGenerator::ClearAccumulator() { __ mov(r0, Operand(Smi::kZero)); }
365db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r2, Operand(profiling_counter_));
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(r3, r3, Operand(Smi::FromInt(delta)), SetCC);
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r3, FieldMemOperand(r2, Cell::kValueOffset));
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef CAN_USE_ARMV7_INSTRUCTIONS
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int kProfileCounterResetSequenceLength = 5 * Assembler::kInstrSize;
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int kProfileCounterResetSequenceLength = 7 * Assembler::kInstrSize;
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitProfilingCounterReset() {
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler::BlockConstPoolScope block_const_pool(masm_);
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PredictableCodeSizeScope predictable_code_size_scope(
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      masm_, kProfileCounterResetSequenceLength);
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label start;
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&start);
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int reset_value = FLAG_interrupt_budget;
3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r2, Operand(profiling_counter_));
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The mov instruction above can be either 1 to 3 (for ARMv7) or 1 to 5
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // instructions (for ARMv6) depending upon whether it is an extended constant
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // pool - insert nop to compensate.
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int expected_instr_count =
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (kProfileCounterResetSequenceLength / Assembler::kInstrSize) - 2;
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_->InstructionsGeneratedSince(&start) <= expected_instr_count);
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (masm_->InstructionsGeneratedSince(&start) != expected_instr_count) {
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ nop();
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r3, Operand(Smi::FromInt(reset_value)));
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r3, FieldMemOperand(r2, Cell::kValueOffset));
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Label* back_edge_target) {
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ Back edge bookkeeping");
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Block literal pools whilst emitting back edge code.
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler::BlockConstPoolScope block_const_pool(masm_);
408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label ok;
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(back_edge_target->is_bound());
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int weight = Min(kMaxBackEdgeWeight,
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Max(1, distance / kCodeSizeMultiplier));
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitProfilingCounterDecrement(weight);
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(pl, &ok);
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
418086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Record a mapping of this PC offset to the OSR id.  This is used to find
419086aeeaae12517475c22695a200be45495516549Ben Murdoch  // the AST id from the unoptimized code in order to use it as a key into
420086aeeaae12517475c22695a200be45495516549Ben Murdoch  // the deoptimization input data found in the optimized code.
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordBackEdge(stmt->OsrEntryId());
422086aeeaae12517475c22695a200be45495516549Ben Murdoch
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitProfilingCounterReset();
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&ok);
426bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
427086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Record a mapping of the OSR id to this PC.  This is used if the OSR
428086aeeaae12517475c22695a200be45495516549Ben Murdoch  // entry becomes the target of a bailout.  We don't expect it to be, but
429086aeeaae12517475c22695a200be45495516549Ben Murdoch  // we want it to work if it is.
430bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
433109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
434109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    bool is_tail_call) {
435109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Pretend that the exit is a backwards jump to the entry.
436109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int weight = 1;
437109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (info_->ShouldSelfOptimize()) {
438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    weight = FLAG_interrupt_budget / FLAG_self_opt_count;
439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
440109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int distance = masm_->pc_offset();
441109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    weight = Min(kMaxBackEdgeWeight, Max(1, distance / kCodeSizeMultiplier));
442109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
443109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  EmitProfilingCounterDecrement(weight);
444109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label ok;
445109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ b(pl, &ok);
446109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Don't need to save result register if we are going to do a tail call.
447109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!is_tail_call) {
448109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ push(r0);
449109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
450109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
451109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!is_tail_call) {
452109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ pop(r0);
453109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
454109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  EmitProfilingCounterReset();
455109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bind(&ok);
456109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() {
459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ b(&return_label_);
462d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
463d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
4643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
4653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // Push the return value on the stack as the parameter.
4663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // Runtime::TraceExit returns its parameter in r0.
4673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(r0);
468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ CallRuntime(Runtime::kTraceExit);
4693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
470109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    EmitProfilingCounterHandlingForReturnSequence(false);
4713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Make sure that the constant pool is not emitted inside of the return
4736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // sequence.
4746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    { Assembler::BlockConstPoolScope block_const_pool(masm_);
475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int32_t arg_count = info_->scope()->num_parameters() + 1;
476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int32_t sp_delta = arg_count * kPointerSize;
477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SetReturnPosition(literal());
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // TODO(svenpanne) The code below is sometimes 4 words, sometimes 5!
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PredictableCodeSizeScope predictable(masm_, -1);
480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ LeaveFrame(StackFrame::JAVA_SCRIPT);
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      { ConstantPoolUnavailableScope constant_pool_unavailable(masm_);
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ add(sp, sp, Operand(sp_delta));
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Jump(lr);
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
485d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
486d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
487d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
488d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
489bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid FullCodeGenerator::RestoreContext() {
490bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
491bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
492d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
493589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
495589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  codegen()->GetVar(result_register(), var);
496109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  codegen()->PushOperand(result_register());
497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5000d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
5010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
5050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
5060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), index);
5070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5100d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
5110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
5120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), index);
513109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  codegen()->PushOperand(result_register());
5140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5170d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
5220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (index == Heap::kUndefinedValueRootIndex ||
5230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kNullValueRootIndex ||
5240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kFalseValueRootIndex) {
525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (false_label_ != fall_through_) __ b(false_label_);
5260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (index == Heap::kTrueValueRootIndex) {
527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (true_label_ != fall_through_) __ b(true_label_);
5280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
5290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ LoadRoot(result_register(), index);
5303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    codegen()->DoTest(this);
531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
532d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5350d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
5360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5390d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
5400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Handle<Object> lit) const {
5410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), Operand(lit));
5420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
543e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5450d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Immediates cannot be pushed directly.
5470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), Operand(lit));
548109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  codegen()->PushOperand(result_register());
5490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5520d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
55713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) ||
55813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch         !lit->IsUndetectable());
55913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) ||
56013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      lit->IsFalse(isolate())) {
561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (false_label_ != fall_through_) __ b(false_label_);
56213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (true_label_ != fall_through_) __ b(true_label_);
5640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsString()) {
5650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (String::cast(*lit)->length() == 0) {
5668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (false_label_ != fall_through_) __ b(false_label_);
5670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ b(true_label_);
5690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
5700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsSmi()) {
5710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (Smi::cast(*lit)->value() == 0) {
572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (false_label_ != fall_through_) __ b(false_label_);
5730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ b(true_label_);
5750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
5760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
5770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // For simplicity we always test the accumulator register.
5780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ mov(result_register(), Operand(lit));
5793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    codegen()->DoTest(this);
580d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5840d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count,
5850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                       Register reg) const {
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(count > 0);
587109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (count > 1) codegen()->DropOperands(count - 1);
5880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ str(reg, MemOperand(sp, 0));
589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
591d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5920d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
5930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            Label* materialize_false) const {
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(materialize_true == materialize_false);
5950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
5960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5990d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
6000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
6010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
6020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label done;
6030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
6040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
6050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ jmp(&done);
6060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
6070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
6080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6120d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
6130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
6140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
6150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label done;
6160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
6170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(ip, Heap::kTrueValueRootIndex);
6180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ jmp(&done);
6190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
6200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(ip, Heap::kFalseValueRootIndex);
6210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
622109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  codegen()->PushOperand(ip);
6230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6260d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true,
6270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                          Label* materialize_false) const {
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(materialize_true == true_label_);
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(materialize_false == false_label_);
6300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6330d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
6340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
6350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
6360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), value_root_index);
6370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6400d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const {
6410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
6420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
6430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(ip, value_root_index);
644109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  codegen()->PushOperand(ip);
6450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6480d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const {
6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
6530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (flag) {
6540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (true_label_ != fall_through_) __ b(true_label_);
6550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
6560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (false_label_ != fall_through_) __ b(false_label_);
657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
659f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
6613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::DoTest(Expression* condition,
6623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               Label* if_true,
66380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* if_false,
66480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* fall_through) {
6653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(ic, condition->test_id());
667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Split(eq, if_true, if_false, fall_through);
66980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid FullCodeGenerator::Split(Condition cond,
67380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_true,
67480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_false,
67580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* fall_through) {
67680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (if_false == fall_through) {
6771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(cond, if_true);
67880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (if_true == fall_through) {
6791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(NegateCondition(cond), if_false);
68080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
6811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(cond, if_true);
68280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(if_false);
683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
687589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) {
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsStackAllocated());
689589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Offset is negative because higher indexes are at lower addresses.
690589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int offset = -var->index() * kPointerSize;
691589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Adjust by a (parameter or local) base offset.
692589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsParameter()) {
693589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
694589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else {
695589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    offset += JavaScriptFrameConstants::kLocal0Offset;
696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
697589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return MemOperand(fp, offset);
698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
700e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
701589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
703589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsContextSlot()) {
704589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    int context_chain_length = scope()->ContextChainLength(var->scope());
705589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ LoadContext(scratch, context_chain_length);
706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return ContextMemOperand(scratch, var->index());
707589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else {
708589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return StackOperand(var);
709589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
710589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
711589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
712589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
713589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) {
714e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Use destination as scratch.
715589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand location = VarOperand(var, dest);
716589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ ldr(dest, location);
717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
719e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
720589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::SetVar(Variable* var,
721589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register src,
722589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register scratch0,
723589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register scratch1) {
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch0.is(src));
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch0.is(scratch1));
727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch1.is(src));
728589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand location = VarOperand(var, scratch0);
729e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ str(src, location);
7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
732589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsContextSlot()) {
7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteContextSlot(scratch0,
7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              location.offset(),
7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              src,
7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              scratch1,
7373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              kLRHasBeenSaved,
7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              kDontSaveFPRegs);
739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     bool should_normalize,
745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_true,
746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_false) {
747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Only prepare for bailouts before splits if we're in a test
748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // context. Otherwise, we let the Visit function deal with the
749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // preparation to avoid preparing with the same AST id twice.
750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!context()->IsTest()) return;
751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label skip;
753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (should_normalize) __ b(&skip);
754bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (should_normalize) {
756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ LoadRoot(ip, Heap::kTrueValueRootIndex);
757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ cmp(r0, ip);
758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Split(eq, if_true, if_false, NULL);
759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ bind(&skip);
760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The variable in the declaration always resides in the current function
766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // context.
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, scope()->ContextChainLength(variable->scope()));
768109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (FLAG_debug_code) {
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check that we're not inside a with or catch context.
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset));
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(r1, Heap::kWithContextMapRootIndex);
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(ne, kDeclarationInWithContext);
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(r1, Heap::kCatchContextMapRootIndex);
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(ne, kDeclarationInCatchContext);
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitVariableDeclaration(
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VariableDeclaration* declaration) {
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VariableProxy* proxy = declaration->proxy();
782589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Variable* variable = proxy->var();
783589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (variable->location()) {
784f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case VariableLocation::UNALLOCATED: {
785bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      DCHECK(!variable->binding_needs_init());
786f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      FeedbackVectorSlot slot = proxy->VariableFeedbackSlot();
787f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK(!slot.IsInvalid());
788f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
789bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      globals_->Add(isolate()->factory()->undefined_value(), zone());
790589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
791f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::PARAMETER:
793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::LOCAL:
794f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (variable->binding_needs_init()) {
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment cmnt(masm_, "[ VariableDeclaration");
796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ str(r0, StackOperand(variable));
798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
79969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::CONTEXT:
802f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (variable->binding_needs_init()) {
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment cmnt(masm_, "[ VariableDeclaration");
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        EmitDebugCheckDeclarationContext(variable);
805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ str(r0, ContextMemOperand(cp, variable->index()));
80769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // No write barrier since the_hole_value is in old space.
808bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
80969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
81069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::LOOKUP: {
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ VariableDeclaration");
814f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK_EQ(VAR, variable->mode());
815f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK(!variable->binding_needs_init());
81669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov(r2, Operand(variable->name()));
81713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      __ Push(r2);
81813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      __ CallRuntime(Runtime::kDeclareEvalVar);
819bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
822f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
823f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case VariableLocation::MODULE:
824f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UNREACHABLE();
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitFunctionDeclaration(
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FunctionDeclaration* declaration) {
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VariableProxy* proxy = declaration->proxy();
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Variable* variable = proxy->var();
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (variable->location()) {
834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::UNALLOCATED: {
835f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      FeedbackVectorSlot slot = proxy->VariableFeedbackSlot();
836f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK(!slot.IsInvalid());
837f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<SharedFunctionInfo> function =
839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Check for stack-overflow exception.
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (function.is_null()) return SetStackOverflow();
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      globals_->Add(function, zone());
843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::PARAMETER:
847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::LOCAL: {
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ FunctionDeclaration");
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(declaration->fun());
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ str(result_register(), StackOperand(variable));
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::CONTEXT: {
855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ FunctionDeclaration");
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitDebugCheckDeclarationContext(variable);
857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(declaration->fun());
858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ str(result_register(), ContextMemOperand(cp, variable->index()));
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int offset = Context::SlotOffset(variable->index());
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // We know that we have written a function, which is not a smi.
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ RecordWriteContextSlot(cp,
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                offset,
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                result_register(),
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                r2,
865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                kLRHasBeenSaved,
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                kDontSaveFPRegs,
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                EMIT_REMEMBERED_SET,
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                OMIT_SMI_CHECK);
869bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::LOOKUP: {
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ FunctionDeclaration");
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(r2, Operand(variable->name()));
876109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(r2);
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Push initial value for function declaration.
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForStackValue(declaration->fun());
87913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
880bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
88169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
883f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
884f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case VariableLocation::MODULE:
885f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UNREACHABLE();
8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
890d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
8913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
892589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ mov(r1, Operand(pairs));
893589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags())));
894f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ EmitLoadTypeFeedbackVector(r2);
895f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ Push(r1, r0, r2);
896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CallRuntime(Runtime::kDeclareGlobals);
8973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
8983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ SwitchStatement");
903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Breakable nested_statement(this, stmt);
904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
905e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Keep the switch value on the stack until a case matches.
9070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(stmt->tag());
908bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<CaseClause*>* clauses = stmt->cases();
911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label next_test;  // Recycled for each test.
914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the tests with branches to their bodies.
915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
9178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    clause->body_target()->Unuse();
9181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The default is not a test, but remember it as final fall through.
920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (clause->is_default()) {
921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      default_clause = clause;
922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      continue;
923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case comparison");
926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&next_test);
927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    next_test.Unuse();
928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Compile the label expression.
9300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(clause->label());
931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
93280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Perform the comparison as if via '==='.
933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(r1, MemOperand(sp, 0));  // Switch value.
9340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
9351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    JumpPatchSite patch_site(masm_);
9360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (inline_smi_code) {
93780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label slow_case;
93880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ orr(r2, r1, r0);
9391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      patch_site.EmitJumpIfNotSmi(r2, &slow_case);
9401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
94180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ cmp(r1, r0);
94280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ b(ne, &next_test);
94380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ Drop(1);  // Switch value is no longer needed.
9448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      __ b(clause->body_target());
9451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ bind(&slow_case);
94680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
94780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
9481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Record position before stub call for type feedback.
949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SetExpressionPosition(clause);
950109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Handle<Code> ic =
951109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallIC(ic, clause->CompareId());
9533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    patch_site.EmitPatchInfo();
954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label skip;
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(&skip);
957bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(ip, Heap::kTrueValueRootIndex);
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(r0, ip);
960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(ne, &next_test);
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Drop(1);
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(clause->body_target());
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&skip);
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(r0, Operand::Zero());
966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(ne, &next_test);
967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
9688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ b(clause->body_target());
969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Discard the test value and jump to the default if present, otherwise to
972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the end of the statement.
973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&next_test);
974109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DropOperands(1);  // Switch value is no longer needed.
975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (default_clause == NULL) {
97669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ b(nested_statement.break_label());
977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
9788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ b(default_clause->body_target());
979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the case bodies.
982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case body");
984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
9858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ bind(clause->body_target());
986bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitStatements(clause->statements());
988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
99069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(nested_statement.break_label());
991bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ ForInStatement");
997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetStatementPosition(stmt, SKIP_BREAK);
998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
999958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
1000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1001109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Get the object to enumerate over.
1002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionAsStatementPosition(stmt->enumerable());
10030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(stmt->enumerable());
10043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  OperandStackDepthIncrement(5);
10053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
10063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label loop, exit;
10073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Iteration loop_statement(this, stmt);
10083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  increment_loop_depth();
1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1010109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // If the object is null or undefined, skip over the loop, otherwise convert
1011109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // it to a JS receiver.  See ECMA-262 version 5, section 12.6.4.
1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label convert, done_convert;
10131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, &convert);
1014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareObjectType(r0, r1, r1, FIRST_JS_RECEIVER_TYPE);
10153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ b(ge, &done_convert);
1016109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CompareRoot(r0, Heap::kNullValueRootIndex);
1017109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ b(eq, &exit);
1018109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
1019109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ b(eq, &exit);
1020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&convert);
1021c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Call(isolate()->builtins()->ToObject(), RelocInfo::CODE_TARGET);
1022f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RestoreContext();
1023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done_convert);
1024bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
1025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);
1026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1027bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Check cache validity in generated code. If we cannot guarantee cache
1028bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // validity, call the runtime system to check cache validity or get the
1029bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // property names in a fixed array. Note: Proxies never have an enum cache,
1030bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // so will always take the slow path.
1031109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label call_runtime;
1032109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CheckEnumCache(&call_runtime);
1033e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // The enum cache is valid.  Load the map of the object being
1035e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // iterated over and use the cache for the iteration.
1036e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Label use_cache;
1037e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
1038e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(&use_cache);
1039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the set of properties to enumerate.
1041e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&call_runtime);
1042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);  // Duplicate the enumerable object on the stack.
1043109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CallRuntime(Runtime::kForInEnumerate);
1044bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If we got a map from the runtime call, we can do a fast
1047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // modification check. Otherwise, we got a fixed array, and we have
1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // to do a slow check.
1049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label fixed_array;
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(ip, Heap::kMetaMapRootIndex);
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(r2, ip);
1053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &fixed_array);
1054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a map in register r0. Get the enumeration cache from it.
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_descriptors;
1057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&use_cache);
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ EnumLength(r1, r0);
1060c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ cmp(r1, Operand(Smi::kZero));
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(eq, &no_descriptors);
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadInstanceDescriptors(r0, r2);
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheOffset));
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheBridgeCacheOffset));
1066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the four remaining stack slots.
1068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);  // Map.
1069c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ mov(r0, Operand(Smi::kZero));
1070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Push enumeration cache, enumeration cache length (as smi) and zero.
1071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(r2, r1, r0);
1072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
1073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&no_descriptors);
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Drop(1);
1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&exit);
1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a fixed array in register r0. Iterate through that.
1079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&fixed_array);
10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(r1, Operand(Smi::FromInt(1)));  // Smi(1) indicates slow check
10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(r1, r0);  // Smi and array
1083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset));
1084109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Push(r1);  // Fixed array length (as smi).
1085bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
1086c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ mov(r0, Operand(Smi::kZero));
1087109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Push(r0);  // Initial index.
1088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for doing the condition check.
1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&loop);
1091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionAsStatementPosition(stmt->each());
1092958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the current count to r0, load the length to r1.
1094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
1095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, r1);  // Compare to the array length.
109669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ b(hs, loop_statement.break_label());
1097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1098f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Get the current entry of the array into register r0.
1099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(sp, 2 * kPointerSize));
1100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ ldr(r0, MemOperand::PointerAddressFromSmiKey(r2, r0));
1102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
11033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the expected map from the stack or a smi in the
1104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // permanent slow case into register r2.
1105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(sp, 3 * kPointerSize));
1106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the expected map still matches that of the enumerable.
11083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If not, we may have to filter the key.
1109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label update_each;
1110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, MemOperand(sp, 4 * kPointerSize));
1111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset));
1112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r4, Operand(r2));
1113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, &update_each);
1114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
11153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // We need to filter the key, record slow-path here.
11163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int const vector_index = SmiFromSlot(slot)->value();
1117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ EmitLoadTypeFeedbackVector(r3);
1118109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ mov(r2, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate())));
1119f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ str(r2, FieldMemOperand(r3, FixedArray::OffsetOfElementAt(vector_index)));
1120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // r0 contains the key. The receiver in r1 is the second argument to the
1122c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // ForInFilter. ForInFilter returns undefined if the receiver doesn't
1123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // have the key or returns the name-converted key.
1124c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Call(isolate()->builtins()->ForInFilter(), RelocInfo::CODE_TARGET);
1125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RestoreContext();
1126bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
1127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex);
112869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ b(eq, loop_statement.continue_label());
1129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the 'each' property or variable from the possibly filtered
1131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // entry in register r0.
1132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&update_each);
1133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Perform the assignment as if via '='.
1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { EffectContext context(this);
1136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
1137bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
1141bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
1142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the body of the loop.
1143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Visit(stmt->body());
1144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the going to the next element by incrementing
1146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the index (smi) stored on top of the stack.
114769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.continue_label());
1148f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  PrepareForBailoutForId(stmt->IncrementId(), BailoutState::NO_REGISTERS);
1149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r0);
1150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(r0, r0, Operand(Smi::FromInt(1)));
1151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);
1152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBackEdgeBookkeeping(stmt, &loop);
1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ b(&loop);
1155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Remove the pointers stored on the stack.
115769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.break_label());
1158109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DropOperands(5);
1159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Exit and decrement the loop depth.
1161bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
1162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
1163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  decrement_loop_depth();
1164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
11653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
1168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          FeedbackVectorSlot slot) {
1169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(NeedsHomeObject(initializer));
1170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
1171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ldr(StoreDescriptor::ValueRegister(),
1172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         MemOperand(sp, offset * kPointerSize));
1173f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CallStoreIC(slot, isolate()->factory()->home_object_symbol());
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer,
1178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                     int offset,
1179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                     FeedbackVectorSlot slot) {
1180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(NeedsHomeObject(initializer));
1181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Move(StoreDescriptor::ReceiverRegister(), r0);
1182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ldr(StoreDescriptor::ValueRegister(),
1183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         MemOperand(sp, offset * kPointerSize));
1184f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CallStoreIC(slot, isolate()->factory()->home_object_symbol());
1185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
1189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                      TypeofMode typeof_mode,
1190589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                      Label* slow) {
1191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register current = cp;
1192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register next = r1;
1193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register temp = r2;
1194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
1196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
1197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (!s->NeedsContext()) continue;
1198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (s->calls_sloppy_eval()) {
1199f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Check that extension is "the hole".
1200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
1201f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
1202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Load next context in chain.
1204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    __ ldr(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
1205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Walk the rest of the chain without clobbering cp.
1206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    current = next;
1207f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    to_check--;
1208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // All extension objects were empty and it is safe to use a normal global
1211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // load machinery.
1212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitGlobalVariableLoad(proxy, typeof_mode);
1213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1216589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1217589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                                Label* slow) {
1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsContextSlot());
1219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register context = cp;
122059151504615d929945dc59db37bf1166937748c6Steve Block  Register next = r3;
122159151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = r4;
122259151504615d929945dc59db37bf1166937748c6Steve Block
1223589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
1224f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (s->NeedsContext()) {
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (s->calls_sloppy_eval()) {
1226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Check that extension is "the hole".
1227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ ldr(temp, ContextMemOperand(context, Context::EXTENSION_INDEX));
1228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
122959151504615d929945dc59db37bf1166937748c6Steve Block      }
1230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ ldr(next, ContextMemOperand(context, Context::PREVIOUS_INDEX));
123159151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering cp.
1232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      context = next;
123359151504615d929945dc59db37bf1166937748c6Steve Block    }
123459151504615d929945dc59db37bf1166937748c6Steve Block  }
1235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Check that last extension is "the hole".
1236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ldr(temp, ContextMemOperand(context, Context::EXTENSION_INDEX));
1237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
1238e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // This function is used only for loads, not stores, so it's safe to
1240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // return an cp-based operand (the write barrier cannot be allowed to
1241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // destroy the cp register).
1242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return ContextMemOperand(context, var->index());
124359151504615d929945dc59db37bf1166937748c6Steve Block}
124459151504615d929945dc59db37bf1166937748c6Steve Block
124559151504615d929945dc59db37bf1166937748c6Steve Block
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
1247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                  TypeofMode typeof_mode,
1248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                  Label* slow, Label* done) {
124959151504615d929945dc59db37bf1166937748c6Steve Block  // Generate fast-case code for variables that might be shadowed by
125059151504615d929945dc59db37bf1166937748c6Steve Block  // eval-introduced variables.  Eval is used a lot without
125159151504615d929945dc59db37bf1166937748c6Steve Block  // introducing variables.  In those cases, we do not want to
125259151504615d929945dc59db37bf1166937748c6Steve Block  // perform a runtime call for all variables in the scope
125359151504615d929945dc59db37bf1166937748c6Steve Block  // containing the eval.
1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Variable* var = proxy->var();
12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (var->mode() == DYNAMIC_GLOBAL) {
1256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow);
125759151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(done);
12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (var->mode() == DYNAMIC_LOCAL) {
1259589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Variable* local = var->local_if_not_shadowed();
1260589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow));
1261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (local->binding_needs_init()) {
1262589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
1263bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      __ b(ne, done);
1264bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      __ mov(r0, Operand(var->name()));
1265bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      __ push(r0);
1266bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      __ CallRuntime(Runtime::kThrowReferenceError);
1267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    } else {
1268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ jmp(done);
126959151504615d929945dc59db37bf1166937748c6Steve Block    }
127059151504615d929945dc59db37bf1166937748c6Steve Block  }
127159151504615d929945dc59db37bf1166937748c6Steve Block}
127259151504615d929945dc59db37bf1166937748c6Steve Block
1273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
1274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                         TypeofMode typeof_mode) {
12753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Record position before possible IC call.
1276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionPosition(proxy);
1277bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
12783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Variable* var = proxy->var();
12793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1280589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Three cases: global variables, lookup variables, and all other types of
1281589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // variables.
1282589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (var->location()) {
1283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::UNALLOCATED: {
1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ Global variable");
1285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      EmitGlobalVariableLoad(proxy, typeof_mode);
1286589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      context()->Plug(r0);
1287589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1288589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
128959151504615d929945dc59db37bf1166937748c6Steve Block
1290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::PARAMETER:
1291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::LOCAL:
1292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::CONTEXT: {
1293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode);
1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               : "[ Stack variable");
1296c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (proxy->hole_check_mode() == HoleCheckMode::kRequired) {
1297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        // Throw a reference error when using an uninitialized let/const
1298f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        // binding in harmony mode.
1299f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        Label done;
1300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        GetVar(r0, var);
1301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
1302f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ b(ne, &done);
1303f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ mov(r0, Operand(var->name()));
1304f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ push(r0);
1305f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ CallRuntime(Runtime::kThrowReferenceError);
1306f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ bind(&done);
1307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        context()->Plug(r0);
1308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1309589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      context()->Plug(var);
1311589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1312589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
1313d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::LOOKUP: {
1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ Lookup variable");
1316589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Label done, slow;
1317589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Generate code for loading from variables potentially shadowed
1318589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // by eval-introduced variables.
1319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done);
1320589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ bind(&slow);
1321109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Push(var->name());
1322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Runtime::FunctionId function_id =
1323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          typeof_mode == NOT_INSIDE_TYPEOF
1324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              ? Runtime::kLoadLookupSlot
1325109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch              : Runtime::kLoadLookupSlotInsideTypeof;
1326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ CallRuntime(function_id);
132769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ bind(&done);
132869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      context()->Plug(r0);
1329f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
13300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
1331f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1332f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case VariableLocation::MODULE:
1333f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UNREACHABLE();
13343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
13363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
1339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Expression* expression = (property == NULL) ? NULL : property->value();
13403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expression == NULL) {
13413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(r1, Heap::kNullValueRootIndex);
1342109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(r1);
13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForStackValue(expression);
1345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (NeedsHomeObject(expression)) {
1346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
1347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             property->kind() == ObjectLiteral::Property::SETTER);
1348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
1349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      EmitSetHomeObject(expression, offset, property->GetSlot());
1350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1355d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> constant_properties = expr->constant_properties();
1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
13606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
13613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r1, Operand(constant_properties));
1362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int flags = expr->ComputeFlags();
136344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(r0, Operand(Smi::FromInt(flags)));
1364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (MustCreateObjectLiteralWithRuntime(expr)) {
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(r3, r2, r1, r0);
1366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallRuntime(Runtime::kCreateObjectLiteral);
13673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
1370bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    RestoreContext();
1371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1372bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
1373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
1375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in r0.
1376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
1377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AccessorTable accessor_table(zone());
1379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int property_index = 0;
1380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (; property_index < expr->properties()->length(); property_index++) {
1381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ObjectLiteral::Property* property = expr->properties()->at(property_index);
1382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (property->is_computed_name()) break;
1383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
1384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Literal* key = property->key()->AsLiteral();
1386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
1387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
1388109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(r0);  // Save result on stack
1389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
1390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
1392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::CONSTANT:
1393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        UNREACHABLE();
1394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
1398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // It is safe to use [[Put]] here because the boilerplate already
1399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // contains computed properties with an uninitialized value.
1400f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if (key->IsStringLiteral()) {
1401f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          DCHECK(key->IsPropertyName());
14023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          if (property->emit_store()) {
1403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            VisitForAccumulatorValue(value);
1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            DCHECK(StoreDescriptor::ValueRegister().is(r0));
1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
1406f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            CallStoreIC(property->GetSlot(0), key->value());
1407bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
1408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            if (NeedsHomeObject(value)) {
1410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
1411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            }
1412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else {
1413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            VisitForEffect(value);
14143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          }
1415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Duplicate receiver on stack.
1418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ ldr(r0, MemOperand(sp));
1419109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(r0);
14200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(key);
14210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(value);
14223e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        if (property->emit_store()) {
1423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (NeedsHomeObject(value)) {
1424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            EmitSetHomeObject(value, 2, property->GetSlot());
1425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ mov(r0, Operand(Smi::FromInt(SLOPPY)));  // PropertyAttributes
1427109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          PushOperand(r0);
1428109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          CallRuntimeWithOperands(Runtime::kSetProperty);
14293e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        } else {
1430109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          DropOperands(3);
14313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        }
1432d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case ObjectLiteral::Property::PROTOTYPE:
1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Duplicate receiver on stack.
1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ ldr(r0, MemOperand(sp));
1436109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(r0);
1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(value);
1438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(property->emit_store());
1439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
1440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
1441bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                               BailoutState::NO_REGISTERS);
1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::GETTER:
1445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (property->emit_store()) {
144613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          AccessorTable::Iterator it = accessor_table.lookup(key);
144713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
144813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          it->second->getter = property;
1449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
14503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
1451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::SETTER:
1452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (property->emit_store()) {
145313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          AccessorTable::Iterator it = accessor_table.lookup(key);
145413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
145513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          it->second->setter = property;
1456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Emit code to define accessors, using only a single call to the runtime for
14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // each pair of corresponding getters and setters.
14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (AccessorTable::Iterator it = accessor_table.begin();
14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       it != accessor_table.end();
14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       ++it) {
14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, MemOperand(sp));  // Duplicate receiver.
1467109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(r0);
14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForStackValue(it->first);
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAccessor(it->second->getter);
14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAccessor(it->second->setter);
14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r0, Operand(Smi::FromInt(NONE)));
1472109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(r0);
1473109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
147413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
1475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Object literals have two parts. The "static" part on the left contains no
1478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // computed property names, and so we can compute its map ahead of time; see
1479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part
1480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // starts with the first computed property name, and continues with all
1481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // properties to its right.  All the code from above initializes the static
1482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // component of the object literal, and arranges for the map of the result to
1483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // reflect the static order in which the keys appear. For the dynamic
1484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // properties, we compile them into a series of "SetOwnProperty" runtime
1485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // calls. This will preserve insertion order.
1486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (; property_index < expr->properties()->length(); property_index++) {
1487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ObjectLiteral::Property* property = expr->properties()->at(property_index);
1488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Expression* value = property->value();
1490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!result_saved) {
1491109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(r0);  // Save result on the stack
1492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      result_saved = true;
1493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ldr(r0, MemOperand(sp));  // Duplicate receiver.
1496109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(r0);
1497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!property->is_computed_name());
1500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      VisitForStackValue(value);
1501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(property->emit_store());
1502109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
1503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
1504bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             BailoutState::NO_REGISTERS);
1505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
1507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      VisitForStackValue(value);
1508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (NeedsHomeObject(value)) {
1509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        EmitSetHomeObject(value, 2, property->GetSlot());
1510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      switch (property->kind()) {
1513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ObjectLiteral::Property::CONSTANT:
1514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ObjectLiteral::Property::COMPUTED:
1516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (property->emit_store()) {
1517109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            PushOperand(Smi::FromInt(NONE));
1518109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
1519109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
152013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
152113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                   BailoutState::NO_REGISTERS);
1522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else {
1523109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            DropOperands(3);
1524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
1525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
1526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ObjectLiteral::Property::PROTOTYPE:
1528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          UNREACHABLE();
1529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
1530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ObjectLiteral::Property::GETTER:
1532109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          PushOperand(Smi::FromInt(NONE));
1533109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked);
1534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
1535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ObjectLiteral::Property::SETTER:
1537109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          PushOperand(Smi::FromInt(NONE));
1538109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked);
1539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
1540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1544e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
15450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
15470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
15483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
15493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
15503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1552d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
15533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
1554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> constant_elements = expr->constant_elements();
1556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool has_fast_elements =
1557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      IsFastObjectElementsKind(expr->constant_elements_kind());
15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArrayBase> constant_elements_values(
15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FixedArrayBase::cast(constant_elements->get(1)));
1560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (has_fast_elements && !FLAG_allocation_site_pretenuring) {
1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If the only customer of allocation sites is transitioning, then
1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // we can turn it off if we don't have anywhere else to transition to.
1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
15693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r1, Operand(constant_elements));
1571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (MustCreateArrayLiteralWithRuntime(expr)) {
1572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(r0, Operand(Smi::FromInt(expr->ComputeFlags())));
1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(r3, r2, r1, r0);
1574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallRuntime(Runtime::kCreateArrayLiteral);
1575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
1577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
1578f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    RestoreContext();
15793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1580bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
15813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
1583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneList<Expression*>* subexprs = expr->values();
1584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int length = subexprs->length();
15853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
15873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
1588f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  for (int array_index = 0; array_index < length; array_index++) {
1589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Expression* subexpr = subexprs->at(array_index);
1590109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(!subexpr->IsSpread());
1591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
15923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
15933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
15953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
1597109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(r0);
15983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
15993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
16000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(subexpr);
16013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(StoreDescriptor::NameRegister(), Operand(Smi::FromInt(array_index)));
1603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp, 0));
1604f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    CallKeyedStoreIC(expr->LiteralFeedbackSlot());
1605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(expr->GetIdForElement(array_index),
1607bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           BailoutState::NO_REGISTERS);
16083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
16093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
16110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
16130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
16143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
16153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1618402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1621402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Comment cmnt(masm_, "[ Assignment");
1622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
162380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Property* property = expr->target()->AsProperty();
1624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LhsKind assign_type = Property::GetAssignType(property);
1625402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1626402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate LHS expression.
1627402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1628402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1629402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Nothing to do here.
1630402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1631402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1632402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // We need the receiver both on the stack and in the register.
1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->obj());
1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
1636402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
16370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
1638402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1639402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1640958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    case NAMED_SUPER_PROPERTY:
1641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      VisitForStackValue(
1642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          property->obj()->AsSuperPropertyReference()->this_var());
1643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      VisitForAccumulatorValue(
1644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          property->obj()->AsSuperPropertyReference()->home_object());
1645109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(result_register());
1646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (expr->is_compound()) {
1647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        const Register scratch = r1;
1648958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ ldr(scratch, MemOperand(sp, kPointerSize));
1649109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(scratch);
1650109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(result_register());
1651958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1652958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
1653958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    case KEYED_SUPER_PROPERTY:
1654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      VisitForStackValue(
1655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          property->obj()->AsSuperPropertyReference()->this_var());
1656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      VisitForStackValue(
1657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          property->obj()->AsSuperPropertyReference()->home_object());
1658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      VisitForAccumulatorValue(property->key());
1659109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(result_register());
1660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (expr->is_compound()) {
1661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        const Register scratch = r1;
1662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
1663109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(scratch);
1664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
1665109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(scratch);
1666109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(result_register());
1667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
1669402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
167025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      if (expr->is_compound()) {
16713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->obj());
1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->key());
1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ ldr(LoadDescriptor::ReceiverRegister(),
1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               MemOperand(sp, 1 * kPointerSize));
1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0));
167625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      } else {
16773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->obj());
16783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->key());
167925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      }
1680402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1681402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1682402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
16838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // For compound assignments we need another deoptimization point after the
16848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // variable/property load.
1685402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
16860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    { AccumulatorValueContext context(this);
16870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
16880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
16893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          EmitVariableLoad(expr->target()->AsVariableProxy());
1690bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
16910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
16920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
16930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitNamedPropertyLoad(property);
1694bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          PrepareForBailoutForId(property->LoadId(),
1695bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                 BailoutState::TOS_REGISTER);
16960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
1697958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        case NAMED_SUPER_PROPERTY:
1698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          EmitNamedSuperPropertyLoad(property);
1699bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          PrepareForBailoutForId(property->LoadId(),
1700bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                 BailoutState::TOS_REGISTER);
1701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          break;
1702958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        case KEYED_SUPER_PROPERTY:
1703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          EmitKeyedSuperPropertyLoad(property);
1704bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          PrepareForBailoutForId(property->LoadId(),
1705bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                 BailoutState::TOS_REGISTER);
1706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          break;
17070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
17080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitKeyedPropertyLoad(property);
1709bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          PrepareForBailoutForId(property->LoadId(),
1710bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                 BailoutState::TOS_REGISTER);
17110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
17120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
1713402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1714402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
171580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Token::Value op = expr->binary_op();
1716109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(r0);  // Left operand goes on the stack.
1717e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    VisitForAccumulatorValue(expr->value());
1718402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
17190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
172080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (ShouldInlineSmiCase(op)) {
1721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitInlineSmiBinaryOp(expr->binary_operation(),
172280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            op,
172380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            expr->target(),
1724e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                            expr->value());
172580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    } else {
1726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      EmitBinaryOp(expr->binary_operation(), op);
172780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
1728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Deoptimization point in case the binary operation may have side effects.
1730bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
173180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
17320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->value());
1733402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1734402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionPosition(expr);
1736402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1737402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Store the value.
1738402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1739c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    case VARIABLE: {
1740c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      VariableProxy* proxy = expr->target()->AsVariableProxy();
1741c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(),
1742c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                             proxy->hole_check_mode());
1743bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
1744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      context()->Plug(r0);
1745402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1746c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1747402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1748402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitNamedPropertyAssignment(expr);
1749402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    case NAMED_SUPER_PROPERTY:
1751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      EmitNamedSuperPropertyStore(property);
1752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      context()->Plug(r0);
1753958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
1754958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    case KEYED_SUPER_PROPERTY:
1755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      EmitKeyedSuperPropertyStore(property);
1756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      context()->Plug(r0);
1757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
1758402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1759402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitKeyedPropertyAssignment(expr);
1760402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1761402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1762402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1763402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1764402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitYield(Yield* expr) {
1766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ Yield");
1767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionPosition(expr);
1768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Evaluate yielded value first; the initial iterator definition depends on
1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this.  It stays on the stack while we update the iterator.
1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(expr->expression());
1772e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1773bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label suspend, continuation, post_runtime, resume, exception;
17743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ jmp(&suspend);
17763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ bind(&continuation);
1777bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // When we arrive here, r0 holds the generator object.
17783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ RecordGeneratorContinuation();
1779bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ ldr(r1, FieldMemOperand(r0, JSGeneratorObject::kResumeModeOffset));
178013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ ldr(r0, FieldMemOperand(r0, JSGeneratorObject::kInputOrDebugPosOffset));
1781bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
1782bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
1783bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ cmp(r1, Operand(Smi::FromInt(JSGeneratorObject::kReturn)));
1784bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ b(lt, &resume);
1785bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ Push(result_register());
1786bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ b(gt, &exception);
17873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  EmitCreateIteratorResult(true);
17883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  EmitUnwindAndReturn();
17893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1790bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ bind(&exception);
1791f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ CallRuntime(expr->rethrow_on_exception() ? Runtime::kReThrow
1792f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                              : Runtime::kThrow);
1793bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
17943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ bind(&suspend);
17953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  OperandStackDepthIncrement(1);  // Not popped on this path.
17963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  VisitForAccumulatorValue(expr->generator_object());
17973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
17983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ mov(r1, Operand(Smi::FromInt(continuation.pos())));
17993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset));
18003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset));
18013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ mov(r1, cp);
18023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2,
18033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                      kLRHasBeenSaved, kDontSaveFPRegs);
18043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ add(r1, fp, Operand(StandardFrameConstants::kExpressionsOffset));
18053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ cmp(sp, r1);
18063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ b(eq, &post_runtime);
18073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ push(r0);  // generator object
18083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
1809bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  RestoreContext();
18103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ bind(&post_runtime);
18113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  PopOperand(result_register());
18123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  EmitReturnSequence();
1813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
18143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ bind(&resume);
18153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  context()->Plug(result_register());
1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1817e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1818109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::PushOperands(Register reg1, Register reg2) {
1819109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthIncrement(2);
1820109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Push(reg1, reg2);
1821109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1822109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1823109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::PopOperands(Register reg1, Register reg2) {
1824109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(2);
1825109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Pop(reg1, reg2);
1826109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1827109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1828109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::EmitOperandStackDepthCheck() {
1829109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (FLAG_debug_code) {
1830109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp +
1831109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                        operand_stack_depth_ * kPointerSize;
1832109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ sub(r0, fp, sp);
1833109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ cmp(r0, Operand(expected_diff));
1834109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Assert(eq, kUnexpectedStackDepth);
1835109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
1836109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCreateIteratorResult(bool done) {
1839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label allocate, done_allocate;
1840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1841bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ Allocate(JSIteratorResult::kSize, r0, r2, r3, &allocate,
1842bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              NO_ALLOCATION_FLAGS);
1843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ b(&done_allocate);
1844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&allocate);
1846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Push(Smi::FromInt(JSIteratorResult::kSize));
1847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace);
1848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&done_allocate);
1850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, r1);
18513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  PopOperand(r2);
1852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(r3,
1853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex);
1854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex);
1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset));
1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
1858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ str(r2, FieldMemOperand(r0, JSIteratorResult::kValueOffset));
1859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ str(r3, FieldMemOperand(r0, JSIteratorResult::kDoneOffset));
1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Token::Value op,
1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Expression* left_expr,
1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Expression* right_expr) {
1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, smi_case, stub_call;
1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch1 = r2;
1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch2 = r3;
1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the arguments.
1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register left = r1;
1874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register right = r0;
1875109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(left);
1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Perform combined smi check on both operands.
1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ orr(scratch1, left, Operand(right));
1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpPatchSite patch_site(masm_);
1881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  patch_site.EmitJumpIfSmi(scratch1, &smi_case);
1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&stub_call);
1884109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(code, expr->BinaryOperationFeedbackId());
1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  patch_site.EmitPatchInfo();
1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done);
1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&smi_case);
1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Smi case. This code works the same way as the smi-smi case in the type
1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // recording binary operation stub, see
1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (op) {
1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::SAR:
1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ GetLeastBitsFromSmi(scratch1, right, 5);
1895e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(right, Operand(left, ASR, scratch1));
1896e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ bic(right, right, Operand(kSmiTagMask));
1897e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1898e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::SHL: {
1899e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ SmiUntag(scratch1, left);
1900e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ GetLeastBitsFromSmi(scratch2, right, 5);
1901e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(scratch1, Operand(scratch1, LSL, scratch2));
1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ TrySmiTag(right, scratch1, &stub_call);
1903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1904e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1905e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::SHR: {
1906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ SmiUntag(scratch1, left);
1907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ GetLeastBitsFromSmi(scratch2, right, 5);
1908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(scratch1, Operand(scratch1, LSR, scratch2));
1909e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ tst(scratch1, Operand(0xc0000000));
1910e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(ne, &stub_call);
1911e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ SmiTag(right, scratch1);
1912e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1913e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1914e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::ADD:
1915e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ add(scratch1, left, Operand(right), SetCC);
1916e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(vs, &stub_call);
1917e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(right, scratch1);
1918e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1919e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::SUB:
1920e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ sub(scratch1, left, Operand(right), SetCC);
1921e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(vs, &stub_call);
1922e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(right, scratch1);
1923e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1924e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::MUL: {
1925e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ SmiUntag(ip, right);
1926e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ smull(scratch1, scratch2, left, ip);
1927e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(ip, Operand(scratch1, ASR, 31));
1928e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ cmp(ip, Operand(scratch2));
1929e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(ne, &stub_call);
1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmp(scratch1, Operand::Zero());
1931e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(right, Operand(scratch1), LeaveCC, ne);
1932e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(ne, &done);
1933e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ add(scratch2, right, Operand(left), SetCC);
1934c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      __ mov(right, Operand(Smi::kZero), LeaveCC, pl);
1935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(mi, &stub_call);
1936e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1937e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1938e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::BIT_OR:
1939e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ orr(right, left, Operand(right));
1940e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1941e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::BIT_AND:
1942e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ and_(right, left, Operand(right));
1943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1944e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::BIT_XOR:
1945e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ eor(right, left, Operand(right));
1946e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1947e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    default:
1948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      UNREACHABLE();
1949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1950e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1951e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&done);
1952e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  context()->Plug(r0);
195380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
195480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
195580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1956958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
1957958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (int i = 0; i < lit->properties()->length(); i++) {
1958f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    ClassLiteral::Property* property = lit->properties()->at(i);
1959958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Expression* value = property->value();
1960958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1961109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Register scratch = r1;
1962958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (property->is_static()) {
1963958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ ldr(scratch, MemOperand(sp, kPointerSize));  // constructor
1964958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
1965958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ ldr(scratch, MemOperand(sp, 0));  // prototype
1966958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
1967109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(scratch);
1968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    EmitPropertyKey(property, lit->GetIdForProperty(i));
1969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // The static prototype property is read only. We handle the non computed
1971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // property name case in the parser. Since this is the only case where we
1972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // need to check for an own read only property we special case this so we do
1973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // not need to do this for every property.
1974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (property->is_static() && property->is_computed_name()) {
1975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ CallRuntime(Runtime::kThrowIfStaticPrototype);
1976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ push(r0);
1977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1979958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    VisitForStackValue(value);
1980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (NeedsHomeObject(value)) {
1981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      EmitSetHomeObject(value, 2, property->GetSlot());
1982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1983958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1984958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (property->kind()) {
1985f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      case ClassLiteral::Property::METHOD:
1986109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(Smi::FromInt(DONT_ENUM));
1987109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
1988109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
1989958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1990958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1991f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      case ClassLiteral::Property::GETTER:
1992109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(Smi::FromInt(DONT_ENUM));
1993109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked);
1994958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1995958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1996f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      case ClassLiteral::Property::SETTER:
1997109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(Smi::FromInt(DONT_ENUM));
1998109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked);
1999958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
2000958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2001f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      case ClassLiteral::Property::FIELD:
2002958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      default:
2003958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        UNREACHABLE();
2004958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2006958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2007958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2008958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
2010109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(r1);
2011109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
20123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(code, expr->BinaryOperationFeedbackId());
20143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
20150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2016e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2018e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr,
2020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       FeedbackVectorSlot slot) {
2021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(expr->IsValidReferenceExpressionOrThis());
2022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = expr->AsProperty();
2024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LhsKind assign_type = Property::GetAssignType(prop);
2025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (assign_type) {
2027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case VARIABLE: {
2028c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      VariableProxy* proxy = expr->AsVariableProxy();
20290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EffectContext context(this);
2030c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot,
2031c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                             proxy->hole_check_mode());
2032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case NAMED_PROPERTY: {
2035109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(r0);  // Preserve value.
20360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(StoreDescriptor::ReceiverRegister(), r0);
2038109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(StoreDescriptor::ValueRegister());  // Restore value.
2039f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      CallStoreIC(slot, prop->key()->AsLiteral()->value());
2040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2042958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    case NAMED_SUPER_PROPERTY: {
2043109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(r0);
2044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
2045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      VisitForAccumulatorValue(
2046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          prop->obj()->AsSuperPropertyReference()->home_object());
2047958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // stack: value, this; r0: home_object
2048958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Register scratch = r2;
2049958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Register scratch2 = r3;
2050958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ mov(scratch, result_register());              // home_object
2051958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ ldr(r0, MemOperand(sp, kPointerSize));        // value
2052958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ ldr(scratch2, MemOperand(sp, 0));             // this
2053958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ str(scratch2, MemOperand(sp, kPointerSize));  // this
2054958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ str(scratch, MemOperand(sp, 0));              // home_object
2055958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // stack: this, home_object; r0: value
2056958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      EmitNamedSuperPropertyStore(prop);
2057958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
2058958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2059958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    case KEYED_SUPER_PROPERTY: {
2060109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(r0);
2061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
2062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      VisitForStackValue(
2063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          prop->obj()->AsSuperPropertyReference()->home_object());
2064958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      VisitForAccumulatorValue(prop->key());
2065958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Register scratch = r2;
2066958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Register scratch2 = r3;
2067958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ ldr(scratch2, MemOperand(sp, 2 * kPointerSize));  // value
2068958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // stack: value, this, home_object; r0: key, r3: value
2069958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ ldr(scratch, MemOperand(sp, kPointerSize));  // this
2070958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ str(scratch, MemOperand(sp, 2 * kPointerSize));
2071958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ ldr(scratch, MemOperand(sp, 0));  // home_object
2072958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ str(scratch, MemOperand(sp, kPointerSize));
2073958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ str(r0, MemOperand(sp, 0));
2074958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ Move(r0, scratch2);
2075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // stack: this, home_object, key; r0: value.
2076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      EmitKeyedSuperPropertyStore(prop);
2077958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
2078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case KEYED_PROPERTY: {
2080109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(r0);  // Preserve value.
20813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForStackValue(prop->obj());
20823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForAccumulatorValue(prop->key());
2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(StoreDescriptor::NameRegister(), r0);
2084109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperands(StoreDescriptor::ValueRegister(),
2085109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                  StoreDescriptor::ReceiverRegister());
2086f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      CallKeyedStoreIC(slot);
2087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(r0);
2091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Variable* var, MemOperand location) {
2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(result_register(), location);
2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (var->IsContextSlot()) {
2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // RecordWrite may destroy all its register arguments.
2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(r3, result_register());
2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int offset = Context::SlotOffset(var->index());
2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ RecordWriteContextSlot(
2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs);
2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
2107c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                               FeedbackVectorSlot slot,
2108c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                               HoleCheckMode hole_check_mode) {
2109589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsUnallocated()) {
2110589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Global var, const, or let.
2111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
2112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    CallStoreIC(slot, var->name());
2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
2115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!var->IsLookupSlot());
2116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MemOperand location = VarOperand(var, r1);
2118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Perform an initialization check for lexically declared variables.
2119c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (hole_check_mode == HoleCheckMode::kRequired) {
2120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Label assign;
2121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ ldr(r3, location);
2122f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
2123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ b(ne, &assign);
2124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ mov(r3, Operand(var->name()));
2125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ push(r3);
2126f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ CallRuntime(Runtime::kThrowReferenceError);
2127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ bind(&assign);
2128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
2129f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (var->mode() != CONST) {
2130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      EmitStoreToStackLocalOrContextSlot(var, location);
2131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    } else if (var->throw_on_const_assignment(language_mode())) {
2132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      __ CallRuntime(Runtime::kThrowConstAssignError);
2133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) {
2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Initializing assignment to const {this} needs a write barrier.
2136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label uninitialized_this;
2138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MemOperand location = VarOperand(var, r1);
2139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ldr(r3, location);
2140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
2141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ b(eq, &uninitialized_this);
2142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(r0, Operand(var->name()));
2143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Push(r0);
2144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallRuntime(Runtime::kThrowReferenceError);
2145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&uninitialized_this);
2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    EmitStoreToStackLocalOrContextSlot(var, location);
2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2148f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } else {
2149f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK(var->mode() != CONST || op == Token::INIT);
2150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (var->IsLookupSlot()) {
2151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Assignment to var.
2152109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Push(var->name());
2153109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Push(r0);
2154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ CallRuntime(is_strict(language_mode())
2155109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                         ? Runtime::kStoreLookupSlot_Strict
2156109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                         : Runtime::kStoreLookupSlot_Sloppy);
2157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
2158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Assignment to var or initializing assignment to let/const in harmony
2159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // mode.
2160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK((var->IsStackAllocated() || var->IsContextSlot()));
2161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      MemOperand location = VarOperand(var, r1);
2162109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) {
2163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Check for an uninitialized let binding.
2164589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ ldr(r2, location);
2165589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Check(eq, kLetBindingReInitialization);
2167589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitStoreToStackLocalOrContextSlot(var, location);
21693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
21703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
21713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
21723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
21733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2174d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
2176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(prop != NULL);
2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(prop->key()->IsLiteral());
2179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2180109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(StoreDescriptor::ReceiverRegister());
2181f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CallStoreIC(expr->AssignmentSlot(), prop->key()->AsLiteral()->value());
2182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2183bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(r0);
2185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
2189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Assignment to named property of super.
2190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r0 : value
2191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // stack : receiver ('this'), home_object
2192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(prop != NULL);
2193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Literal* key = prop->key()->AsLiteral();
2194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(key != NULL);
2195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2196109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(key->value());
2197109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(r0);
2198109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CallRuntimeWithOperands(is_strict(language_mode())
2199109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                              ? Runtime::kStoreToSuper_Strict
2200109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                              : Runtime::kStoreToSuper_Sloppy);
2201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
2205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Assignment to named property of super.
2206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r0 : value
2207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // stack : receiver ('this'), home_object, key
2208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(prop != NULL);
2209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2210109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(r0);
2211109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CallRuntimeWithOperands(is_strict(language_mode())
2212109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                              ? Runtime::kStoreKeyedToSuper_Strict
2213109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                              : Runtime::kStoreKeyedToSuper_Sloppy);
2214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2217d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
2219109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperands(StoreDescriptor::ReceiverRegister(),
2220109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch              StoreDescriptor::NameRegister());
2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(StoreDescriptor::ValueRegister().is(r0));
2222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2223f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CallKeyedStoreIC(expr->AssignmentSlot());
2224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2225bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->Plug(r0);
2227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC.
2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
2231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Expression* callee = expr->expression();
2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the target function.
2234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ConvertReceiverMode convert_mode;
2235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (callee->IsVariableProxy()) {
2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    { StackValueContext context(this);
2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitVariableLoad(callee->AsVariableProxy());
2238bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
22393e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push undefined as receiver. This is patched in the method prologue if it
2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // is a sloppy mode method.
2242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
2243109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(ip);
2244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    convert_mode = ConvertReceiverMode::kNullOrUndefined;
2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load the function from the receiver.
2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(callee->IsProperty());
2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!callee->AsProperty()->IsSuperAccess());
2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitNamedPropertyLoad(callee->AsProperty());
2251bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
2252bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           BailoutState::TOS_REGISTER);
2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push the target function under the receiver.
2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(ip, MemOperand(sp, 0));
2255109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(ip);
2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ str(r0, MemOperand(sp, kPointerSize));
2257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
22583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitCall(expr, convert_mode);
2261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Expression* callee = expr->expression();
2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(callee->IsProperty());
2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Property* prop = callee->AsProperty();
2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(prop->IsSuperAccess());
2269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionPosition(prop);
2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Literal* key = prop->key()->AsLiteral();
2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!key->value()->IsSmi());
2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the function from the receiver.
2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const Register scratch = r1;
2275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
2276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForStackValue(super_ref->home_object());
2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(super_ref->this_var());
2278109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(r0);
2279109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(r0);
2280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ldr(scratch, MemOperand(sp, kPointerSize * 2));
2281109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(scratch);
2282109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(key->value());
2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Stack here:
2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  - home_object
2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  - this (receiver)
2287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  - this (receiver) <-- LoadFromSuper will pop here and below.
2288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  - home_object
2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  - key
2290109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CallRuntimeWithOperands(Runtime::kLoadFromSuper);
2291bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Replace home_object with target function.
2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r0, MemOperand(sp, kPointerSize));
2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Stack here:
2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // - target function
2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // - this (receiver)
2299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitCall(expr);
2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC.
2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Expression* key) {
23068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the key.
23078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForAccumulatorValue(key);
23088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Expression* callee = expr->expression();
23108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the function from the receiver.
2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(callee->IsProperty());
2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(LoadDescriptor::NameRegister(), r0);
2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitKeyedPropertyLoad(callee->AsProperty());
2316bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
2317bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                         BailoutState::TOS_REGISTER);
2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push the target function under the receiver.
2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(ip, MemOperand(sp, 0));
2321109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(ip);
2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r0, MemOperand(sp, kPointerSize));
2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined);
23259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
23269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
23279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
2329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Expression* callee = expr->expression();
2330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(callee->IsProperty());
2331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Property* prop = callee->AsProperty();
2332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(prop->IsSuperAccess());
2333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionPosition(prop);
2335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load the function from the receiver.
2336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const Register scratch = r1;
2337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
2338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForStackValue(super_ref->home_object());
2339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  VisitForAccumulatorValue(super_ref->this_var());
2340109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(r0);
2341109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(r0);
2342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ldr(scratch, MemOperand(sp, kPointerSize * 2));
2343109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(scratch);
2344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  VisitForStackValue(prop->key());
2345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Stack here:
2347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  - home_object
2348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  - this (receiver)
2349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
2350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  - home_object
2351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  - key
2352109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
2353bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
2354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Replace home_object with target function.
2356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ str(r0, MemOperand(sp, kPointerSize));
2357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Stack here:
2359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // - target function
2360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // - this (receiver)
2361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitCall(expr);
2362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the arguments.
2367d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2368d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
2369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (int i = 0; i < arg_count; i++) {
2370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    VisitForStackValue(args->at(i));
2371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2373bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
23743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  SetCallPosition(expr, expr->tail_call_mode());
2375109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (expr->tail_call_mode() == TailCallMode::kAllow) {
2376109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (FLAG_trace) {
2377109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ CallRuntime(Runtime::kTraceTailCall);
2378109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
2379109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Update profiling counters before the tail call since we will
2380109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // not return to this function.
2381109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    EmitProfilingCounterHandlingForReturnSequence(true);
2382109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
2383c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<Code> code =
2384c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      CodeFactory::CallIC(isolate(), mode, expr->tail_call_mode()).code();
2385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(r3, Operand(SmiFromSlot(expr->CallFeedbackICSlot())));
23863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2387c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ mov(r0, Operand(arg_count));
2388c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CallIC(code);
2389109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(arg_count + 1);
2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RecordJSReturnSite(expr);
2392bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  RestoreContext();
23930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->DropAndPlug(1, r0);
2394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2396bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
2397bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  int arg_count = expr->arguments()->length();
2398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r4: copy of the first argument or undefined if it doesn't exist.
2399e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (arg_count > 0) {
2400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ldr(r4, MemOperand(sp, arg_count * kPointerSize));
2401e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
2402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
2403e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2404e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r3: the receiver of the enclosing function.
2406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
2407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r2: language mode.
2409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(r2, Operand(Smi::FromInt(language_mode())));
2410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r1: the start position of the scope the calls resides in.
24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r1, Operand(Smi::FromInt(scope()->start_position())));
24133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2414bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // r0: the source position of the eval call.
2415bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ mov(r0, Operand(Smi::FromInt(expr->position())));
2416bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
24173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do the runtime call.
2418bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ Push(r4, r3, r2, r1, r0);
2419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
2420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
2424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
2425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VariableProxy* callee = expr->expression()->AsVariableProxy();
2426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (callee->var()->IsLookupSlot()) {
242759151504615d929945dc59db37bf1166937748c6Steve Block    Label slow, done;
2428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SetExpressionPosition(callee);
2429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Generate code for loading from variables potentially shadowed
2430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // by eval-introduced variables.
2431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
243259151504615d929945dc59db37bf1166937748c6Steve Block
243359151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
24340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Call the runtime to find the function to call (returned in r0)
243559151504615d929945dc59db37bf1166937748c6Steve Block    // and the object holding it (returned in edx).
2436109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Push(callee->name());
2437109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ CallRuntime(Runtime::kLoadLookupSlotForCall);
2438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperands(r0, r1);  // Function, receiver.
2439bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
244059151504615d929945dc59db37bf1166937748c6Steve Block
244159151504615d929945dc59db37bf1166937748c6Steve Block    // If fast case code has been generated, emit code to push the
244259151504615d929945dc59db37bf1166937748c6Steve Block    // function and receiver and have the slow path jump around this
244359151504615d929945dc59db37bf1166937748c6Steve Block    // code.
244459151504615d929945dc59db37bf1166937748c6Steve Block    if (done.is_linked()) {
244559151504615d929945dc59db37bf1166937748c6Steve Block      Label call;
244659151504615d929945dc59db37bf1166937748c6Steve Block      __ b(&call);
244759151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&done);
244859151504615d929945dc59db37bf1166937748c6Steve Block      // Push function.
244959151504615d929945dc59db37bf1166937748c6Steve Block      __ push(r0);
24503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // The receiver is implicitly the global receiver. Indicate this
24513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // by passing the hole to the call function stub.
2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
245359151504615d929945dc59db37bf1166937748c6Steve Block      __ push(r1);
245459151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&call);
245559151504615d929945dc59db37bf1166937748c6Steve Block    }
24563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    VisitForStackValue(callee);
2458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // refEnv.WithBaseObject()
2459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
2460109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(r2);  // Reserved receiver slot.
24613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
2466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // In a call to eval, we first call
2467bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Runtime_ResolvePossiblyDirectEval to resolve the function we need
2468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to call.  Then we call the resolved function using the given arguments.
2469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
2470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int arg_count = args->length();
2471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  PushCalleeAndWithBaseObject(expr);
2473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push the arguments.
2475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (int i = 0; i < arg_count; i++) {
2476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    VisitForStackValue(args->at(i));
2477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push a copy of the function (found below the arguments) and
2480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // resolve eval.
2481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ push(r1);
2483bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  EmitResolvePossiblyDirectEval(expr);
2484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Touch up the stack with the resolved function.
2486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
2487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2488bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
2489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Record source position for debugger.
2491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetCallPosition(expr);
2492c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<Code> code = CodeFactory::CallIC(isolate(), ConvertReceiverMode::kAny,
2493c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                          expr->tail_call_mode())
2494c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                          .code();
2495c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ mov(r3, Operand(SmiFromSlot(expr->CallFeedbackICSlot())));
2496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(r0, Operand(arg_count));
2498c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Call(code, RelocInfo::CODE_TARGET);
2499109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(arg_count + 1);
2500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RecordJSReturnSite(expr);
2501bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  RestoreContext();
2502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->DropAndPlug(1, r0);
25033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
25043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
25053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2506d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
2507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
2508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
2509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
2510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
251180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
251280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Push constructor on the stack.  If it's not a function it's used as
251380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
251480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ignored.
2515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!expr->expression()->IsSuperPropertyReference());
2516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForStackValue(expr->expression());
2517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
2519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2520d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
2521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
25220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
2523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
2526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
2527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetConstructCallPosition(expr);
2528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
252980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load function and argument count into r1 and r0.
2530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(r0, Operand(arg_count));
253180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
2532d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Record call targets in unoptimized code.
2534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ EmitLoadTypeFeedbackVector(r2);
2535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r3, Operand(SmiFromSlot(expr->CallNewFeedbackSlot())));
2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallConstructStub stub(isolate());
2538c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CallIC(stub.GetCode());
2539109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(arg_count + 1);
2540bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
2541bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  RestoreContext();
25420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
2547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SuperCallReference* super_call_ref =
2548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      expr->expression()->AsSuperCallReference();
2549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_NOT_NULL(super_call_ref);
2550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push the super constructor target on the stack (may be null,
2552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // but the Construct builtin can deal with that properly).
2553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForAccumulatorValue(super_call_ref->this_function_var());
2554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ AssertFunction(result_register());
2555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ldr(result_register(),
2556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         FieldMemOperand(result_register(), HeapObject::kMapOffset));
2557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ldr(result_register(),
2558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         FieldMemOperand(result_register(), Map::kPrototypeOffset));
2559109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(result_register());
2560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push the arguments ("left-to-right") on the stack.
2562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
2563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int arg_count = args->length();
2564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (int i = 0; i < arg_count; i++) {
2565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    VisitForStackValue(args->at(i));
2566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Call the construct call builtin that handles allocation and
2569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // constructor invocation.
2570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetConstructCallPosition(expr);
2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load new target into r3.
2573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForAccumulatorValue(super_call_ref->new_target_var());
2574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(r3, result_register());
2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load function and argument count into r1 and r0.
2577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(r0, Operand(arg_count));
2578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
2579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
2581109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(arg_count + 1);
2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RecordJSReturnSite(expr);
2584bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  RestoreContext();
2585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->Plug(r0);
2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
2592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
259880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
26000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
260180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
26023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ SmiTst(r0);
2604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Split(eq, if_true, if_false, fall_through);
2605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsJSReceiver(CallRuntime* expr) {
26113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
26133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
26140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
26153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
26163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label materialize_true, materialize_false;
26173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_true = NULL;
26183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_false = NULL;
261980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
26200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
26210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
26223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
26231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, if_false);
2624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareObjectType(r0, r1, r1, FIRST_JS_RECEIVER_TYPE);
26253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
262680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(ge, if_true, if_false, fall_through);
26273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
26280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
26293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
26303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
26313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
26323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
26333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
2635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
264180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
26420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
26430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, if_false);
2646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
26473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
264880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
2649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsTypedArray(CallRuntime* expr) {
26553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
2657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2659f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
266380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
2664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
2665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         &if_false, &fall_through);
2666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, if_false);
2668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareObjectType(r0, r1, r1, JS_TYPED_ARRAY_TYPE);
26693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
267080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
2671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
2677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ZoneList<Expression*>* args = expr->arguments();
2678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(args->length() == 1);
2679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  VisitForAccumulatorValue(args->at(0));
2681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label materialize_true, materialize_false;
2683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label* if_true = NULL;
2684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label* if_false = NULL;
2685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label* fall_through = NULL;
2686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
2687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         &if_true, &if_false, &fall_through);
2688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2689958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfSmi(r0, if_false);
2690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
2691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Split(eq, if_true, if_false, fall_through);
2693958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  context()->Plug(if_true, if_false);
2695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) {
2699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
2700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(args->length() == 1);
2701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForAccumulatorValue(args->at(0));
2703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
270780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
2708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
2709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         &if_false, &fall_through);
2710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ JumpIfSmi(r0, if_false);
2712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareObjectType(r0, r1, r1, JS_PROXY_TYPE);
27133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
271480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
2715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
27213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
2723f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, null, function, non_function_constructor;
2724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // If the object is not a JSReceiver, we return null.
27281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, &null);
2729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
2730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareObjectType(r0, r0, r1, FIRST_JS_RECEIVER_TYPE);
27313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Map is now in r0.
2732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(lt, &null);
27333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Return 'Function' for JSFunction and JSBoundFunction objects.
27353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ cmp(r1, Operand(FIRST_FUNCTION_TYPE));
27363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
27373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ b(hs, &function);
27383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the constructor in the map is a JS function.
2740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register instance_type = r2;
2741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ GetMapConstructor(r0, r0, r1, instance_type);
2742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ cmp(instance_type, Operand(JS_FUNCTION_TYPE));
2743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &non_function_constructor);
2744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r0 now contains the constructor function. Grab the
2746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // instance class name from there.
2747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
2748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset));
2749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(&done);
2750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Functions have class 'Function'.
2752f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&function);
2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(r0, Heap::kFunction_stringRootIndex);
2754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Objects with a non-function constructor have class 'Object'.
2757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&non_function_constructor);
2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(r0, Heap::kObject_stringRootIndex);
2759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-JS objects have class null.
2762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&null);
2763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(r0, Heap::kNullValueRootIndex);
2764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // All done.
2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
27733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
27750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
27760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
27777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = r1;
27797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = r0;
27807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = r3;
27817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2782109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(object);
27837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
27857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
27867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
278713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
278813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                      &need_conversion, &index_out_of_range);
27897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
27907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
27917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
27937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
27947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // NaN.
27957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kNanValueRootIndex);
27967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
27977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
27997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Load the undefined value into the result register, which will
28007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // trigger conversion.
28017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
28027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
28037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
2805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
28067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
28080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
28097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
28107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCall(CallRuntime* expr) {
28133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_LE(2, args->length());
2815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push target, receiver and arguments onto the stack.
2816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (Expression* const arg : *args) {
2817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    VisitForStackValue(arg);
2818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2819bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
2820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Move target to r1.
2821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int const argc = args->length() - 2;
2822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize));
2823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Call the target.
2824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(r0, Operand(argc));
2825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
2826109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(argc + 1);
2827bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  RestoreContext();
2828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Discard the function left on TOS.
2829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->DropAndPlug(1, r0);
2830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) {
2833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
2834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, args->length());
2835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForAccumulatorValue(args->at(0));
2836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ AssertFunction(r0);
2837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
2838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ldr(r0, FieldMemOperand(r0, Map::kPrototypeOffset));
2839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->Plug(r0);
2840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
2843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->arguments()->length() == 0);
2844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference debug_is_active =
2845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::debug_is_active_address(isolate());
2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ip, Operand(debug_is_active));
2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldrb(r0, MemOperand(ip));
2848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTag(r0);
2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(r0);
2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
2854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
2855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(2, args->length());
2856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForStackValue(args->at(0));
2857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForStackValue(args->at(1));
2858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label runtime, done;
2860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2861bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ Allocate(JSIteratorResult::kSize, r0, r2, r3, &runtime,
2862bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              NO_ALLOCATION_FLAGS);
2863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, r1);
2864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ pop(r3);
2865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ pop(r2);
2866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex);
2867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset));
2869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
2870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ str(r2, FieldMemOperand(r0, JSIteratorResult::kValueOffset));
2871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ str(r3, FieldMemOperand(r0, JSIteratorResult::kDoneOffset));
2872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
2873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ b(&done);
2874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&runtime);
2876109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CallRuntimeWithOperands(Runtime::kCreateIterResultObject);
2877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&done);
2879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->Plug(r0);
2880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
28843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Push function.
28853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ LoadNativeContextSlot(expr->context_index(), r0);
28863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  PushOperand(r0);
28873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push undefined as the receiver.
2889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
2890109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(r0);
2891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
28953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* args = expr->arguments();
2896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int arg_count = args->length();
28973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetCallPosition(expr);
2899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(r0, Operand(arg_count));
2901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
2902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          RelocInfo::CODE_TARGET);
2903109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(arg_count + 1);
2904bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  RestoreContext();
2905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2908d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
2910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Token::DELETE: {
2911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
2912589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Property* property = expr->expression()->AsProperty();
2913589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VariableProxy* proxy = expr->expression()->AsVariableProxy();
2914e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2915589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (property != NULL) {
2916589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        VisitForStackValue(property->obj());
2917589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        VisitForStackValue(property->key());
2918109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        CallRuntimeWithOperands(is_strict(language_mode())
2919109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                    ? Runtime::kDeleteProperty_Strict
2920109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                    : Runtime::kDeleteProperty_Sloppy);
292169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        context()->Plug(r0);
2922589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else if (proxy != NULL) {
2923589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Variable* var = proxy->var();
2924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Delete of an unqualified identifier is disallowed in strict mode but
2925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // "delete this" is allowed.
2926f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        bool is_this = var->is_this();
2927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(is_sloppy(language_mode()) || is_this);
2928f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        if (var->IsUnallocated()) {
2929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ LoadGlobalObject(r2);
2930e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ mov(r1, Operand(var->name()));
2931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ Push(r2, r1);
2932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ CallRuntime(Runtime::kDeleteProperty_Sloppy);
2933e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(r0);
2934589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        } else if (var->IsStackAllocated() || var->IsContextSlot()) {
2935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Result of deleting non-global, non-dynamic variables is false.
2936e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // The subexpression does not have side effects.
2937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          context()->Plug(is_this);
2938e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else {
2939e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Non-global variable.  Call the runtime to try to delete from the
2940e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // context where the variable was introduced.
2941109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          __ Push(var->name());
2942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ CallRuntime(Runtime::kDeleteLookupSlot);
2943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(r0);
2944e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
29451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
2946e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Result of deleting non-property, non-variable reference is true.
2947e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // The subexpression may have side effects.
2948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
2949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        context()->Plug(true);
2950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
2951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
2955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
2956e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
29570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(Heap::kUndefinedValueRootIndex);
2958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2960d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
2962d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2963e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (context()->IsEffect()) {
2964e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Unary NOT has no side effects so it's only necessary to visit the
2965e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // subexpression.  Match the optimizing compiler by not branching.
2966e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
29673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (context()->IsTest()) {
29683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        const TestContext* test = TestContext::cast(context());
29693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The labels are swapped for the recursive call.
29703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VisitForControl(expr->expression(),
29713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->false_label(),
29723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->true_label(),
29733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->fall_through());
29743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        context()->Plug(test->true_label(), test->false_label());
2975e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
29763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We handle value contexts explicitly rather than simply visiting
29773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // for control and plugging the control flow into the context,
29783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // because we need to prepare a pair of extra administrative AST ids
29793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // for the optimizing compiler.
2980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue());
29813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label materialize_true, materialize_false, done;
29823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VisitForControl(expr->expression(),
29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_false,
29843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_true,
29853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_true);
2986109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
29873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&materialize_true);
2988bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        PrepareForBailoutForId(expr->MaterializeTrueId(),
2989bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                               BailoutState::NO_REGISTERS);
29903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(r0, Heap::kTrueValueRootIndex);
29913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (context()->IsStackValue()) __ push(r0);
29923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&done);
29933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&materialize_false);
2994bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        PrepareForBailoutForId(expr->MaterializeFalseId(),
2995bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                               BailoutState::NO_REGISTERS);
29963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(r0, Heap::kFalseValueRootIndex);
29973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (context()->IsStackValue()) __ push(r0);
29983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&done);
2999e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
3000d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3001d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3002d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3003d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
3004d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
3005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      {
3006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AccumulatorValueContext context(this);
30070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForTypeofValue(expr->expression());
30080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
3009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ mov(r3, r0);
3010c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      __ Call(isolate()->builtins()->Typeof(), RelocInfo::CODE_TARGET);
30110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(r0);
3012d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
30133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
3014d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3015d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
3016d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
30173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
3018d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3019d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3020d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3021d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
3023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3024d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CountOperation");
302580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3026e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
3027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LhsKind assign_type = Property::GetAssignType(prop);
3028e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3029e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
3030e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
3031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
30320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
30333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    EmitVariableLoad(expr->expression()->AsVariableProxy());
30343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
3035e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
30360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (expr->is_postfix() && !context()->IsEffect()) {
3037c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      __ mov(ip, Operand(Smi::kZero));
3038109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(ip);
3039e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3040958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (assign_type) {
3041958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case NAMED_PROPERTY: {
3042958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Put the object both on the stack and in the register.
3043958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        VisitForStackValue(prop->obj());
3044958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
3045958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        EmitNamedPropertyLoad(prop);
3046958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
3047958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
3048958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3049958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case NAMED_SUPER_PROPERTY: {
3050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
3051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        VisitForAccumulatorValue(
3052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            prop->obj()->AsSuperPropertyReference()->home_object());
3053109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(result_register());
3054958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        const Register scratch = r1;
3055958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ ldr(scratch, MemOperand(sp, kPointerSize));
3056109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(scratch);
3057109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(result_register());
3058958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        EmitNamedSuperPropertyLoad(prop);
3059958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
3060958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
3061958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3062958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case KEYED_SUPER_PROPERTY: {
3063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
3064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        VisitForStackValue(
3065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            prop->obj()->AsSuperPropertyReference()->home_object());
3066958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        VisitForAccumulatorValue(prop->key());
3067109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(result_register());
3068958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        const Register scratch = r1;
3069958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
3070109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(scratch);
3071958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ ldr(scratch, MemOperand(sp, 2 * kPointerSize));
3072109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(scratch);
3073109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(result_register());
3074958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        EmitKeyedSuperPropertyLoad(prop);
3075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
3076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
3077958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case KEYED_PROPERTY: {
3079958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        VisitForStackValue(prop->obj());
3080958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        VisitForStackValue(prop->key());
3081958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ ldr(LoadDescriptor::ReceiverRegister(),
3082958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               MemOperand(sp, 1 * kPointerSize));
3083958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0));
3084958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        EmitKeyedPropertyLoad(prop);
3085958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
3086958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
3087958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3088958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case VARIABLE:
3089958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        UNREACHABLE();
3090e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3091d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3092d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We need a second deoptimization point after loading the value
3094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // in case evaluating the property load my have a side effect.
30958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (assign_type == VARIABLE) {
3096bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
30978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
3098bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
30998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
3100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Inline smi case if we are in a loop.
3102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label stub_call, done;
3103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpPatchSite patch_site(masm_);
3104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int count_value = expr->op() == Token::INC ? 1 : -1;
3106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (ShouldInlineSmiCase(expr->op())) {
3107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label slow;
3108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patch_site.EmitJumpIfNotSmi(r0, &slow);
3109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Save result for postfix expressions.
3111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (expr->is_postfix()) {
3112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!context()->IsEffect()) {
3113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Save the result on the stack. If we have a named or keyed property
3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // we store the result under the receiver that is currently on top
3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // of the stack.
3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        switch (assign_type) {
3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          case VARIABLE:
3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ push(r0);
3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          case NAMED_PROPERTY:
3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ str(r0, MemOperand(sp, kPointerSize));
3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
3123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case NAMED_SUPER_PROPERTY:
3124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            __ str(r0, MemOperand(sp, 2 * kPointerSize));
3125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            break;
3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          case KEYED_PROPERTY:
3127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ str(r0, MemOperand(sp, 2 * kPointerSize));
3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
3129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case KEYED_SUPER_PROPERTY:
3130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            __ str(r0, MemOperand(sp, 3 * kPointerSize));
3131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            break;
3132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
3133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
3134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC);
3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(vc, &done);
3138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Call stub. Undo operation first.
3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(r0, r0, Operand(Smi::FromInt(count_value)));
3140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&stub_call);
3141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&slow);
3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
31433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
31443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Convert old value into a number.
314513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
3146f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RestoreContext();
3147bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
3148e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3149e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
3150e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
31510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (!context()->IsEffect()) {
31520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Save the result on the stack. If we have a named or keyed property
31530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // we store the result under the receiver that is currently on top
31540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // of the stack.
31550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
31560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
3157109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          PushOperand(r0);
31580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
31590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
31600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ str(r0, MemOperand(sp, kPointerSize));
31610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
3162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        case NAMED_SUPER_PROPERTY:
3163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          __ str(r0, MemOperand(sp, 2 * kPointerSize));
3164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          break;
31650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
31660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ str(r0, MemOperand(sp, 2 * kPointerSize));
31670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
3168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        case KEYED_SUPER_PROPERTY:
3169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          __ str(r0, MemOperand(sp, 3 * kPointerSize));
3170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          break;
31710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
3172e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3174e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3175d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&stub_call);
3177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r1, r0);
3178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r0, Operand(Smi::FromInt(count_value)));
3179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionPosition(expr);
3181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3182109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code();
3183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(code, expr->CountBinOpFeedbackId());
31843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
3185d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
3186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in r0.
3188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
3189c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    case VARIABLE: {
3190c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      VariableProxy* proxy = expr->expression()->AsVariableProxy();
3191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
31920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        { EffectContext context(this);
3193c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
3194c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                 proxy->hole_check_mode());
3195bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          PrepareForBailoutForId(expr->AssignmentId(),
3196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                 BailoutState::TOS_REGISTER);
3197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          context.Plug(r0);
31980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        }
31990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        // For all contexts except EffectConstant We have the result on
3200e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
32010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
32020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3204e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
3205c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
3206c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                               proxy->hole_check_mode());
3207bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        PrepareForBailoutForId(expr->AssignmentId(),
3208bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                               BailoutState::TOS_REGISTER);
3209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        context()->Plug(r0);
3210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3212c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
3213e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
3214109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(StoreDescriptor::ReceiverRegister());
3215f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value());
3216bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3217e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
32180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
32190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3220e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
32220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(r0);
3223e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    case NAMED_SUPER_PROPERTY: {
3227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      EmitNamedSuperPropertyStore(prop);
3228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (expr->is_postfix()) {
3230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (!context()->IsEffect()) {
3231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          context()->PlugTOS();
3232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
3233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
3234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        context()->Plug(r0);
3235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
3236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
3237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
3238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    case KEYED_SUPER_PROPERTY: {
3239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      EmitKeyedSuperPropertyStore(prop);
3240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (expr->is_postfix()) {
3242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (!context()->IsEffect()) {
3243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          context()->PlugTOS();
3244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
3245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
3246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        context()->Plug(r0);
3247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
3248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
3249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
3250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
3251109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperands(StoreDescriptor::ReceiverRegister(),
3252109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                  StoreDescriptor::NameRegister());
3253f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      CallKeyedStoreIC(expr->CountSlot());
3254bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
32560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
32570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
32600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(r0);
3261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
32643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
32653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
32663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
32673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
32683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
32693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Expression* sub_expr,
32703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Handle<String> check) {
32713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label materialize_true, materialize_false;
32723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* if_true = NULL;
32733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* if_false = NULL;
32743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* fall_through = NULL;
32753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
32763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         &if_true, &if_false, &fall_through);
32773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  { AccumulatorValueContext context(this);
32793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForTypeofValue(sub_expr);
32800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
32813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate()->factory();
3284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (String::Equals(check, factory->number_string())) {
3285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(r0, if_true);
328680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
328780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
328880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r0, ip);
328980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
3290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->string_string())) {
3291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(r0, if_false);
3292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE);
3293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Split(lt, if_true, if_false, fall_through);
3294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->symbol_string())) {
3295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(r0, if_false);
3296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareObjectType(r0, r0, r1, SYMBOL_TYPE);
3297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Split(eq, if_true, if_false, fall_through);
3298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->boolean_string())) {
3299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CompareRoot(r0, Heap::kTrueValueRootIndex);
3300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(eq, if_true);
3301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CompareRoot(r0, Heap::kFalseValueRootIndex);
330280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
3303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->undefined_string())) {
3304109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ CompareRoot(r0, Heap::kNullValueRootIndex);
3305109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ b(eq, if_false);
3306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(r0, if_false);
330780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => true.
330880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
330980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
3310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ tst(r1, Operand(1 << Map::kIsUndetectable));
3311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(ne, if_true, if_false, fall_through);
3312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->function_string())) {
3314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(r0, if_false);
3315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
3316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
3317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ and_(r1, r1,
3318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
3319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ cmp(r1, Operand(1 << Map::kIsCallable));
33203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Split(eq, if_true, if_false, fall_through);
3321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->object_string())) {
3322e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(r0, if_false);
3323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(r0, Heap::kNullValueRootIndex);
3324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(eq, if_true);
3325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
3326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CompareObjectType(r0, r0, r1, FIRST_JS_RECEIVER_TYPE);
33273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ b(lt, if_false);
3328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Check for callable or undetectable objects => false.
3329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
3330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ tst(r1, Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
3331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Split(eq, if_true, if_false, fall_through);
3332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// clang-format off
3333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type)   \
3334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (String::Equals(check, factory->type##_string())) { \
3335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ JumpIfSmi(r0, if_false);                                 \
3336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));    \
3337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CompareRoot(r0, Heap::k##Type##MapRootIndex);            \
3338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(eq, if_true, if_false, fall_through);
3339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SIMD128_TYPES(SIMD128_TYPE)
3340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef SIMD128_TYPE
3341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // clang-format on
334280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
334380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (if_false != fall_through) __ jmp(if_false);
3344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
33453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->Plug(if_true, if_false);
3346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3349d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
3350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
3351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
33523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First we try a fast inlined version of the compare when one of
33533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the operands is a literal.
33543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (TryLiteralCompare(expr)) return;
33553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
3357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
3358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
336180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
33620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
33630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
336480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
33653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Token::Value op = expr->op();
33660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->left());
336780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
3368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
33690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
3370bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      SetExpressionPosition(expr);
3371bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      EmitHasProperty();
33723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
3373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ CompareRoot(r0, Heap::kTrueValueRootIndex);
337480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(eq, if_true, if_false, fall_through);
3375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
3378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      VisitForAccumulatorValue(expr->right());
3379bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      SetExpressionPosition(expr);
3380109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(r1);
3381c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      __ Call(isolate()->builtins()->InstanceOf(), RelocInfo::CODE_TARGET);
3382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
3383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ CompareRoot(r0, Heap::kTrueValueRootIndex);
338480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(eq, if_true, if_false, fall_through);
3385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
33890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->right());
3390bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      SetExpressionPosition(expr);
3391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Condition cond = CompareIC::ComputeCondition(op);
3392109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(r1);
3393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
33940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      bool inline_smi_code = ShouldInlineSmiCase(op);
33951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      JumpPatchSite patch_site(masm_);
33960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (inline_smi_code) {
339780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Label slow_case;
339880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ orr(r2, r0, Operand(r1));
33991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        patch_site.EmitJumpIfNotSmi(r2, &slow_case);
340080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ cmp(r1, r0);
34011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Split(cond, if_true, if_false, NULL);
340280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&slow_case);
340380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
34041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3405109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
3406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallIC(ic, expr->CompareOperationFeedbackId());
34073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      patch_site.EmitPatchInfo();
34083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmp(r0, Operand::Zero());
34101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Split(cond, if_true, if_false, fall_through);
34113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
34123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
34133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
3415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
34160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
34183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
34203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
34213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              Expression* sub_expr,
34223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              NilValue nil) {
342380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
342480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
342580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
342680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
34270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
34280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
342980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
34303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitForAccumulatorValue(sub_expr);
34313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
34323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expr->op() == Token::EQ_STRICT) {
3433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Heap::RootListIndex nil_value = nil == kNullValue ?
3434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Heap::kNullValueRootIndex :
3435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Heap::kUndefinedValueRootIndex;
3436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(r1, nil_value);
343780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r0, r1);
343880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
3439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
34403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ JumpIfSmi(r0, if_false);
34413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
34423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
34433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ tst(r1, Operand(1 << Map::kIsUndetectable));
34443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Split(ne, if_true, if_false, fall_through);
344580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
34460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
344780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
344880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
344980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
34500d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() {
34510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return r0;
34520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
3453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
34550d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() {
34560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return cp;
34570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
34580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
34593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid FullCodeGenerator::LoadFromFrameField(int frame_offset, Register value) {
34603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
34613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ ldr(value, MemOperand(fp, frame_offset));
34623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
34630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3464d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
3465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
3466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ str(value, MemOperand(fp, frame_offset));
3467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
34683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3470d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
3471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ldr(dst, ContextMemOperand(cp, context_index));
34723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
34733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
34753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
3476f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeclarationScope* closure_scope = scope()->GetClosureScope();
3477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (closure_scope->is_script_scope() ||
3478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      closure_scope->is_module_scope()) {
3479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Contexts nested in the native context have a canonical empty function
34803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // as their closure, not the anonymous closure containing the global
3481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // code.
3482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadNativeContextSlot(Context::CLOSURE_INDEX, ip);
3483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (closure_scope->is_eval_scope()) {
34843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Contexts created by a call to eval have the same closure as the
34853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // context calling eval, not the anonymous closure containing the eval
34863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // code.  Fetch it from the context.
3487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ldr(ip, ContextMemOperand(cp, Context::CLOSURE_INDEX));
34883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
3489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(closure_scope->is_function_scope());
34903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ ldr(ip, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
34913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3492109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(ip);
34933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
34943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
34953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ----------------------------------------------------------------------------
3497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support.
3498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3499d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() {
3500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result_register().is(r1));
3501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Store pending message while executing finally block.
3502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference pending_message_obj =
3503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_pending_message_obj(isolate());
3504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ip, Operand(pending_message_obj));
3505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r1, MemOperand(ip));
3506109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(r1);
3507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ClearPendingMessage();
3509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3512d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() {
3513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result_register().is(r1));
3514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore pending message from stack.
3515109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(r1);
3516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference pending_message_obj =
3517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_pending_message_obj(isolate());
3518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ip, Operand(pending_message_obj));
3519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r1, MemOperand(ip));
3520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3521e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::ClearPendingMessage() {
3524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result_register().is(r1));
3525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ExternalReference pending_message_obj =
3526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ExternalReference::address_of_pending_message_obj(isolate());
3527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(r1, Heap::kTheHoleValueRootIndex);
3528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(ip, Operand(pending_message_obj));
3529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ str(r1, MemOperand(ip));
3530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
353269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
3533109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::DeferredCommands::EmitCommands() {
3534109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!result_register().is(r1));
3535109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Pop(result_register());  // Restore the accumulator.
3536109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Pop(r1);                 // Get the token.
3537109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  for (DeferredCommand cmd : commands_) {
3538109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Label skip;
3539109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ cmp(r1, Operand(Smi::FromInt(cmd.token)));
3540109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ b(ne, &skip);
3541109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    switch (cmd.command) {
3542109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case kReturn:
3543109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        codegen_->EmitUnwindAndReturn();
3544109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        break;
3545109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case kThrow:
3546109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        __ Push(result_register());
3547109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        __ CallRuntime(Runtime::kReThrow);
3548109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        break;
3549109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case kContinue:
3550109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        codegen_->EmitContinue(cmd.target);
3551109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        break;
3552109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case kBreak:
3553109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        codegen_->EmitBreak(cmd.target);
3554109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        break;
3555109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
3556109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ bind(&skip);
3557109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
3558109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
355969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
356069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#undef __
356169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
3562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Address GetInterruptImmediateLoadAddress(Address pc) {
3564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address load_address = pc - 2 * Assembler::kInstrSize;
3565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!FLAG_enable_embedded_constant_pool) {
3566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(load_address)));
3567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (Assembler::IsLdrPpRegOffset(Memory::int32_at(load_address))) {
3568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This is an extended constant pool lookup.
3569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (CpuFeatures::IsSupported(ARMv7)) {
3570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      load_address -= 2 * Assembler::kInstrSize;
3571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Assembler::IsMovW(Memory::int32_at(load_address)));
3572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Assembler::IsMovT(
3573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Memory::int32_at(load_address + Assembler::kInstrSize)));
3574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
3575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      load_address -= 4 * Assembler::kInstrSize;
3576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Assembler::IsMovImmed(Memory::int32_at(load_address)));
3577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Assembler::IsOrrImmed(
3578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Memory::int32_at(load_address + Assembler::kInstrSize)));
3579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Assembler::IsOrrImmed(
3580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Memory::int32_at(load_address + 2 * Assembler::kInstrSize)));
3581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Assembler::IsOrrImmed(
3582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Memory::int32_at(load_address + 3 * Assembler::kInstrSize)));
3583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (CpuFeatures::IsSupported(ARMv7) &&
3585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             Assembler::IsMovT(Memory::int32_at(load_address))) {
3586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This is a movw / movt immediate load.
3587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    load_address -= Assembler::kInstrSize;
3588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsMovW(Memory::int32_at(load_address)));
3589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (!CpuFeatures::IsSupported(ARMv7) &&
3590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             Assembler::IsOrrImmed(Memory::int32_at(load_address))) {
3591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This is a mov / orr immediate load.
3592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    load_address -= 3 * Assembler::kInstrSize;
3593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsMovImmed(Memory::int32_at(load_address)));
3594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsOrrImmed(
3595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Memory::int32_at(load_address + Assembler::kInstrSize)));
3596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsOrrImmed(
3597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Memory::int32_at(load_address + 2 * Assembler::kInstrSize)));
3598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This is a small constant pool lookup.
3600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(load_address)));
3601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return load_address;
3603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BackEdgeTable::PatchAt(Code* unoptimized_code,
3607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Address pc,
3608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            BackEdgeState target_state,
3609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Code* replacement_code) {
3610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc);
3611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address branch_address = pc_immediate_load_address - Assembler::kInstrSize;
3612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Isolate* isolate = unoptimized_code->GetIsolate();
3613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CodePatcher patcher(isolate, branch_address, 1);
3614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (target_state) {
3615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case INTERRUPT:
3616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
3617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  <decrement profiling counter>
3618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   bpl ok
3619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; load interrupt stub address into ip - either of (for ARMv7):
3620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; <small cp load>      |  <extended cp load> |  <immediate load>
3621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ldr ip, [pc/pp, #imm]  |   movw ip, #imm     |   movw ip, #imm
3622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   movt ip, #imm     |   movw ip, #imm
3623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   ldr  ip, [pp, ip]
3624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; or (for ARMv6):
3625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; <small cp load>      |  <extended cp load> |  <immediate load>
3626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ldr ip, [pc/pp, #imm]  |   mov ip, #imm      |   mov ip, #imm
3627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
3628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
3629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
3630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   blx ip
3631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  <reset profiling counter>
3632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  ok-label
3633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Calculate branch offset to the ok-label - this is the difference
3635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // between the branch address and |pc| (which points at <blx ip>) plus
3636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // kProfileCounterResetSequence instructions
3637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int branch_offset = pc - Instruction::kPCReadOffset - branch_address +
3638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          kProfileCounterResetSequenceLength;
3639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      patcher.masm()->b(branch_offset, pl);
3640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
3641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case ON_STACK_REPLACEMENT:
3643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  <decrement profiling counter>
3644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   mov r0, r0 (NOP)
3645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; load on-stack replacement address into ip - either of (for ARMv7):
3646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; <small cp load>      |  <extended cp load> |  <immediate load>
3647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ldr ip, [pc/pp, #imm]  |   movw ip, #imm     |   movw ip, #imm
3648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   movt ip, #imm>    |   movw ip, #imm
3649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   ldr  ip, [pp, ip]
3650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; or (for ARMv6):
3651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; <small cp load>      |  <extended cp load> |  <immediate load>
3652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ldr ip, [pc/pp, #imm]  |   mov ip, #imm      |   mov ip, #imm
3653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
3654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
3655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
3656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   blx ip
3657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  <reset profiling counter>
3658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  ok-label
3659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      patcher.masm()->nop();
3660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
3661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Replace the call address.
3664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Assembler::set_target_address_at(isolate, pc_immediate_load_address,
3665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   unoptimized_code, replacement_code->entry());
3666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
3668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      unoptimized_code, pc_immediate_load_address, replacement_code);
3669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
3673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Isolate* isolate,
3674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Code* unoptimized_code,
3675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Address pc) {
3676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Assembler::IsBlxIp(Memory::int32_at(pc - Assembler::kInstrSize)));
3677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc);
3679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address branch_address = pc_immediate_load_address - Assembler::kInstrSize;
36803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#ifdef DEBUG
3681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address interrupt_address = Assembler::target_address_at(
3682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      pc_immediate_load_address, unoptimized_code);
36833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#endif
3684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (Assembler::IsBranch(Assembler::instr_at(branch_address))) {
3686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(interrupt_address ==
3687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           isolate->builtins()->InterruptCheck()->entry());
3688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return INTERRUPT;
3689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Assembler::IsNop(Assembler::instr_at(branch_address)));
3692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(interrupt_address ==
36943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         isolate->builtins()->OnStackReplacement()->entry());
36953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return ON_STACK_REPLACEMENT;
3696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
3700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
3701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
3703