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#include "src/v8.h"
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler.h"
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/debug.h"
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/full-codegen.h"
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h"
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/isolate-inl.h"
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/parser.h"
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/scopes.h"
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/code-stubs-arm.h"
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/macro-assembler-arm.h"
229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 {
243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal {
253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_)
273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// A patch site is a location in the code which it is possible to patch. This
301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// class has a number of methods to emit the code which is patchable and the
311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// method EmitPatchInfo to record a marker back to the patchable code. This
321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// marker is a cmp rx, #yyy instruction, and x * 0x00000fff + yyy (raw 12 bit
331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// immediate value is used) is the delta from the pc to the first instruction of
341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// the patchable code.
351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass JumpPatchSite BASE_EMBEDDED {
361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    info_emitted_ = false;
401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ~JumpPatchSite() {
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(patch_site_.is_bound() == info_emitted_);
451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // When initially emitting this ensure that a jump is always generated to skip
481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the inlined smi code.
491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EmitJumpIfNotSmi(Register reg, Label* target) {
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!patch_site_.is_bound() && !info_emitted_);
51db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch    Assembler::BlockConstPoolScope block_const_pool(masm_);
521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&patch_site_);
531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cmp(reg, Operand(reg));
541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(eq, target);  // Always taken before patched.
551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // When initially emitting this ensure that a jump is never generated to skip
581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the inlined smi code.
591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EmitJumpIfSmi(Register reg, Label* target) {
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!patch_site_.is_bound() && !info_emitted_);
61db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch    Assembler::BlockConstPoolScope block_const_pool(masm_);
621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&patch_site_);
631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cmp(reg, Operand(reg));
641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(ne, target);  // Never taken before patched.
651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EmitPatchInfo() {
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Block literal pool emission whilst recording patch site information.
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assembler::BlockConstPoolScope block_const_pool(masm_);
703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (patch_site_.is_bound()) {
713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_);
723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Register reg;
733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      reg.set_code(delta_to_patch_site / kOff12Mask);
743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ cmp_raw_immediate(reg, delta_to_patch_site % kOff12Mask);
751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      info_emitted_ = true;
771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ nop();  // Signals no inlined code.
803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  MacroAssembler* masm_;
851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Label patch_site_;
861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool info_emitted_;
881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function.  On entry to the function the receiver
933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right.  The actual
943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// argument count matches the formal parameter count expected by the
953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// function.
963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are:
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   o r1: the JS function object being called (i.e., ourselves)
993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o cp: our context
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//   o pp: our caller's constant pool pointer (if FLAG_enable_ool_constant_pool)
1013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o fp: our caller's frame pointer
1023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o sp: stack pointer
1033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o lr: return address
1043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
1053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame.  Please see JavaScriptFrameConstants in
1063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-arm.h for its layout.
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::Generate() {
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompilationInfo* info = info_;
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  handler_table_ =
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  profiling_counter_ = isolate()->factory()->NewCell(
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
1143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  SetFunctionPosition(function());
1156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comment cmnt(masm_, "[ function compiled by full code generator");
1163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProfileEntryHookStub::MaybeCallEntryHook(masm_);
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
119f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG
120f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (strlen(FLAG_stop_at) > 0 &&
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
122f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ stop("stop-at");
123f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
124f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif
125f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Sloppy mode functions and builtins need to replace the receiver with the
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // global proxy when called as functions (without an explicit receiver
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object).
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (info->strict_mode() == SLOPPY && !info->is_native()) {
130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label ok;
1313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int receiver_offset = info->scope()->num_parameters() * kPointerSize;
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(r2, MemOperand(sp, receiver_offset));
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(r2, Heap::kUndefinedValueRootIndex);
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(ne, &ok);
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(r2, GlobalObjectOperand());
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalProxyOffset));
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ str(r2, MemOperand(sp, receiver_offset));
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&ok);
142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Open a frame scope to indicate that there is a frame on the stack.  The
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // MANUAL indicates that the scope shouldn't actually generate code to set up
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the frame (that is done below).
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameScope frame_scope(masm_, StackFrame::MANUAL);
1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info->set_prologue_offset(masm_->pc_offset());
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Prologue(info->IsCodePreAgingActive());
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info->AddNoFrameRange(0, masm_->pc_offset());
1523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
153756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  { Comment cmnt(masm_, "[ Allocate locals");
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int locals_count = info->scope()->num_stack_slots();
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Generators allocate locals, if any, in context slots.
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!info->function()->is_generator() || locals_count == 0);
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (locals_count > 0) {
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (locals_count >= 128) {
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label ok;
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ sub(r9, sp, Operand(locals_count * kPointerSize));
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ LoadRoot(r2, Heap::kRealStackLimitRootIndex);
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmp(r9, Operand(r2));
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ b(hs, &ok);
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ bind(&ok);
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(r9, Heap::kUndefinedValueRootIndex);
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int kMaxPushes = FLAG_optimize_for_size ? 4 : 32;
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (locals_count >= kMaxPushes) {
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int loop_iterations = locals_count / kMaxPushes;
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov(r2, Operand(loop_iterations));
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label loop_header;
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ bind(&loop_header);
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Do pushes.
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        for (int i = 0; i < kMaxPushes; i++) {
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ push(r9);
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Continue loop if not done.
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ sub(r2, r2, Operand(1), SetCC);
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ b(&loop_header, ne);
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int remaining = locals_count % kMaxPushes;
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Emit the remaining pushes.
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (int i  = 0; i < remaining; i++) {
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ push(r9);
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
188756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
190756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  bool function_in_register = true;
1914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
192756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate a local context.
1933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
194756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (heap_slots > 0) {
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Argument to NewContext is the function, which is still in r1.
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment cmnt(masm_, "[ Allocate context");
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool need_write_barrier = true;
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ push(r1);
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(info->scope()->GetScopeInfo());
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kNewGlobalContext, 2);
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FastNewContextStub stub(isolate(), heap_slots);
204756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ CallStub(&stub);
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Result of FastNewContextStub is always in new space.
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      need_write_barrier = false;
207756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ push(r1);
2093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ CallRuntime(Runtime::kNewFunctionContext, 1);
210756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
211756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    function_in_register = false;
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Context is returned in r0.  It replaces the context passed to us.
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // It's saved in the stack and kept live in cp.
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(cp, r0);
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ str(r0, MemOperand(fp, StandardFrameConstants::kContextOffset));
216756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Copy any necessary parameters into the context.
2173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int num_parameters = info->scope()->num_parameters();
218756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (int i = 0; i < num_parameters; i++) {
219589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Variable* var = scope()->parameter(i);
220589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (var->IsContextSlot()) {
221756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
222756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick            (num_parameters - 1 - i) * kPointerSize;
223756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Load parameter from stack.
224756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ ldr(r0, MemOperand(fp, parameter_offset));
225756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Store it in the context.
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        MemOperand target = ContextOperand(cp, var->index());
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ str(r0, target);
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Update the write barrier.
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (need_write_barrier) {
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ RecordWriteContextSlot(
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              cp, target.offset(), r0, r3, kLRHasBeenSaved, kDontSaveFPRegs);
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (FLAG_debug_code) {
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Label done;
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ JumpIfInNewSpace(cp, r0, &done);
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Abort(kExpectedNewSpaceObject);
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ bind(&done);
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
241756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Variable* arguments = scope()->arguments();
244756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (arguments != NULL) {
245756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Function uses arguments object.
246756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate arguments object");
247756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (!function_in_register) {
248756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      // Load this again, if it's used by the local context below.
249756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
250756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
251756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ mov(r3, r1);
252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
253756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Receiver is just before the parameters on the caller's stack.
2543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int num_parameters = info->scope()->num_parameters();
2553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int offset = num_parameters * kPointerSize;
256756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ add(r2, fp,
257756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           Operand(StandardFrameConstants::kCallerSPOffset + offset));
2583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ mov(r1, Operand(Smi::FromInt(num_parameters)));
259756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ Push(r3, r2, r1);
260756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
261756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Arguments to ArgumentsAccessStub:
262756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    //   function, receiver address, parameter count.
263756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The stub will rewrite receiever and parameter count if the previous
264756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // stack frame was an arguments adapter frame.
2653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ArgumentsAccessStub::Type type;
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (strict_mode() == STRICT) {
2673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      type = ArgumentsAccessStub::NEW_STRICT;
2683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else if (function()->has_duplicate_parameters()) {
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
2703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
2723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ArgumentsAccessStub stub(isolate(), type);
274756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
27544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
276589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SetVar(arguments, r0, r1, r2);
277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace) {
280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ CallRuntime(Runtime::kTraceEnter, 0);
281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Visit the declarations and body unless there is an illegal
284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // redeclaration.
285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (scope()->HasIllegalRedeclaration()) {
286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Comment cmnt(masm_, "[ Declarations");
287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    scope()->VisitIllegalRedeclaration(this);
2883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    { Comment cmnt(masm_, "[ Declarations");
292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // For named function expressions, declare the function name as a
293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // constant.
294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (scope()->is_function_scope() && scope()->function() != NULL) {
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VariableDeclaration* function = scope()->function();
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(function->proxy()->var()->mode() == CONST ||
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               function->proxy()->var()->mode() == CONST_LEGACY);
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED);
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitVariableDeclaration(function);
300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      VisitDeclarations(scope()->declarations());
302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    { Comment cmnt(masm_, "[ Stack check");
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Label ok;
307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ LoadRoot(ip, Heap::kStackLimitRootIndex);
308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ cmp(sp, Operand(ip));
309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(hs, &ok);
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Code> stack_check = isolate()->builtins()->StackCheck();
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PredictableCodeSizeScope predictable(masm_,
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          masm_->CallSize(stack_check, RelocInfo::CODE_TARGET));
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Call(stack_check, RelocInfo::CODE_TARGET);
314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ bind(&ok);
315e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    { Comment cmnt(masm_, "[ Body");
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(loop_depth() == 0);
319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      VisitStatements(function()->body());
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(loop_depth() == 0);
321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
3223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
3233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
324e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Always emit a 'return undefined' in case control fell off the end of
325e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the body.
3263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
3273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  EmitReturnSequence();
330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Force emit the constant pool, so it doesn't get emitted in the middle
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // of the back edge table.
333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  masm()->CheckConstPool(true, false);
334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
337db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdochvoid FullCodeGenerator::ClearAccumulator() {
338db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  __ mov(r0, Operand(Smi::FromInt(0)));
339db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch}
340db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
341db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r2, Operand(profiling_counter_));
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(r3, r3, Operand(Smi::FromInt(delta)), SetCC);
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r3, FieldMemOperand(r2, Cell::kValueOffset));
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef CAN_USE_ARMV7_INSTRUCTIONS
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int kProfileCounterResetSequenceLength = 5 * Assembler::kInstrSize;
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int kProfileCounterResetSequenceLength = 7 * Assembler::kInstrSize;
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitProfilingCounterReset() {
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler::BlockConstPoolScope block_const_pool(masm_);
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PredictableCodeSizeScope predictable_code_size_scope(
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      masm_, kProfileCounterResetSequenceLength);
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label start;
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&start);
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int reset_value = FLAG_interrupt_budget;
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (info_->is_debug()) {
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Detect debug break requests as soon as possible.
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    reset_value = FLAG_interrupt_budget >> 4;
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r2, Operand(profiling_counter_));
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The mov instruction above can be either 1 to 3 (for ARMv7) or 1 to 5
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // instructions (for ARMv6) depending upon whether it is an extended constant
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // pool - insert nop to compensate.
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int expected_instr_count =
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (kProfileCounterResetSequenceLength / Assembler::kInstrSize) - 2;
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_->InstructionsGeneratedSince(&start) <= expected_instr_count);
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (masm_->InstructionsGeneratedSince(&start) != expected_instr_count) {
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ nop();
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r3, Operand(Smi::FromInt(reset_value)));
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r3, FieldMemOperand(r2, Cell::kValueOffset));
3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Label* back_edge_target) {
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ Back edge bookkeeping");
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Block literal pools whilst emitting back edge code.
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler::BlockConstPoolScope block_const_pool(masm_);
388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label ok;
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(back_edge_target->is_bound());
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int weight = Min(kMaxBackEdgeWeight,
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Max(1, distance / kCodeSizeMultiplier));
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitProfilingCounterDecrement(weight);
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(pl, &ok);
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
398086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Record a mapping of this PC offset to the OSR id.  This is used to find
399086aeeaae12517475c22695a200be45495516549Ben Murdoch  // the AST id from the unoptimized code in order to use it as a key into
400086aeeaae12517475c22695a200be45495516549Ben Murdoch  // the deoptimization input data found in the optimized code.
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordBackEdge(stmt->OsrEntryId());
402086aeeaae12517475c22695a200be45495516549Ben Murdoch
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitProfilingCounterReset();
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&ok);
406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
407086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Record a mapping of the OSR id to this PC.  This is used if the OSR
408086aeeaae12517475c22695a200be45495516549Ben Murdoch  // entry becomes the target of a bailout.  We don't expect it to be, but
409086aeeaae12517475c22695a200be45495516549Ben Murdoch  // we want it to work if it is.
410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() {
415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ b(&return_label_);
418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
4203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
4213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // Push the return value on the stack as the parameter.
4223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // Runtime::TraceExit returns its parameter in r0.
4233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(r0);
4243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ CallRuntime(Runtime::kTraceExit, 1);
4253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Pretend that the exit is a backwards jump to the entry.
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int weight = 1;
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (info_->ShouldSelfOptimize()) {
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      weight = FLAG_interrupt_budget / FLAG_self_opt_count;
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int distance = masm_->pc_offset();
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      weight = Min(kMaxBackEdgeWeight,
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Max(1, distance / kCodeSizeMultiplier));
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitProfilingCounterDecrement(weight);
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(pl, &ok);
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(r0);
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Call(isolate()->builtins()->InterruptCheck(),
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            RelocInfo::CODE_TARGET);
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pop(r0);
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitProfilingCounterReset();
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&ok);
4443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG
446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Add a label for checking the size of the code used for returning.
447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Label check_exit_codesize;
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&check_exit_codesize);
4496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
4506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Make sure that the constant pool is not emitted inside of the return
4516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // sequence.
4526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    { Assembler::BlockConstPoolScope block_const_pool(masm_);
4533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize;
454bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // TODO(svenpanne) The code below is sometimes 4 words, sometimes 5!
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PredictableCodeSizeScope predictable(masm_, -1);
4576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ RecordJSReturn();
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int no_frame_start = __ LeaveFrame(StackFrame::JAVA_SCRIPT);
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      { ConstantPoolUnavailableScope constant_pool_unavailable(masm_);
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ add(sp, sp, Operand(sp_delta));
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Jump(lr);
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
464d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG
4671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check that the size of the code used for returning is large enough
4681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // for the debugger's requirements.
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::kJSReturnSequenceInstructions <=
4701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           masm_->InstructionsGeneratedSince(&check_exit_codesize));
4716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
475d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
476589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EffectContext::Plug(Variable* var) const {
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
4780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
481589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
483589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  codegen()->GetVar(result_register(), var);
4840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
487589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
489589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  codegen()->GetVar(result_register(), var);
4900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(result_register());
491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
492d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
493d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
494589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::TestContext::Plug(Variable* var) const {
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
4960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
497589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  codegen()->GetVar(result_register(), var);
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
4993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  codegen()->DoTest(this);
500d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5030d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5070d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
5080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
5090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), index);
5100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5130d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
5140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
5150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), index);
5160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(result_register());
5170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5200d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
5250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (index == Heap::kUndefinedValueRootIndex ||
5260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kNullValueRootIndex ||
5270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kFalseValueRootIndex) {
528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (false_label_ != fall_through_) __ b(false_label_);
5290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (index == Heap::kTrueValueRootIndex) {
530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (true_label_ != fall_through_) __ b(true_label_);
5310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
5320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ LoadRoot(result_register(), index);
5333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    codegen()->DoTest(this);
534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
536d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
537d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5380d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
5390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
541e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5420d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
5430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Handle<Object> lit) const {
5440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), Operand(lit));
5450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5480d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Immediates cannot be pushed directly.
5500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), Operand(lit));
5510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(result_register());
5520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5550d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!lit->IsUndetectableObject());  // There are no undetectable literals.
5610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (false_label_ != fall_through_) __ b(false_label_);
5630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsTrue() || lit->IsJSObject()) {
564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (true_label_ != fall_through_) __ b(true_label_);
5650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsString()) {
5660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (String::cast(*lit)->length() == 0) {
5678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (false_label_ != fall_through_) __ b(false_label_);
5680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ b(true_label_);
5700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
5710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsSmi()) {
5720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (Smi::cast(*lit)->value() == 0) {
573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (false_label_ != fall_through_) __ b(false_label_);
5740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ b(true_label_);
5760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
5770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
5780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // For simplicity we always test the accumulator register.
5790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ mov(result_register(), Operand(lit));
5803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    codegen()->DoTest(this);
581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5850d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count,
5860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                   Register reg) const {
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(count > 0);
5880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
5890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5920d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
5930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    int count,
5940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Register reg) const {
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(count > 0);
5960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
5970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6010d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count,
6020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                       Register reg) const {
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(count > 0);
6040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (count > 1) __ Drop(count - 1);
6050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ str(reg, MemOperand(sp, 0));
606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
608d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6090d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count,
6100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                 Register reg) const {
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(count > 0);
6120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
6130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
6140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
6153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
6163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  codegen()->DoTest(this);
6170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6200d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
6210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            Label* materialize_false) const {
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(materialize_true == materialize_false);
6230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
6240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6270d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
6280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
6290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
6300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label done;
6310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
6320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
6330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ jmp(&done);
6340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
6350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
6360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6400d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
6410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
6420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
6430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label done;
6440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
6450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(ip, Heap::kTrueValueRootIndex);
6460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ jmp(&done);
6470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
6480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(ip, Heap::kFalseValueRootIndex);
6490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(ip);
6510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6540d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true,
6550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                          Label* materialize_false) const {
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(materialize_true == true_label_);
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(materialize_false == false_label_);
6580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6610d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const {
6620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6650d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
6660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
6670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
6680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), value_root_index);
6690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6720d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const {
6730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
6740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
6750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(ip, value_root_index);
6760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(ip);
6770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6800d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const {
6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
6850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (flag) {
6860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (true_label_ != fall_through_) __ b(true_label_);
6870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
6880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (false_label_ != fall_through_) __ b(false_label_);
689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
6933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::DoTest(Expression* condition,
6943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               Label* if_true,
69580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* if_false,
69680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* fall_through) {
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(ic, condition->test_id());
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ tst(result_register(), result_register());
700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Split(ne, if_true, if_false, fall_through);
70180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
7041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid FullCodeGenerator::Split(Condition cond,
70580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_true,
70680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_false,
70780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* fall_through) {
70880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (if_false == fall_through) {
7091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(cond, if_true);
71080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (if_true == fall_through) {
7111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(NegateCondition(cond), if_false);
71280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
7131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(cond, if_true);
71480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(if_false);
715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
719589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) {
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsStackAllocated());
721589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Offset is negative because higher indexes are at lower addresses.
722589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int offset = -var->index() * kPointerSize;
723589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Adjust by a (parameter or local) base offset.
724589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsParameter()) {
725589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
726589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else {
727589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    offset += JavaScriptFrameConstants::kLocal0Offset;
728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
729589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return MemOperand(fp, offset);
730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
733589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
735589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsContextSlot()) {
736589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    int context_chain_length = scope()->ContextChainLength(var->scope());
737589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ LoadContext(scratch, context_chain_length);
738589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return ContextOperand(scratch, var->index());
739589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else {
740589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return StackOperand(var);
741589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
742589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
743589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
744589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
745589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) {
746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Use destination as scratch.
747589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand location = VarOperand(var, dest);
748589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ ldr(dest, location);
749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
752589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::SetVar(Variable* var,
753589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register src,
754589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register scratch0,
755589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register scratch1) {
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch0.is(src));
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch0.is(scratch1));
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch1.is(src));
760589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand location = VarOperand(var, scratch0);
761e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ str(src, location);
7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
763e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
764589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsContextSlot()) {
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteContextSlot(scratch0,
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              location.offset(),
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              src,
7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              scratch1,
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              kLRHasBeenSaved,
7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              kDontSaveFPRegs);
771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     bool should_normalize,
777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_true,
778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_false) {
779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Only prepare for bailouts before splits if we're in a test
780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // context. Otherwise, we let the Visit function deal with the
781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // preparation to avoid preparing with the same AST id twice.
782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!context()->IsTest() || !info_->IsOptimizable()) return;
783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label skip;
785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (should_normalize) __ b(&skip);
7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailout(expr, TOS_REG);
787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (should_normalize) {
788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ LoadRoot(ip, Heap::kTrueValueRootIndex);
789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ cmp(r0, ip);
790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Split(eq, if_true, if_false, NULL);
791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ bind(&skip);
792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The variable in the declaration always resides in the current function
798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // context.
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, scope()->ContextChainLength(variable->scope()));
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (generate_debug_code_) {
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check that we're not inside a with or catch context.
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset));
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(r1, Heap::kWithContextMapRootIndex);
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(ne, kDeclarationInWithContext);
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(r1, Heap::kCatchContextMapRootIndex);
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(ne, kDeclarationInCatchContext);
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitVariableDeclaration(
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VariableDeclaration* declaration) {
813589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // If it was not possible to allocate the variable at compile time, we
814589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // need to "declare" it at runtime to make sure it actually exists in the
815589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // local context.
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VariableProxy* proxy = declaration->proxy();
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VariableMode mode = declaration->mode();
818589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Variable* variable = proxy->var();
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
820589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (variable->location()) {
821589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::UNALLOCATED:
822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      globals_->Add(variable->name(), zone());
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      globals_->Add(variable->binding_needs_init()
824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        ? isolate()->factory()->the_hole_value()
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        : isolate()->factory()->undefined_value(),
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    zone());
827589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
828589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
829589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::PARAMETER:
830589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOCAL:
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (hole_init) {
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment cmnt(masm_, "[ VariableDeclaration");
83369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
834589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ str(ip, StackOperand(variable));
835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
83669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
838589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::CONTEXT:
839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (hole_init) {
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment cmnt(masm_, "[ VariableDeclaration");
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        EmitDebugCheckDeclarationContext(variable);
84269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
843589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ str(ip, ContextOperand(cp, variable->index()));
84469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // No write barrier since the_hole_value is in old space.
845589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
84669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
84769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
849589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOOKUP: {
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ VariableDeclaration");
85169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov(r2, Operand(variable->name()));
8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Declaration nodes are always introduced in one of four modes.
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(IsDeclaredVariableMode(mode));
854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PropertyAttributes attr =
855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          IsImmutableVariableMode(mode) ? READ_ONLY : NONE;
85669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov(r1, Operand(Smi::FromInt(attr)));
85769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // Push initial value, if any.
85869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // Note: For variables we must not push an initial value (such as
85969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // 'undefined') because we may have a (legal) redeclaration and we
86069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // must not destroy the current value.
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (hole_init) {
86269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
86369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ Push(cp, r2, r1, r0);
86469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      } else {
865589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ mov(r0, Operand(Smi::FromInt(0)));  // Indicates no initial value.
86669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ Push(cp, r2, r1, r0);
86769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kDeclareLookupSlot, 4);
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitFunctionDeclaration(
876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FunctionDeclaration* declaration) {
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VariableProxy* proxy = declaration->proxy();
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Variable* variable = proxy->var();
879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (variable->location()) {
880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::UNALLOCATED: {
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      globals_->Add(variable->name(), zone());
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<SharedFunctionInfo> function =
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Compiler::BuildFunctionInfo(declaration->fun(), script(), info_);
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Check for stack-overflow exception.
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (function.is_null()) return SetStackOverflow();
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      globals_->Add(function, zone());
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::PARAMETER:
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::LOCAL: {
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ FunctionDeclaration");
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(declaration->fun());
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ str(result_register(), StackOperand(variable));
895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::CONTEXT: {
899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ FunctionDeclaration");
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitDebugCheckDeclarationContext(variable);
901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(declaration->fun());
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ str(result_register(), ContextOperand(cp, variable->index()));
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int offset = Context::SlotOffset(variable->index());
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // We know that we have written a function, which is not a smi.
905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ RecordWriteContextSlot(cp,
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                offset,
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                result_register(),
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                r2,
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                kLRHasBeenSaved,
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                kDontSaveFPRegs,
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                EMIT_REMEMBERED_SET,
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                OMIT_SMI_CHECK);
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::LOOKUP: {
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ FunctionDeclaration");
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(r2, Operand(variable->name()));
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(r1, Operand(Smi::FromInt(NONE)));
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(cp, r2, r1);
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Push initial value for function declaration.
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForStackValue(declaration->fun());
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kDeclareLookupSlot, 4);
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Variable* variable = declaration->proxy()->var();
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(variable->location() == Variable::CONTEXT);
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(variable->interface()->IsFrozen());
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ ModuleDeclaration");
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitDebugCheckDeclarationContext(variable);
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load instance object.
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadContext(r1, scope_->ContextChainLength(scope_->GlobalScope()));
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r1, ContextOperand(r1, variable->interface()->Index()));
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r1, ContextOperand(r1, Context::EXTENSION_INDEX));
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Assign it.
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r1, ContextOperand(cp, variable->index()));
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We know that we have written a module, which is not a smi.
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteContextSlot(cp,
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Context::SlotOffset(variable->index()),
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            r1,
950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            r3,
951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            kLRHasBeenSaved,
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            kDontSaveFPRegs,
953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            EMIT_REMEMBERED_SET,
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            OMIT_SMI_CHECK);
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS);
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Traverse into body.
958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Visit(declaration->module());
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VariableProxy* proxy = declaration->proxy();
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Variable* variable = proxy->var();
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (variable->location()) {
966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::UNALLOCATED:
967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // TODO(rossberg)
968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::CONTEXT: {
971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ ImportDeclaration");
972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitDebugCheckDeclarationContext(variable);
973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // TODO(rossberg)
97469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
975d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::PARAMETER:
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::LOCAL:
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::LOOKUP:
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
9813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
9833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) {
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(rossberg)
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
990d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
9913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
9923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // The context is the first argument.
993589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ mov(r1, Operand(pairs));
994589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags())));
995589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ Push(cp, r1, r0);
996589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ CallRuntime(Runtime::kDeclareGlobals, 3);
9973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
9983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
9993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) {
1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Call the runtime to declare the modules.
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(descriptions);
1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kDeclareModules, 1);
1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return value is ignored.
1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
1010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ SwitchStatement");
1011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Breakable nested_statement(this, stmt);
1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
1013e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Keep the switch value on the stack until a case matches.
10150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(stmt->tag());
1016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
1017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<CaseClause*>* clauses = stmt->cases();
1019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
1020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label next_test;  // Recycled for each test.
1022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the tests with branches to their bodies.
1023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
1024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
10258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    clause->body_target()->Unuse();
10261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The default is not a test, but remember it as final fall through.
1028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (clause->is_default()) {
1029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      default_clause = clause;
1030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      continue;
1031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case comparison");
1034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&next_test);
1035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    next_test.Unuse();
1036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Compile the label expression.
10380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(clause->label());
1039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
104080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Perform the comparison as if via '==='.
1041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(r1, MemOperand(sp, 0));  // Switch value.
10420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
10431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    JumpPatchSite patch_site(masm_);
10440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (inline_smi_code) {
104580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label slow_case;
104680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ orr(r2, r1, r0);
10471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      patch_site.EmitJumpIfNotSmi(r2, &slow_case);
10481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
104980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ cmp(r1, r0);
105080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ b(ne, &next_test);
105180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ Drop(1);  // Switch value is no longer needed.
10528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      __ b(clause->body_target());
10531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ bind(&slow_case);
105480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
105580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
10561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Record position before stub call for type feedback.
10571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    SetSourcePosition(clause->position());
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Code> ic =
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallIC(ic, clause->CompareId());
10613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    patch_site.EmitPatchInfo();
1062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label skip;
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(&skip);
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrepareForBailout(clause, TOS_REG);
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(r0, ip);
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(ne, &next_test);
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Drop(1);
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(clause->body_target());
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&skip);
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(r0, Operand::Zero());
1074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(ne, &next_test);
1075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
10768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ b(clause->body_target());
1077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Discard the test value and jump to the default if present, otherwise to
1080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the end of the statement.
1081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&next_test);
1082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(1);  // Switch value is no longer needed.
1083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (default_clause == NULL) {
108469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ b(nested_statement.break_label());
1085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
10868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ b(default_clause->body_target());
1087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the case bodies.
1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
1091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case body");
1092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
10938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ bind(clause->body_target());
109444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
1095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitStatements(clause->statements());
1096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
109869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(nested_statement.break_label());
1099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ ForInStatement");
1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int slot = stmt->ForInFeedbackSlot();
1106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
1107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label loop, exit;
1109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ForIn loop_statement(this, stmt);
1110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  increment_loop_depth();
1111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the object to enumerate over. If the object is null or undefined, skip
1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // over the loop.  See ECMA-262 version 5, section 12.6.4.
11140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(stmt->enumerable());
1115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, ip);
1117f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, &exit);
1118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register null_value = r5;
1119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ LoadRoot(null_value, Heap::kNullValueRootIndex);
1120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(r0, null_value);
1121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, &exit);
1122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the object to a JS object.
1126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label convert, done_convert;
11271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, &convert);
11283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
11293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ b(ge, &done_convert);
1130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&convert);
1131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);
1132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done_convert);
1134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);
1135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
11363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for proxies.
11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label call_runtime;
11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE);
11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(le, &call_runtime);
11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check cache validity in generated code. This is a fast case for
1143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
1144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // guarantee cache validity, call the runtime system to check cache
1145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // validity or get the property names in a fixed array.
11463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckEnumCache(null_value, &call_runtime);
1147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // The enum cache is valid.  Load the map of the object being
1149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // iterated over and use the cache for the iteration.
1150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Label use_cache;
1151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
1152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(&use_cache);
1153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the set of properties to enumerate.
1155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&call_runtime);
1156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);  // Duplicate the enumerable object on the stack.
1157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If we got a map from the runtime call, we can do a fast
1160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // modification check. Otherwise, we got a fixed array, and we have
1161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // to do a slow check.
1162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label fixed_array;
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
1164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(ip, Heap::kMetaMapRootIndex);
1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(r2, ip);
1166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &fixed_array);
1167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a map in register r0. Get the enumeration cache from it.
1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_descriptors;
1170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&use_cache);
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ EnumLength(r1, r0);
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(r1, Operand(Smi::FromInt(0)));
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(eq, &no_descriptors);
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadInstanceDescriptors(r0, r2);
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheOffset));
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheBridgeCacheOffset));
1179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
11803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the four remaining stack slots.
1181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);  // Map.
1182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r0, Operand(Smi::FromInt(0)));
1183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Push enumeration cache, enumeration cache length (as smi) and zero.
1184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(r2, r1, r0);
1185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
1186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&no_descriptors);
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Drop(1);
1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&exit);
1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1191f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a fixed array in register r0. Iterate through that.
11923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label non_proxy;
1193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&fixed_array);
11943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(r1, FeedbackVector());
1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r2, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate())));
1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r2, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(slot)));
11983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r1, Operand(Smi::FromInt(1)));  // Smi indicates slow check
12003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(r2, MemOperand(sp, 0 * kPointerSize));  // Get enumerated object
12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
12023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE);
12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(gt, &non_proxy);
12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r1, Operand(Smi::FromInt(0)));  // Zero indicates proxy
12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&non_proxy);
12063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(r1, r0);  // Smi and array
1207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset));
1208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r0, Operand(Smi::FromInt(0)));
1209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(r1, r0);  // Fixed array length (as smi) and initial index.
1210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for doing the condition check.
12123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&loop);
1214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the current count to r0, load the length to r1.
1215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
1216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, r1);  // Compare to the array length.
121769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ b(hs, loop_statement.break_label());
1218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the current entry of the array into register r3.
1220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(sp, 2 * kPointerSize));
1221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r3, MemOperand::PointerAddressFromSmiKey(r2, r0));
1223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
12243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the expected map from the stack or a smi in the
1225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // permanent slow case into register r2.
1226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(sp, 3 * kPointerSize));
1227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the expected map still matches that of the enumerable.
12293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If not, we may have to filter the key.
1230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label update_each;
1231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, MemOperand(sp, 4 * kPointerSize));
1232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset));
1233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r4, Operand(r2));
1234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, &update_each);
1235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
12363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For proxies, no filtering is done.
12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r2, Operand(Smi::FromInt(0)));
12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(eq, &update_each);
12403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1241756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Convert the entry to a string or (smi) 0 if it isn't a property
1242756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // any more. If the property has been removed while iterating, we
1243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // just skip it.
1244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r1);  // Enumerable.
1245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r3);  // Current entry.
1246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1247756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ mov(r3, Operand(r0), SetCC);
124869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ b(eq, loop_statement.continue_label());
1249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the 'each' property or variable from the possibly filtered
1251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // entry in register r3.
1252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&update_each);
1253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(result_register(), r3);
1254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Perform the assignment as if via '='.
1255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { EffectContext context(this);
12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAssignment(stmt->each());
1257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the body of the loop.
1260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Visit(stmt->body());
1261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the going to the next element by incrementing
1263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the index (smi) stored on top of the stack.
126469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.continue_label());
1265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r0);
1266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(r0, r0, Operand(Smi::FromInt(1)));
1267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);
1268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBackEdgeBookkeeping(stmt, &loop);
1270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ b(&loop);
1271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Remove the pointers stored on the stack.
127369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.break_label());
1274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(5);
1275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Exit and decrement the loop depth.
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
1279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  decrement_loop_depth();
1280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
12813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ ForOfStatement");
1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetStatementPosition(stmt);
1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Iteration loop_statement(this, stmt);
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  increment_loop_depth();
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // var iterator = iterable[Symbol.iterator]();
1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForEffect(stmt->assign_iterator());
1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loop entry.
1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(loop_statement.continue_label());
1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // result = iterator.next()
1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForEffect(stmt->next_result());
1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // if (result.done) break;
1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label result_not_done;
1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForControl(stmt->result_done(),
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  loop_statement.break_label(),
1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &result_not_done,
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &result_not_done);
1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&result_not_done);
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // each = result.value
1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForEffect(stmt->assign_each());
1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generate code for the body of the loop.
1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Visit(stmt->body());
1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check stack before looping.
1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(loop_statement.continue_label());
1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Exit and decrement the loop depth.
1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(loop_statement.break_label());
1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  decrement_loop_depth();
1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
13268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                       bool pretenure) {
1327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Use the fast case closure allocation code that allocates in new
1328e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // space for nested functions that don't need literals cloning. If
1329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // we're running with the --always-opt or the --prepare-always-opt
1330e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // flag, we need to use the runtime function so that the new function
1331e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // we are creating here gets a chance to have its code optimized and
1332e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // doesn't just get a copy of the existing unoptimized code.
1333e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!FLAG_always_opt &&
1334e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      !FLAG_prepare_always_opt &&
133544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      !pretenure &&
1336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      scope()->is_function_scope() &&
133744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      info->num_literals() == 0) {
1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(r2, Operand(info));
1340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
1341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r0, Operand(info));
13438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ LoadRoot(r1, pretenure ? Heap::kTrueValueRootIndex
13448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                              : Heap::kFalseValueRootIndex);
13458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Push(cp, r0, r1);
13468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ CallRuntime(Runtime::kNewClosure, 3);
1347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
13480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
13493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
13503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1352d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
13533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ VariableProxy");
13543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  EmitVariableLoad(expr);
1355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cnmt(masm_, "[ SuperReference ");
1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(LoadDescriptor::ReceiverRegister(),
1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(LoadDescriptor::NameRegister(), home_object_symbol);
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(r0, Operand(isolate()->factory()->undefined_value()));
1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(ne, &done);
1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kThrowNonMethodError, 0);
1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
1378589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                      TypeofState typeof_state,
1379589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                      Label* slow) {
1380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register current = cp;
1381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register next = r1;
1382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register temp = r2;
1383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Scope* s = scope();
1385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  while (s != NULL) {
1386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (s->num_heap_slots() > 0) {
1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (s->calls_sloppy_eval()) {
1388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Check that extension is NULL.
1389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX));
1390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ tst(temp, temp);
1391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ b(ne, slow);
1392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
1393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Load next context in chain.
13943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ ldr(next, ContextOperand(current, Context::PREVIOUS_INDEX));
1395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Walk the rest of the chain without clobbering cp.
1396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      current = next;
1397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // If no outer scope calls eval, we do not need to check more
1399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // context extensions.
1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break;
1401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    s = s->outer_scope();
1402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (s->is_eval_scope()) {
1405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label loop, fast;
1406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!current.is(next)) {
1407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Move(next, current);
1408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&loop);
1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Terminate at native context.
1411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset));
1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(ip, Heap::kNativeContextMapRootIndex);
1413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ cmp(temp, ip);
1414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ b(eq, &fast);
1415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that extension is NULL.
1416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX));
1417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ tst(temp, temp);
1418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ b(ne, slow);
1419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Load next context in chain.
14203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ ldr(next, ContextOperand(next, Context::PREVIOUS_INDEX));
1421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ b(&loop);
1422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&fast);
1423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(LoadDescriptor::NameRegister(), Operand(proxy->var()->name()));
1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_vector_ics) {
1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(VectorLoadICDescriptor::SlotRegister(),
1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           Operand(Smi::FromInt(proxy->VariableFeedbackSlot())));
1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? NOT_CONTEXTUAL
1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : CONTEXTUAL;
1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallLoadIC(mode);
1436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1439589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1440589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                                Label* slow) {
1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsContextSlot());
1442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register context = cp;
144359151504615d929945dc59db37bf1166937748c6Steve Block  Register next = r3;
144459151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = r4;
144559151504615d929945dc59db37bf1166937748c6Steve Block
1446589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
144759151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (s->calls_sloppy_eval()) {
144959151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
1450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX));
145159151504615d929945dc59db37bf1166937748c6Steve Block        __ tst(temp, temp);
145259151504615d929945dc59db37bf1166937748c6Steve Block        __ b(ne, slow);
145359151504615d929945dc59db37bf1166937748c6Steve Block      }
14543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ ldr(next, ContextOperand(context, Context::PREVIOUS_INDEX));
145559151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering cp.
1456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      context = next;
145759151504615d929945dc59db37bf1166937748c6Steve Block    }
145859151504615d929945dc59db37bf1166937748c6Steve Block  }
145959151504615d929945dc59db37bf1166937748c6Steve Block  // Check that last extension is NULL.
1460e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX));
146159151504615d929945dc59db37bf1166937748c6Steve Block  __ tst(temp, temp);
146259151504615d929945dc59db37bf1166937748c6Steve Block  __ b(ne, slow);
1463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1464e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // This function is used only for loads, not stores, so it's safe to
1465e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // return an cp-based operand (the write barrier cannot be allowed to
1466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // destroy the cp register).
1467589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return ContextOperand(context, var->index());
146859151504615d929945dc59db37bf1166937748c6Steve Block}
146959151504615d929945dc59db37bf1166937748c6Steve Block
147059151504615d929945dc59db37bf1166937748c6Steve Block
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
1472589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                  TypeofState typeof_state,
1473589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                  Label* slow,
1474589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                  Label* done) {
147559151504615d929945dc59db37bf1166937748c6Steve Block  // Generate fast-case code for variables that might be shadowed by
147659151504615d929945dc59db37bf1166937748c6Steve Block  // eval-introduced variables.  Eval is used a lot without
147759151504615d929945dc59db37bf1166937748c6Steve Block  // introducing variables.  In those cases, we do not want to
147859151504615d929945dc59db37bf1166937748c6Steve Block  // perform a runtime call for all variables in the scope
147959151504615d929945dc59db37bf1166937748c6Steve Block  // containing the eval.
1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Variable* var = proxy->var();
14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (var->mode() == DYNAMIC_GLOBAL) {
1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitLoadGlobalCheckExtensions(proxy, typeof_state, slow);
148359151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(done);
14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (var->mode() == DYNAMIC_LOCAL) {
1485589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Variable* local = var->local_if_not_shadowed();
1486589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow));
1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (local->mode() == LET || local->mode() == CONST ||
1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        local->mode() == CONST_LEGACY) {
1489589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (local->mode() == CONST_LEGACY) {
14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {  // LET || CONST
14933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ b(ne, done);
14943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(r0, Operand(var->name()));
14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ push(r0);
14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CallRuntime(Runtime::kThrowReferenceError, 1);
14973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
149859151504615d929945dc59db37bf1166937748c6Steve Block    }
1499589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ jmp(done);
150059151504615d929945dc59db37bf1166937748c6Steve Block  }
150159151504615d929945dc59db37bf1166937748c6Steve Block}
150259151504615d929945dc59db37bf1166937748c6Steve Block
150359151504615d929945dc59db37bf1166937748c6Steve Block
15043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
15053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Record position before possible IC call.
15063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SetSourcePosition(proxy->position());
15073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Variable* var = proxy->var();
15083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1509589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Three cases: global variables, lookup variables, and all other types of
1510589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // variables.
1511589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (var->location()) {
1512589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::UNALLOCATED: {
1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ Global variable");
1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(LoadDescriptor::NameRegister(), Operand(var->name()));
1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (FLAG_vector_ics) {
1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov(VectorLoadICDescriptor::SlotRegister(),
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               Operand(Smi::FromInt(proxy->VariableFeedbackSlot())));
1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallLoadIC(CONTEXTUAL);
1521589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      context()->Plug(r0);
1522589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1523589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
152459151504615d929945dc59db37bf1166937748c6Steve Block
1525589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::PARAMETER:
1526589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOCAL:
1527589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::CONTEXT: {
1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               : "[ Stack variable");
15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (var->binding_needs_init()) {
15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // var->scope() may be NULL when the proxy is located in eval code and
15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // refers to a potential outside binding. Currently those bindings are
15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // always looked up dynamically, i.e. in that case
15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //     var->location() == LOOKUP.
15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // always holds.
1536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(var->scope() != NULL);
15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Check if the binding really needs an initialization check. The check
15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // can be skipped in the following situation: we have a LET or CONST
15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // binding in harmony mode, both the Variable and the VariableProxy have
15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // the same declaration scope (i.e. they are both in global code, in the
15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // same function or in the same eval code) and the VariableProxy is in
15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // the source physically located after the initializer of the variable.
15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We cannot skip any initialization checks for CONST in non-harmony
15463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // mode because const variables may be declared but never initialized:
15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //   if (false) { const x; }; var y = x;
15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The condition on the declaration scopes is a conservative check for
15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // nested functions that access a binding and are called before the
15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // binding is initialized:
15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //   function() { f(); let x = 1; function f() { x = 2; } }
15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bool skip_init_check;
15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
15563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          skip_init_check = false;
1557589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        } else {
15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Check that we always have valid source position.
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          DCHECK(var->initializer_position() != RelocInfo::kNoPosition);
1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          DCHECK(proxy->position() != RelocInfo::kNoPosition);
1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          skip_init_check = var->mode() != CONST_LEGACY &&
15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              var->initializer_position() < proxy->position();
15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!skip_init_check) {
15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Let and const need a read barrier.
15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          GetVar(r0, var);
15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (var->mode() == LET || var->mode() == CONST) {
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // Throw a reference error when using an uninitialized let/const
15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // binding in harmony mode.
15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Label done;
15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ b(ne, &done);
15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ mov(r0, Operand(var->name()));
15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ push(r0);
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ CallRuntime(Runtime::kThrowReferenceError, 1);
15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ bind(&done);
15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else {
15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // Uninitalized const bindings outside of harmony mode are unholed.
1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            DCHECK(var->mode() == CONST_LEGACY);
15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          context()->Plug(r0);
15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          break;
1585589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        }
1586589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      context()->Plug(var);
1588589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1589589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
1590d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1591589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOOKUP: {
1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ Lookup variable");
1593589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Label done, slow;
1594589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Generate code for loading from variables potentially shadowed
1595589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // by eval-introduced variables.
1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
1597589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ bind(&slow);
1598589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(r1, Operand(var->name()));
1599589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ Push(cp, r1);  // Context and name.
1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kLoadLookupSlot, 2);
160169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ bind(&done);
160269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      context()->Plug(r0);
16030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
16043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
16053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1608d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ RegExpLiteral");
1610bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label materialized;
16113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Registers will be used as follows:
1612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // r5 = materialized value (RegExp literal)
16133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r4 = JS function, literals array
16143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r3 = literal index
16153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r2 = RegExp pattern
16163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r1 = RegExp flags
1617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // r0 = RegExp literal clone
161880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
161980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
16203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int literal_offset =
162180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1622e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(r5, FieldMemOperand(r4, literal_offset));
16233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(r5, ip);
1625bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(ne, &materialized);
162680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
162780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Create regexp literal using runtime function.
162880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Result will be in r0.
16293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r3, Operand(Smi::FromInt(expr->literal_index())));
16303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r2, Operand(expr->pattern()));
16313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r1, Operand(expr->flags()));
16326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(r4, r3, r2, r1);
16333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ mov(r5, r0);
163580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1636bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&materialized);
1637bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1638e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Label allocated, runtime_allocate;
1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT);
1640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ jmp(&allocated);
1641e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1642e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&runtime_allocate);
1643bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(r0, Operand(Smi::FromInt(size)));
1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(r5, r0);
1645bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1646e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ pop(r5);
164780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1648e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&allocated);
1649bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // After this, registers are used as follows:
1650bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // r0: Newly allocated regexp.
1651e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // r5: Materialized regexp.
1652bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // r2: temp.
1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CopyFields(r0, r5, d0, size / kPointerSize);
16540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
1655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAccessor(Expression* expression) {
16593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expression == NULL) {
16603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(r1, Heap::kNullValueRootIndex);
16613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r1);
16623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
16633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForStackValue(expression);
16643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
16653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1668d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  expr->BuildConstantProperties(isolate());
16723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> constant_properties = expr->constant_properties();
1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
16746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
16756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
16763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r1, Operand(constant_properties));
167744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int flags = expr->fast_elements()
167844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? ObjectLiteral::kFastElements
167944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : ObjectLiteral::kNoFlags;
168044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  flags |= expr->has_function()
168144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? ObjectLiteral::kHasFunction
168244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : ObjectLiteral::kNoFlags;
168344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(r0, Operand(Smi::FromInt(flags)));
16843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int properties_count = constant_properties->length() / 2;
1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expr->may_store_doubles() || expr->depth() > 1 ||
1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements ||
16873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(r3, r2, r1, r0);
1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
16903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FastCloneShallowObjectStub stub(isolate(), properties_count);
16923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
1693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
1696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in r0.
1697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
1698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
16993e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Mark all computed expressions that are bound to a key that
17003e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // is shadowed by a later occurrence of the same key. For the
17013e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // marked expressions, no store code is emitted.
1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  expr->CalculateEmitStore(zone());
17033e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AccessorTable accessor_table(zone());
1705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < expr->properties()->length(); i++) {
1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectLiteral::Property* property = expr->properties()->at(i);
1707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
1708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = property->key();
1710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
1711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
1712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ push(r0);  // Save result on stack
1713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
1714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
1716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::CONSTANT:
1717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        UNREACHABLE();
1718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (key->value()->IsInternalizedString()) {
17233e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          if (property->emit_store()) {
1724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            VisitForAccumulatorValue(value);
1725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            DCHECK(StoreDescriptor::ValueRegister().is(r0));
1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ mov(StoreDescriptor::NameRegister(), Operand(key->value()));
1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            CallStoreIC(key->LiteralFeedbackId());
1729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            PrepareForBailoutForId(key->id(), NO_REGISTERS);
1730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else {
1731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            VisitForEffect(value);
17323e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          }
1733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Duplicate receiver on stack.
1736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ ldr(r0, MemOperand(sp));
1737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(r0);
17380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(key);
17390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(value);
17403e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        if (property->emit_store()) {
1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ mov(r0, Operand(Smi::FromInt(SLOPPY)));  // PropertyAttributes
1742e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(r0);
1743e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ CallRuntime(Runtime::kSetProperty, 4);
17443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        } else {
17453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          __ Drop(3);
17463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        }
1747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case ObjectLiteral::Property::PROTOTYPE:
1749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Duplicate receiver on stack.
1750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ ldr(r0, MemOperand(sp));
1751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ push(r0);
1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(value);
1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (property->emit_store()) {
1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ CallRuntime(Runtime::kSetPrototype, 2);
1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Drop(2);
1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::GETTER:
17613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        accessor_table.lookup(key)->second->getter = value;
17623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
1763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::SETTER:
17643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        accessor_table.lookup(key)->second->setter = value;
1765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1768e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
17693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Emit code to define accessors, using only a single call to the runtime for
17703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // each pair of corresponding getters and setters.
17713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (AccessorTable::Iterator it = accessor_table.begin();
17723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       it != accessor_table.end();
17733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       ++it) {
17743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, MemOperand(sp));  // Duplicate receiver.
17753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);
17763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForStackValue(it->first);
17773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAccessor(it->second->getter);
17783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAccessor(it->second->setter);
17793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r0, Operand(Smi::FromInt(NONE)));
17803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);
1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
17823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
17833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
178444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (expr->has_function()) {
1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(result_saved);
178644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ ldr(r0, MemOperand(sp));
178744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ push(r0);
178844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
178944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
179044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1791e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
17920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1793e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
17940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
17953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
17963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
17973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1799d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
18003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
1801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  expr->BuildConstantElements(isolate());
1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int flags = expr->depth() == 1
1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? ArrayLiteral::kShallowElements
1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : ArrayLiteral::kNoFlags;
1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<Expression*>* subexprs = expr->values();
1808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int length = subexprs->length();
18093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> constant_elements = expr->constant_elements();
1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(2, constant_elements->length());
18113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsKind constant_elements_kind =
18123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind);
18143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArrayBase> constant_elements_values(
18153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FixedArrayBase::cast(constant_elements->get(1)));
1816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (has_fast_elements && !FLAG_allocation_site_pretenuring) {
1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If the only customer of allocation sites is transitioning, then
1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // we can turn it off if we don't have anywhere else to transition to.
1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
18253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
18263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
18273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r1, Operand(constant_elements));
1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) {
1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(r0, Operand(Smi::FromInt(flags)));
1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(r3, r2, r1, r0);
1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
1832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
1834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
18353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
18363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
18383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
18403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
1841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < length; i++) {
18423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Expression* subexpr = subexprs->at(i);
18433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
18443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
1845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
18463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
18483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(r0);
1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(Smi::FromInt(expr->literal_index()));
18503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
18513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
18520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(subexpr);
18533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsFastObjectElementsKind(constant_elements_kind)) {
18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldr(r6, MemOperand(sp, kPointerSize));  // Copy of array literal.
18573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r1, FieldMemOperand(r6, JSObject::kElementsOffset));
18583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(result_register(), FieldMemOperand(r1, offset));
18593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Update the write barrier for the array store.
18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWriteField(r1, offset, result_register(), r2,
18613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          kLRHasBeenSaved, kDontSaveFPRegs,
18623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          EMIT_REMEMBERED_SET, INLINE_SMI_CHECK);
18633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
18643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(r3, Operand(Smi::FromInt(i)));
1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      StoreArrayLiteralElementStub stub(isolate());
18663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CallStub(&stub);
18673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
18703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
18713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1872e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pop();  // literal index
18740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1875e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
18760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
18773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
18783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
18793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1881402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->target()->IsValidReferenceExpression());
1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1884402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Comment cmnt(masm_, "[ Assignment");
1885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1886402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Left-hand side can only be a property, a global or a (parameter or local)
18873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot.
1888402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1889402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LhsKind assign_type = VARIABLE;
189080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Property* property = expr->target()->AsProperty();
189180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (property != NULL) {
189280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    assign_type = (property->key()->IsPropertyName())
189380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? NAMED_PROPERTY
189480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : KEYED_PROPERTY;
1895402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1896402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1897402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate LHS expression.
1898402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1899402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1900402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Nothing to do here.
1901402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1902402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1903402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // We need the receiver both on the stack and in the register.
1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->obj());
1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
1907402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
19080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
1909402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1910402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1911402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
191225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      if (expr->is_compound()) {
19133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->obj());
1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->key());
1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ ldr(LoadDescriptor::ReceiverRegister(),
1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               MemOperand(sp, 1 * kPointerSize));
1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0));
191825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      } else {
19193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->obj());
19203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->key());
192125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      }
1922402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1923402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1924402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
19258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // For compound assignments we need another deoptimization point after the
19268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // variable/property load.
1927402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
19280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    { AccumulatorValueContext context(this);
19290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
19300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
19313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          EmitVariableLoad(expr->target()->AsVariableProxy());
19328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          PrepareForBailout(expr->target(), TOS_REG);
19330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
19340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
19350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitNamedPropertyLoad(property);
1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          PrepareForBailoutForId(property->LoadId(), TOS_REG);
19370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
19380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
19390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitKeyedPropertyLoad(property);
1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          PrepareForBailoutForId(property->LoadId(), TOS_REG);
19410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
19420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
1943402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1944402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
194580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Token::Value op = expr->binary_op();
1946e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ push(r0);  // Left operand goes on the stack.
1947e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    VisitForAccumulatorValue(expr->value());
1948402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
194980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
195080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? OVERWRITE_RIGHT
195180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : NO_OVERWRITE;
195280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    SetSourcePosition(expr->position() + 1);
19530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
195480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (ShouldInlineSmiCase(op)) {
1955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitInlineSmiBinaryOp(expr->binary_operation(),
195680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            op,
195780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            mode,
195880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            expr->target(),
1959e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                            expr->value());
196080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    } else {
1961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitBinaryOp(expr->binary_operation(), op, mode);
196280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
1963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Deoptimization point in case the binary operation may have side effects.
1965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailout(expr->binary_operation(), TOS_REG);
196680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
19670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->value());
1968402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1969402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1970402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Record source position before possible IC call.
1971402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  SetSourcePosition(expr->position());
1972402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1973402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Store the value.
1974402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1975402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1976402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
19770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             expr->op());
1978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      context()->Plug(r0);
1980402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1981402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1982402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitNamedPropertyAssignment(expr);
1983402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1984402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1985402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitKeyedPropertyAssignment(expr);
1986402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1987402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1988402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1989402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1990402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitYield(Yield* expr) {
1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ Yield");
1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Evaluate yielded value first; the initial iterator definition depends on
1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this.  It stays on the stack while we update the iterator.
1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(expr->expression());
1996e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (expr->yield_kind()) {
1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Yield::kSuspend:
1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Pop value from top-of-stack slot; box result into result register.
2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitCreateIteratorResult(false);
2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ push(result_register());
2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Fall through.
2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Yield::kInitial: {
2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label suspend, continuation, post_runtime, resume;
2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&suspend);
2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&continuation);
2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&resume);
2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&suspend);
2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(expr->generator_object());
2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
2014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(r1, Operand(Smi::FromInt(continuation.pos())));
2015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset));
2016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset));
2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(r1, cp);
2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2,
2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          kLRHasBeenSaved, kDontSaveFPRegs);
2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ add(r1, fp, Operand(StandardFrameConstants::kExpressionsOffset));
2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmp(sp, r1);
2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ b(eq, &post_runtime);
2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ push(r0);  // generator object
2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&post_runtime);
2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pop(result_register());
2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitReturnSequence();
2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&resume);
2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context()->Plug(result_register());
2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2034e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Yield::kFinal: {
2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(expr->generator_object());
2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(r1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ str(r1, FieldMemOperand(result_register(),
2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 JSGeneratorObject::kContinuationOffset));
2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Pop value from top-of-stack slot, box result into result register.
2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitCreateIteratorResult(true);
2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitUnwindBeforeReturn();
2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitReturnSequence();
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2046e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Yield::kDelegating: {
2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForStackValue(expr->generator_object());
2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Initial stack layout is as follows:
2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // [sp + 1 * kPointerSize] iter
2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // [sp + 0 * kPointerSize] g
2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label l_catch, l_try, l_suspend, l_continuation, l_resume;
2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label l_next, l_call, l_loop;
2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register load_receiver = LoadDescriptor::ReceiverRegister();
2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register load_name = LoadDescriptor::NameRegister();
2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Initial send value is undefined.
2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ b(&l_next);
2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_catch);
2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(load_name, Heap::kthrow_stringRootIndex);  // "throw"
2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldr(r3, MemOperand(sp, 1 * kPointerSize));          // iter
2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(load_name, r3, r0);                       // "throw", iter, except
2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&l_call);
2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // try { received = %yield result }
2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Shuffle the received result above a try handler and yield it without
2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // re-boxing.
2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_try);
2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pop(r0);                                        // result
2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ PushTryHandler(StackHandler::CATCH, expr->index());
2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const int handler_size = StackHandlerConstants::kSize;
2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ push(r0);                                       // result
2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&l_suspend);
2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_continuation);
2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&l_resume);
2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_suspend);
2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const int generator_object_depth = kPointerSize + handler_size;
2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldr(r0, MemOperand(sp, generator_object_depth));
2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ push(r0);                                       // g
2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(r1, Operand(Smi::FromInt(l_continuation.pos())));
2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset));
2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset));
2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(r1, cp);
2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2,
2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          kLRHasBeenSaved, kDontSaveFPRegs);
2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pop(r0);                                      // result
2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitReturnSequence();
2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_resume);                              // received in r0
2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ PopTryHandler();
2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // receiver = iter; f = 'next'; arg = received;
2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_next);
2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(load_name, Heap::knext_stringRootIndex);  // "next"
2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldr(r3, MemOperand(sp, 1 * kPointerSize));         // iter
2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(load_name, r3, r0);                      // "next", iter, received
2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // result = receiver[f](arg);
2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_call);
2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldr(load_receiver, MemOperand(sp, kPointerSize));
2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldr(load_name, MemOperand(sp, 2 * kPointerSize));
2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (FLAG_vector_ics) {
2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov(VectorLoadICDescriptor::SlotRegister(),
2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               Operand(Smi::FromInt(expr->KeyedLoadFeedbackSlot())));
2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallIC(ic, TypeFeedbackId::None());
2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(r1, r0);
2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ str(r1, MemOperand(sp, 2 * kPointerSize));
2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallStub(&stub);
2121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Drop(1);  // The function is still on the stack; drop it.
2124e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // if (!result.done) goto l_try;
2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_loop);
2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(load_receiver, r0);
2128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ push(load_receiver);                               // save result
2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(load_name, Heap::kdone_stringRootIndex);  // "done"
2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (FLAG_vector_ics) {
2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov(VectorLoadICDescriptor::SlotRegister(),
2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               Operand(Smi::FromInt(expr->DoneFeedbackSlot())));
2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallLoadIC(NOT_CONTEXTUAL);                           // r0=result.done
2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallIC(bool_ic);
2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmp(r0, Operand(0));
2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ b(eq, &l_try);
2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // result.value
2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pop(load_receiver);                                 // result
2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(load_name, Heap::kvalue_stringRootIndex);  // "value"
2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (FLAG_vector_ics) {
2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov(VectorLoadICDescriptor::SlotRegister(),
2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               Operand(Smi::FromInt(expr->ValueFeedbackSlot())));
2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallLoadIC(NOT_CONTEXTUAL);                            // r0=result.value
2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context()->DropAndPlug(2, r0);                         // drop iter and g
2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitGeneratorResume(Expression *generator,
2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Expression *value,
2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JSGeneratorObject::ResumeMode resume_mode) {
2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The value stays in r0, and is ultimately read by the resumed generator, as
2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
2161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // is read to throw the value when the resumed generator is already closed.
2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r1 will hold the generator object until the activation has been resumed.
2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(generator);
2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(value);
2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(r1);
2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check generator state.
2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label wrong_state, closed_state, done;
2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset));
2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(r3, Operand(Smi::FromInt(0)));
2173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(eq, &closed_state);
2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(lt, &wrong_state);
2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load suspended function and context.
2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(cp, FieldMemOperand(r1, JSGeneratorObject::kContextOffset));
2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r4, FieldMemOperand(r1, JSGeneratorObject::kFunctionOffset));
2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load receiver and store as the first argument.
2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r2, FieldMemOperand(r1, JSGeneratorObject::kReceiverOffset));
2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(r2);
2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push holes for the rest of the arguments to the generator function.
2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r3, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r3,
2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(r2, Heap::kTheHoleValueRootIndex);
2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label push_argument_holes, push_frame;
2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&push_argument_holes);
2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub(r3, r3, Operand(Smi::FromInt(1)), SetCC);
2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(mi, &push_frame);
2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(r2);
2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&push_argument_holes);
2195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Enter a new JavaScript frame, and initialize its slots as they were when
2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the generator was suspended.
2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label resume_frame;
2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&push_frame);
2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bl(&resume_frame);
2201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ jmp(&done);
2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&resume_frame);
2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // lr = return address.
2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // fp = caller's frame pointer.
2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // pp = caller's constant pool (if FLAG_enable_ool_constant_pool),
2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cp = callee's context,
2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r4 = callee's JS function.
2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PushFixedFrame(r4);
2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Adjust FP to point to saved FP.
2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the operand stack size.
2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset));
2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r3, FieldMemOperand(r3, FixedArray::kLengthOffset));
2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiUntag(r3);
2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If we are sending a value and there is no operand stack, we can jump back
2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // in directly.
2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (resume_mode == JSGeneratorObject::NEXT) {
2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label slow_resume;
2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(r3, Operand(0));
2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(ne, &slow_resume);
2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(r3, FieldMemOperand(r4, JSFunction::kCodeEntryOffset));
2224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    { ConstantPoolUnavailableScope constant_pool_unavailable(masm_);
2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (FLAG_enable_ool_constant_pool) {
2227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Load the new code object's constant pool pointer.
2228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ ldr(pp,
2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               MemOperand(r3, Code::kConstantPoolOffset - Code::kHeaderSize));
2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldr(r2, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset));
2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ SmiUntag(r2);
2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ add(r3, r3, r2);
2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(r2, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ str(r2, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset));
2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Jump(r3);
2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&slow_resume);
2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Otherwise, we push holes for the operand stack and call the runtime to fix
2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // up the stack and the handlers.
2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label push_operand_holes, call_resume;
2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&push_operand_holes);
2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub(r3, r3, Operand(1), SetCC);
2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(mi, &call_resume);
2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(r2);
2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(&push_operand_holes);
2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&call_resume);
2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result_register().is(r1));
2252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(r1, result_register());
2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(Smi::FromInt(resume_mode));
2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3);
2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Not reached: the runtime call returns elsewhere.
2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ stop("not-reached");
2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Reach here when generator is closed.
2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&closed_state);
2260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (resume_mode == JSGeneratorObject::NEXT) {
2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Return completed iterator result when generator is closed.
2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(r2);
2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Pop value from top-of-stack slot; box result into result register.
2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitCreateIteratorResult(true);
2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Throw the provided value.
2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(r0);
2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntime(Runtime::kThrow, 1);
2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done);
2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Throw error if we attempt to operate on a running generator.
2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&wrong_state);
2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(r1);
2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kThrowGeneratorStateError, 1);
2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(result_register());
2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCreateIteratorResult(bool done) {
2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label gc_required;
2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label allocated;
2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Map> map(isolate()->native_context()->iterator_result_map());
2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Allocate(map->instance_size(), r0, r2, r3, &gc_required, TAG_OBJECT);
2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&allocated);
2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&gc_required);
2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(Smi::FromInt(map->instance_size()));
2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(context_register(),
2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         MemOperand(fp, StandardFrameConstants::kContextOffset));
2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&allocated);
2299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r1, Operand(map));
2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(r2);
2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r3, Operand(isolate()->factory()->ToBoolean(done)));
2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r4, Operand(isolate()->factory()->empty_fixed_array()));
2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(map->instance_size(), 5 * kPointerSize);
2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset));
2306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r2,
2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldMemOperand(r0, JSGeneratorObject::kResultValuePropertyOffset));
2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r3,
2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldMemOperand(r0, JSGeneratorObject::kResultDonePropertyOffset));
2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Only the value field needs a write barrier, as the other values are in the
2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // root set.
2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteField(r0, JSGeneratorObject::kResultValuePropertyOffset,
2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      r2, r3, kLRHasBeenSaved, kDontSaveFPRegs);
2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetSourcePosition(prop->position());
2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Literal* key = prop->key()->AsLiteral();
2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(LoadDescriptor::NameRegister(), Operand(key->value()));
2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_vector_ics) {
2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(VectorLoadICDescriptor::SlotRegister(),
2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           Operand(Smi::FromInt(prop->PropertyFeedbackSlot())));
2327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallLoadIC(NOT_CONTEXTUAL);
2328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
2335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetSourcePosition(prop->position());
2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Literal* key = prop->key()->AsLiteral();
2337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!key->value()->IsSmi());
2338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(prop->IsSuperAccess());
2339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SuperReference* super_ref = prop->obj()->AsSuperReference();
2341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitLoadHomeObject(super_ref);
2342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(r0);
2343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(super_ref->this_var());
2344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(key->value());
2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kLoadFromSuper, 3);
2346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetSourcePosition(prop->position());
2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_vector_ics) {
2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(VectorLoadICDescriptor::SlotRegister(),
2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           Operand(Smi::FromInt(prop->PropertyFeedbackSlot())));
2355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallIC(ic);
2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallIC(ic, prop->PropertyFeedbackId());
2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Token::Value op,
2364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              OverwriteMode mode,
2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Expression* left_expr,
2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Expression* right_expr) {
2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, smi_case, stub_call;
2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch1 = r2;
2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch2 = r3;
2371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the arguments.
2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register left = r1;
2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register right = r0;
2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(left);
2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Perform combined smi check on both operands.
2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ orr(scratch1, left, Operand(right));
2379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpPatchSite patch_site(masm_);
2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  patch_site.EmitJumpIfSmi(scratch1, &smi_case);
2382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&stub_call);
2384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code();
2385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(code, expr->BinaryOperationFeedbackId());
2386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  patch_site.EmitPatchInfo();
2387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done);
2388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&smi_case);
2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Smi case. This code works the same way as the smi-smi case in the type
2391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // recording binary operation stub, see
2392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (op) {
2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::SAR:
2394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ GetLeastBitsFromSmi(scratch1, right, 5);
2395e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(right, Operand(left, ASR, scratch1));
2396e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ bic(right, right, Operand(kSmiTagMask));
2397e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
2398e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::SHL: {
2399e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ SmiUntag(scratch1, left);
2400e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ GetLeastBitsFromSmi(scratch2, right, 5);
2401e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(scratch1, Operand(scratch1, LSL, scratch2));
2402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ TrySmiTag(right, scratch1, &stub_call);
2403e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
2404e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2405e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::SHR: {
2406e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ SmiUntag(scratch1, left);
2407e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ GetLeastBitsFromSmi(scratch2, right, 5);
2408e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(scratch1, Operand(scratch1, LSR, scratch2));
2409e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ tst(scratch1, Operand(0xc0000000));
2410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(ne, &stub_call);
2411e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ SmiTag(right, scratch1);
2412e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
2413e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2414e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::ADD:
2415e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ add(scratch1, left, Operand(right), SetCC);
2416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(vs, &stub_call);
2417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(right, scratch1);
2418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
2419e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::SUB:
2420e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ sub(scratch1, left, Operand(right), SetCC);
2421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(vs, &stub_call);
2422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(right, scratch1);
2423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
2424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::MUL: {
2425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ SmiUntag(ip, right);
2426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ smull(scratch1, scratch2, left, ip);
2427e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(ip, Operand(scratch1, ASR, 31));
2428e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ cmp(ip, Operand(scratch2));
2429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(ne, &stub_call);
2430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmp(scratch1, Operand::Zero());
2431e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(right, Operand(scratch1), LeaveCC, ne);
2432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(ne, &done);
2433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ add(scratch2, right, Operand(left), SetCC);
2434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(right, Operand(Smi::FromInt(0)), LeaveCC, pl);
2435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(mi, &stub_call);
2436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
2437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::BIT_OR:
2439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ orr(right, left, Operand(right));
2440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
2441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::BIT_AND:
2442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ and_(right, left, Operand(right));
2443e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
2444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::BIT_XOR:
2445e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ eor(right, left, Operand(right));
2446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
2447e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    default:
2448e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      UNREACHABLE();
2449e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&done);
2452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  context()->Plug(r0);
245380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
245480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
245580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
2457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Token::Value op,
245880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                     OverwriteMode mode) {
2459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(r1);
2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code();
24613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(code, expr->BinaryOperationFeedbackId());
24633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
24640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr) {
2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->IsValidReferenceExpression());
2470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand side can only be a property, a global or a (parameter or local)
24723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot.
2473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
2474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  LhsKind assign_type = VARIABLE;
2475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = expr->AsProperty();
2476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (prop != NULL) {
2477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    assign_type = (prop->key()->IsPropertyName())
2478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ? NAMED_PROPERTY
2479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        : KEYED_PROPERTY;
2480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (assign_type) {
2483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case VARIABLE: {
2484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->AsVariableProxy()->var();
24850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EffectContext context(this);
24860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitVariableAssignment(var, Token::ASSIGN);
2487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case NAMED_PROPERTY: {
2490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(r0);  // Preserve value.
24910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(StoreDescriptor::ReceiverRegister(), r0);
2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pop(StoreDescriptor::ValueRegister());  // Restore value.
2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(StoreDescriptor::NameRegister(),
2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             Operand(prop->key()->AsLiteral()->value()));
2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallStoreIC();
2497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case KEYED_PROPERTY: {
2500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(r0);  // Preserve value.
25013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForStackValue(prop->obj());
25023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForAccumulatorValue(prop->key());
2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(StoreDescriptor::NameRegister(), r0);
2504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(StoreDescriptor::ValueRegister(),
2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             StoreDescriptor::ReceiverRegister());
2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Code> ic =
2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code();
25083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallIC(ic);
2509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(r0);
2513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Variable* var, MemOperand location) {
2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(result_register(), location);
2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (var->IsContextSlot()) {
2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // RecordWrite may destroy all its register arguments.
2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(r3, result_register());
2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int offset = Context::SlotOffset(var->index());
2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ RecordWriteContextSlot(
2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs);
2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) {
2530589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsUnallocated()) {
2531589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Global var, const, or let.
2532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(StoreDescriptor::NameRegister(), Operand(var->name()));
2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallStoreIC();
2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (op == Token::INIT_CONST_LEGACY) {
2537589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Const initializers need a write barrier.
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!var->IsParameter());  // No const parameters.
2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (var->IsLookupSlot()) {
2540589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(r0);
2541589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(r0, Operand(var->name()));
2542589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ Push(cp, r0);  // Context and name.
2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3);
2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label skip;
2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MemOperand location = VarOperand(var, r1);
2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldr(r2, location);
2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
2550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ b(ne, &skip);
2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitStoreToStackLocalOrContextSlot(var, location);
2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&skip);
2553e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2554e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
25553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (var->mode() == LET && op != Token::INIT_LET) {
2556589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Non-initializing assignment to let variable needs a write barrier.
2557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!var->IsLookupSlot());
2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label assign;
2560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemOperand location = VarOperand(var, r1);
2561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(r3, location);
2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(ne, &assign);
2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(r3, Operand(var->name()));
2565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(r3);
2566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntime(Runtime::kThrowReferenceError, 1);
2567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Perform the assignment.
2568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&assign);
2569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitStoreToStackLocalOrContextSlot(var, location);
2570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
2572589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (var->IsLookupSlot()) {
2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Assignment to var.
2574589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(r0);  // Value.
2575589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(r1, Operand(var->name()));
2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(r0, Operand(Smi::FromInt(strict_mode())));
2577589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ Push(cp, r1, r0);  // Context, name, strict mode.
2578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kStoreLookupSlot, 4);
2579589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else {
2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Assignment to var or initializing assignment to let/const in harmony
2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // mode.
2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK((var->IsStackAllocated() || var->IsContextSlot()));
2583589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      MemOperand location = VarOperand(var, r1);
2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (generate_debug_code_ && op == Token::INIT_LET) {
2585589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // Check for an uninitialized let binding.
2586589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ ldr(r2, location);
2587589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Check(eq, kLetBindingReInitialization);
2589589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitStoreToStackLocalOrContextSlot(var, location);
25913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
25923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2593589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Non-initializing assignments to consts are ignored.
25943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
25953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
25963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2597d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
2599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(prop != NULL);
2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(prop->key()->IsLiteral());
2602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
2604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(StoreDescriptor::NameRegister(),
2606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Operand(prop->key()->AsLiteral()->value()));
2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(StoreDescriptor::ReceiverRegister());
2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStoreIC(expr->AssignmentFeedbackId());
2609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(r0);
2612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2615d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
2617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
2619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister());
2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(StoreDescriptor::ValueRegister().is(r0));
2622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> ic = CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code();
2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(ic, expr->AssignmentFeedbackId());
2625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(r0);
2628d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2631d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) {
2632d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Property");
2633d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* key = expr->key();
2634d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (key->IsPropertyName()) {
2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!expr->IsSuperAccess()) {
2637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(expr->obj());
2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(LoadDescriptor::ReceiverRegister(), r0);
2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitNamedPropertyLoad(expr);
2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitNamedSuperPropertyLoad(expr);
2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrepareForBailoutForId(expr->LoadId(), TOS_REG);
2644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    context()->Plug(r0);
2645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
26460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(expr->obj());
26470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->key());
2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(LoadDescriptor::NameRegister(), r0);
2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pop(LoadDescriptor::ReceiverRegister());
2650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitKeyedPropertyLoad(expr);
2651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    context()->Plug(r0);
2652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2654d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
26553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::CallIC(Handle<Code> code,
2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               TypeFeedbackId ast_id) {
26583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ic_total_count_++;
2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All calls must have a predictable size in full-codegen code to ensure that
2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the debugger can patch them correctly.
2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Call(code, RelocInfo::CODE_TARGET, ast_id, al,
2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          NEVER_INLINE_TARGET_ADDRESS);
26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC.
2667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
2668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Expression* callee = expr->expression();
2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallICState::CallType call_type =
2671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD;
2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the target function.
2674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (call_type == CallICState::FUNCTION) {
2675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    { StackValueContext context(this);
2676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitVariableLoad(callee->AsVariableProxy());
2677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrepareForBailout(callee, NO_REGISTERS);
26783e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push undefined as receiver. This is patched in the method prologue if it
2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // is a sloppy mode method.
2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(isolate()->factory()->undefined_value());
2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load the function from the receiver.
2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(callee->IsProperty());
2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!callee->AsProperty()->IsSuperAccess());
2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitNamedPropertyLoad(callee->AsProperty());
2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push the target function under the receiver.
2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(ip, MemOperand(sp, 0));
2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(ip);
2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ str(r0, MemOperand(sp, kPointerSize));
26933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitCall(expr, call_type);
2696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Expression* callee = expr->expression();
2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(callee->IsProperty());
2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Property* prop = callee->AsProperty();
2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(prop->IsSuperAccess());
2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetSourcePosition(prop->position());
2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Literal* key = prop->key()->AsLiteral();
2707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!key->value()->IsSmi());
2708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the function from the receiver.
2709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const Register scratch = r1;
2710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SuperReference* super_ref = prop->obj()->AsSuperReference();
2711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitLoadHomeObject(super_ref);
2712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(r0);
2713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(super_ref->this_var());
2714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(r0);
2715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(scratch, MemOperand(sp, kPointerSize));
2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(scratch);
2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(r0);
2718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(key->value());
2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Stack here:
2721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  - home_object
2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  - this (receiver)
2723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  - home_object <-- LoadFromSuper will pop here and below.
2724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  - this (receiver)
2725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  - key
2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kLoadFromSuper, 3);
2727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Replace home_object with target function.
2729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r0, MemOperand(sp, kPointerSize));
2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Stack here:
2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // - target function
2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // - this (receiver)
2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitCall(expr, CallICState::METHOD);
2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC.
2739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Expression* key) {
27418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the key.
27428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForAccumulatorValue(key);
27438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Expression* callee = expr->expression();
27458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the function from the receiver.
2747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(callee->IsProperty());
2748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
2749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(LoadDescriptor::NameRegister(), r0);
2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitKeyedPropertyLoad(callee->AsProperty());
2751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push the target function under the receiver.
2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(ip, MemOperand(sp, 0));
2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(ip);
2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r0, MemOperand(sp, kPointerSize));
2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitCall(expr, CallICState::METHOD);
27599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
27609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
27619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the arguments.
2764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
2766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { PreservePositionScope scope(masm()->positions_recorder());
27673e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
27683e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
27693e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Record source position of the IC call.
2773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> ic = CallIC::initialize_stub(
2775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate(), arg_count, call_type);
2776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
27773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Don't assign a type feedback id to the IC, since type feedback is provided
2779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // by the vector above.
2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(ic);
2781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RecordJSReturnSite(expr);
27833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore context register.
27843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
27850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->DropAndPlug(1, r0);
2786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
27893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r5: copy of the first argument or undefined if it doesn't exist.
2791e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (arg_count > 0) {
2792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(r5, MemOperand(sp, arg_count * kPointerSize));
2793e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
2794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
2795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2796e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r4: the receiver of the enclosing function.
2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
2799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r3: the receiver of the enclosing function.
28013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int receiver_offset = 2 + info_->scope()->num_parameters();
2802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r3, MemOperand(fp, receiver_offset * kPointerSize));
2803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r2: strict mode.
2805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r2, Operand(Smi::FromInt(strict_mode())));
2806e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r1: the start position of the scope the calls resides in.
28083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r1, Operand(Smi::FromInt(scope()->start_position())));
28093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do the runtime call.
2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(r5);
2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(r4, r3, r2, r1);
2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
2814e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2815e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2816e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2817d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) {
2818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
2819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We want to verify that RecordJSReturnSite gets called on all paths
2820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // through this function.  Avoid early returns.
2821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->return_is_recorded_ = false;
2822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
2823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Call");
2825589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Expression* callee = expr->expression();
2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Call::CallType call_type = expr->GetCallType(isolate());
2827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (call_type == Call::POSSIBLY_EVAL_CALL) {
2829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
2830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // to resolve the function we need to call and the receiver of the
2831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // call.  Then we call the resolved function using the given
2832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // arguments.
2833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    ZoneList<Expression*>* args = expr->arguments();
2834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    int arg_count = args->length();
2835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope pos_scope(masm()->positions_recorder());
2837589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VisitForStackValue(callee);
28383e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
28393e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ push(r2);  // Reserved receiver slot.
2840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28413e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Push the arguments.
28423e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      for (int i = 0; i < arg_count; i++) {
28433e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        VisitForStackValue(args->at(i));
28443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      }
28453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
2846589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Push a copy of the function (found below the arguments) and
2847e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // resolve eval.
2848e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
28491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ push(r1);
28503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitResolvePossiblyDirectEval(arg_count);
28513e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
28523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // The runtime call returns a pair of values in r0 (function) and
28533e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // r1 (receiver). Touch up the stack with the right values.
28543e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
28553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ str(r1, MemOperand(sp, arg_count * kPointerSize));
28563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Record source position for debugger.
2859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetSourcePosition(expr->position());
2860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
28613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
2863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    RecordJSReturnSite(expr);
2864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Restore context register.
2865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
28660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->DropAndPlug(1, r0);
2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (call_type == Call::GLOBAL_CALL) {
2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitCallWithLoadIC(expr);
2869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (call_type == Call::LOOKUP_SLOT_CALL) {
287159151504615d929945dc59db37bf1166937748c6Steve Block    // Call to a lookup slot (dynamically introduced variable).
2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VariableProxy* proxy = callee->AsVariableProxy();
287359151504615d929945dc59db37bf1166937748c6Steve Block    Label slow, done;
287459151504615d929945dc59db37bf1166937748c6Steve Block
2875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope scope(masm()->positions_recorder());
28763e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Generate code for loading from variables potentially shadowed
28773e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // by eval-introduced variables.
2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
28793e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
288059151504615d929945dc59db37bf1166937748c6Steve Block
288159151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
28820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Call the runtime to find the function to call (returned in r0)
288359151504615d929945dc59db37bf1166937748c6Steve Block    // and the object holding it (returned in edx).
2884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!context_register().is(r2));
2885589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ mov(r2, Operand(proxy->name()));
2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(context_register(), r2);
2887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntime(Runtime::kLoadLookupSlot, 2);
288859151504615d929945dc59db37bf1166937748c6Steve Block    __ Push(r0, r1);  // Function, receiver.
288959151504615d929945dc59db37bf1166937748c6Steve Block
289059151504615d929945dc59db37bf1166937748c6Steve Block    // If fast case code has been generated, emit code to push the
289159151504615d929945dc59db37bf1166937748c6Steve Block    // function and receiver and have the slow path jump around this
289259151504615d929945dc59db37bf1166937748c6Steve Block    // code.
289359151504615d929945dc59db37bf1166937748c6Steve Block    if (done.is_linked()) {
289459151504615d929945dc59db37bf1166937748c6Steve Block      Label call;
289559151504615d929945dc59db37bf1166937748c6Steve Block      __ b(&call);
289659151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&done);
289759151504615d929945dc59db37bf1166937748c6Steve Block      // Push function.
289859151504615d929945dc59db37bf1166937748c6Steve Block      __ push(r0);
28993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // The receiver is implicitly the global receiver. Indicate this
29003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // by passing the hole to the call function stub.
2901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
290259151504615d929945dc59db37bf1166937748c6Steve Block      __ push(r1);
290359151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&call);
290459151504615d929945dc59db37bf1166937748c6Steve Block    }
290559151504615d929945dc59db37bf1166937748c6Steve Block
2906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The receiver is either the global receiver or an object found
2907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // by LoadContextSlot.
2908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitCall(expr);
2909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (call_type == Call::PROPERTY_CALL) {
2910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Property* property = callee->AsProperty();
2911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool is_named_call = property->key()->IsPropertyName();
2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // super.x() is handled in EmitCallWithLoadIC.
2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (property->IsSuperAccess() && is_named_call) {
2914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitSuperCallWithLoadIC(expr);
2915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
2916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      {
2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        PreservePositionScope scope(masm()->positions_recorder());
2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->obj());
2919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (is_named_call) {
2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        EmitCallWithLoadIC(expr);
2922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
2923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        EmitKeyedCallWithLoadIC(expr, property->key());
2924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
29263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(call_type == Call::OTHER_CALL);
2928589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Call to an arbitrary expression not handled specially above.
2929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope scope(masm()->positions_recorder());
2930589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VisitForStackValue(callee);
29313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
2933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(r1);
2934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit function call.
2935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitCall(expr);
29363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
2939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // RecordJSReturnSite should have been called.
2940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->return_is_recorded_);
2941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
29423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
29433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
29443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2945d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
2946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
2947d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
2948d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
2949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
295080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
295180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Push constructor on the stack.  If it's not a function it's used as
295280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
295380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ignored.
29540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->expression());
2955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
2957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
2959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
29600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
2961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2962d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2963d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
2964d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
2965d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
2966d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
296780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load function and argument count into r1 and r0.
2968d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(r0, Operand(arg_count));
296980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
2970d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Record call targets in unoptimized code.
2972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_pretenuring_call_new) {
2973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot());
2974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(expr->AllocationSiteFeedbackSlot() ==
2975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           expr->CallNewFeedbackSlot() + 1);
29763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
29773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(r2, FeedbackVector());
2979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));
2980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET);
29823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
29840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2985d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2986d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2987d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
29883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
29893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
2991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
299780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
29980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
29990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
3000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTst(r0);
3003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Split(eq, if_true, if_false, fall_through);
3004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
30103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
301880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
30190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
30200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
3021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ NonNegativeSmiTst(r0);
302480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
3025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
303980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
30400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
30410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
304280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
30431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, if_false);
3044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(ip, Heap::kNullValueRootIndex);
3045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, ip);
3046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, if_true);
3047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
3048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Undetectable objects behave like undefined when tested with typeof.
3049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
3050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ tst(r1, Operand(1 << Map::kIsUndetectable));
3051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, if_false);
3052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset));
30533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
3054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(lt, if_false);
30553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
30563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
305780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(le, if_true, if_false, fall_through);
3058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
30643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
30663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
30670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
30683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
30693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label materialize_true, materialize_false;
30703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_true = NULL;
30713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_false = NULL;
307280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
30730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
30740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
30753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
30761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, if_false);
30773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
30783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
307980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(ge, if_true, if_false, fall_through);
30803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
30810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
30823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
30833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
30843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
30853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
30863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
309480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
30950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
30960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
3097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, if_false);
3099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
3100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
3101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ tst(r1, Operand(1 << Map::kIsUndetectable));
31023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
310380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(ne, if_true, if_false, fall_through);
3104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3109756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
31103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime* expr) {
31113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3113756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
31140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3115756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label materialize_true, materialize_false, skip_lookup;
3117756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_true = NULL;
3118756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_false = NULL;
311980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
31200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
31210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
3122756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AssertNotSmi(r0);
31248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
31258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
31268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldrb(ip, FieldMemOperand(r1, Map::kBitField2Offset));
31278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ tst(ip, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(ne, &skip_lookup);
31298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
31308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Check for fast case object. Generate false result for slow case object.
31318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r2, FieldMemOperand(r0, JSObject::kPropertiesOffset));
31328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
31338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
31348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ cmp(r2, ip);
31358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ b(eq, if_false);
31368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Look for valueOf name in the descriptor array, and indicate false if
3138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // found. Since we omit an enumeration index check, if it is added via a
3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // transition that shares its descriptor array, this is a false positive.
3140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label entry, loop, done;
3141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Skip loop if no descriptors are valid.
3143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ NumberOfOwnDescriptors(r3, r1);
3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(r3, Operand::Zero());
3145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(eq, &done);
3146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadInstanceDescriptors(r1, r4);
3148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r4: descriptor array.
3149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r3: valid entries in the descriptor array.
3150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ip, Operand(DescriptorArray::kDescriptorSize));
3151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mul(r3, r3, ip);
3152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate location of the first key name.
3153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r4, Operand(DescriptorArray::kFirstOffset - kHeapObjectTag));
31548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Calculate the end of the descriptor array.
3155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r2, r4);
3156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r2, r2, Operand(r3, LSL, kPointerSizeLog2));
31578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
31588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Loop through all the keys in the descriptor array. If one of these is the
3159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // string "valueOf" the result is false.
3160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The use of ip to store the valueOf string assumes that it is not otherwise
31618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // used in the loop below.
3162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ip, Operand(isolate()->factory()->value_of_string()));
31638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ jmp(&entry);
31648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ bind(&loop);
31658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r3, MemOperand(r4, 0));
31668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ cmp(r3, ip);
31678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ b(eq, if_false);
3168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r4, Operand(DescriptorArray::kDescriptorSize * kPointerSize));
31698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ bind(&entry);
31708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ cmp(r4, Operand(r2));
31718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ b(ne, &loop);
31728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
3173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
3174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set the bit in the map to indicate that there is no local valueOf field.
3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldrb(r2, FieldMemOperand(r1, Map::kBitField2Offset));
3177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ orr(r2, r2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
3178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ strb(r2, FieldMemOperand(r1, Map::kBitField2Offset));
3179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&skip_lookup);
3181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If a valueOf property is not found on the object check that its
31838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // prototype is the un-modified String prototype. If not result is false.
31848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r2, FieldMemOperand(r1, Map::kPrototypeOffset));
31853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(r2, if_false);
31868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
3187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r3, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
3188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r3, FieldMemOperand(r3, GlobalObject::kNativeContextOffset));
31898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r3, ContextOperand(r3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
31908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ cmp(r2, r3);
31913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Split(eq, if_true, if_false, fall_through);
3193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
31940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3195756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
3196756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3197756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
31983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
31993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
320780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
32080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
32090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
3210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, if_false);
3212589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE);
32133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
321480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
3215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
3221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(0));
3225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label materialize_true, materialize_false;
3227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_true = NULL;
3228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_false = NULL;
3229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* fall_through = NULL;
3230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
3231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         &if_true, &if_false, &fall_through);
3232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK);
3234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
3235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r1, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
3236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(r2, Operand(0x80000000));
3237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(r1, Operand(0x00000000), eq);
3238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Split(eq, if_true, if_false, fall_through);
3241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(if_true, if_false);
3243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
32463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
32473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
325580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
32560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
32570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
3258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, if_false);
3260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
32613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
326280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
3263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
32693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
327780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
32780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
32790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
3280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, if_false);
3282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
32833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
328480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
3285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3290f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
3292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->arguments()->length() == 0);
3293f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
329780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
32980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
32990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
3300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the frame pointer for the calling frame.
3302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Skip the arguments adaptor frame if it exists.
3305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset));
3306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset), eq);
3308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check the marker in the calling frame.
3310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
3311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
33123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
331380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
3314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
33203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
3322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the two objects into registers and perform the comparison.
33240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
33250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
3326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
333080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
33310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
33320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
3333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r1);
3335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, r1);
33363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
333780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
3338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArguments(CallRuntime* expr) {
33443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ArgumentsAccessStub expects the key in edx and the formal
33480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // parameter count in r0.
33490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r1, r0);
33513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
3352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT);
3353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
33540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
3359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->arguments()->length() == 0);
3360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the number of formal parameters.
33623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
3363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the calling frame is an arguments adaptor frame.
3365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
3367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3368f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Arguments adaptor case: Read the arguments length from the
3370f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // adaptor frame.
3371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset), eq);
3372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3376f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
33783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3380f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, null, function, non_function_constructor;
3381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3383f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3384f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, we return null.
33851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, &null);
3386f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3387f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check that the object is a JS object but take special care of JS
3388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // functions to make sure they have 'Function' as their class.
33893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Assume that there are only two callable types, and one of them is at
33903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // either end of the type range for JS object types. Saves extra comparisons.
33913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
33923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CompareObjectType(r0, r0, r1, FIRST_SPEC_OBJECT_TYPE);
33933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Map is now in r0.
3394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(lt, &null);
33953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
33963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                FIRST_SPEC_OBJECT_TYPE + 1);
33973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(eq, &function);
33983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r1, Operand(LAST_SPEC_OBJECT_TYPE));
34003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
34013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                LAST_SPEC_OBJECT_TYPE - 1);
34023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(eq, &function);
34033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Assume that there is no larger type.
34043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
34053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the constructor in the map is a JS function.
3407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, Map::kConstructorOffset));
3408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
3409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &non_function_constructor);
3410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r0 now contains the constructor function. Grab the
3412f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // instance class name from there.
3413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
3414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset));
3415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(&done);
3416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Functions have class 'Function'.
3418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&function);
3419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(r0, Heap::kFunction_stringRootIndex);
3420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
3421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Objects with a non-function constructor have class 'Object'.
3423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&non_function_constructor);
3424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(r0, Heap::kObject_stringRootIndex);
3425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
3426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-JS objects have class null.
3428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&null);
3429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(r0, Heap::kNullValueRootIndex);
3430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // All done.
3432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
3433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
34340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
34383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSubString(CallRuntime* expr) {
3439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
3440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SubStringStub stub(isolate());
34413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 3);
34430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
34440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
34450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
3446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
34470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
34513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
3452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
3453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegExpExecStub stub(isolate());
34543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 4);
34560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
34570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
34580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
34590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(3));
3460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
34610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
34653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
34663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
34680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));  // Load the object.
3469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
3471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi return the object.
34721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, &done);
3473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the object.
3474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE);
3475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset), eq);
3476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
34780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
34823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitDateField(CallRuntime* expr) {
34833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
3485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NE(NULL, args->at(1)->AsLiteral());
3486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value()));
34873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitForAccumulatorValue(args->at(0));  // Load the object.
34893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label runtime, done, not_date_object;
34913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = r0;
34923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = r0;
34933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch0 = r9;
34943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch1 = r1;
34953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(object, &not_date_object);
34973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareObjectType(object, scratch1, scratch1, JS_DATE_TYPE);
3498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(ne, &not_date_object);
34993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (index->value() == 0) {
35013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
3502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done);
35033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
35043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (index->value() < JSDate::kFirstUncachedField) {
35053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
35063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(scratch1, Operand(stamp));
35073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(scratch1, MemOperand(scratch1));
35083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(scratch0, FieldMemOperand(object, JSDate::kCacheStampOffset));
35093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(scratch1, scratch0);
35103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ b(ne, &runtime);
35113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset +
35123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             kPointerSize * index->value()));
35133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&done);
35143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
35153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&runtime);
35163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ PrepareCallCFunction(2, scratch1);
35173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r1, Operand(index));
35183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
3519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done);
35203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&not_date_object);
3523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kThrowNotDateError, 0);
3524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
35253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->Plug(r0);
35263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
35273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
3530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(3, args->length());
3532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register string = r0;
3534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register index = r1;
3535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register value = r2;
3536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(args->at(0));        // index
3538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(args->at(1));        // value
3539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(2));  // string
3540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(index, value);
3541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
3543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiTst(value);
3544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(eq, kNonSmiValue);
3545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiTst(index);
3546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(eq, kNonSmiIndex);
3547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiUntag(index, index);
3548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
3549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
3550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiTag(index, index);
3551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiUntag(value, value);
3554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(ip,
3555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         string,
3556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize));
3558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(string);
3559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
3563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(3, args->length());
3565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register string = r0;
3567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register index = r1;
3568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register value = r2;
3569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(args->at(0));        // index
3571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(args->at(1));        // value
3572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(2));  // string
3573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(index, value);
3574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
3576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiTst(value);
3577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(eq, kNonSmiValue);
3578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiTst(index);
3579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(eq, kNonSmiIndex);
3580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiUntag(index, index);
3581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
3582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
3583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiTag(index, index);
3584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiUntag(value, value);
3587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(ip,
3588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         string,
3589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
3590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
3591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ strh(value, MemOperand(ip, index));
3592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(string);
3593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
35973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
3598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the runtime function.
35993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
36010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
36020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
3603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MathPowStub stub(isolate(), MathPowStub::ON_STACK);
3604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallStub(&stub);
36050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
36093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
36103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
36120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));  // Load the object.
36130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));  // Load the value.
3614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r1);  // r0 = value. r1 = object.
3615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
3617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, return the value.
36181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r1, &done);
3619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the value.
3621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE);
3622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &done);
3623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Store the value.
3625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
3626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the write barrier.  Save the value as it will be
3627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // overwritten by the write barrier code and is needed afterward.
36283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r2, r0);
36293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWriteField(
36303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      r1, JSValue::kValueOffset, r2, r3, kLRHasBeenSaved, kDontSaveFPRegs);
3631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
36330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
36373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
36383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(args->length(), 1);
3640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the argument into r0 and call the stub.
3641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(0));
3642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NumberToStringStub stub(isolate());
3644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
36450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
36493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
36503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
36520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
36547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
36557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharFromCodeGenerator generator(r0, r1);
36567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
36577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
3658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
36597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
36607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
3661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
36630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r1);
3664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
36673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
36683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
36700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
36710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
36727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
36737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = r1;
36747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = r0;
36757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = r3;
36767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
36777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
36787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
36797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
36807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
36817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
36827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharCodeAtGenerator generator(object,
36837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      index,
36847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      result,
36857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
36867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
36877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &index_out_of_range,
36887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      STRING_INDEX_IS_NUMBER);
36897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
36907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
36917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
36927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
36937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
36947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // NaN.
36957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kNanValueRootIndex);
36967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
36977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
36987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
36997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Load the undefined value into the result register, which will
37007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // trigger conversion.
37017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
37027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
37037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
37047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
37057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
37067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
37077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
37080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
37097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
37107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
37117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
37123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
37133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
37150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
37160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
37177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
37187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = r1;
37197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = r0;
37203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = r3;
37217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = r0;
37227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
37237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
37247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
37257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
37267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
37277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
37287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharAtGenerator generator(object,
37297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  index,
37303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  scratch,
37317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  result,
37327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
37337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
37347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &index_out_of_range,
37357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  STRING_INDEX_IS_NUMBER);
37367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
37377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
37387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
37397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
37407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
37417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the empty string.
3742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(result, Heap::kempty_stringRootIndex);
37437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
37447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
37457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
37467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move smi zero into the result register, which will trigger
37477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // conversion.
37487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(result, Operand(Smi::FromInt(0)));
37497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
37507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
37517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
37527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
37537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
37547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
37550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
3756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
37587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
37593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(2, args->length());
37620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
3763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(1));
3764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(r1);
3766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED);
3767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
37680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
37723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
37733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(2, args->length());
37750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
37760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
3777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StringCompareStub stub(isolate());
3779e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CallStub(&stub);
37800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
37843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
37853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() >= 2);
3787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int arg_count = args->length() - 2;  // 2 ~ receiver and function.
3789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < arg_count + 1; i++) {
3790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VisitForStackValue(args->at(i));
3791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  VisitForAccumulatorValue(args->last());  // Function.
3793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label runtime, done;
3795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for non-function argument (including proxy).
3796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(r0, &runtime);
3797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
3798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(ne, &runtime);
37993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // InvokeFunction requires the function in r1. Move it in there.
3801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(r1, result_register());
3802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ParameterCount count(arg_count);
3803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ InvokeFunction(r1, count, CALL_FUNCTION, NullCallWrapper());
3804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
38053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&done);
38063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&runtime);
38083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(r0);
38093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallRuntime(Runtime::kCall, args->length());
38103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
38113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
38163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegExpConstructResultStub stub(isolate());
38183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 3);
38200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
38210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
3822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(2));
3823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(r1);
3824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(r2);
3825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CallStub(&stub);
38260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
38303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
38313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(2, args->length());
3833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NE(NULL, args->at(0)->AsLiteral());
3834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value();
3835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<FixedArray> jsfunction_result_caches(
3837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate()->native_context()->jsfunction_result_caches());
3838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (jsfunction_result_caches->length() <= cache_id) {
3839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Abort(kAttemptToUseUndefinedCache);
3840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
38410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
3842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
38450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
3846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register key = r0;
3848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register cache = r1;
3849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(cache, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
3850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(cache, FieldMemOperand(cache, GlobalObject::kNativeContextOffset));
385159151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
3852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(cache,
3853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
3854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, not_found;
3857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset));
3858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r2 now holds finger offset as a smi.
3859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r3 now points to the start of fixed array elements.
3861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r2, MemOperand::PointerAddressFromSmiKey(r3, r2, PreIndex));
3862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Note side effect of PreIndex: r3 now points to the key of the pair.
3863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(key, r2);
3864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &not_found);
3865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, MemOperand(r3, kPointerSize));
3867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(&done);
3868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&not_found);
3870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call runtime to perform the lookup.
3871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(cache, key);
3872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetFromCache, 2);
3873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
38750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
38793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
38803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
38810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
388280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
388380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
388480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
388580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
388680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
38870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
38880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
388980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
389080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
389180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ tst(r0, Operand(String::kContainsCachedArrayIndexMask));
38923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Split(eq, if_true, if_false, fall_through);
389480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
38950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
389680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
389780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
389880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
38993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
39003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
39020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AssertString(r0);
3905e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
390680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
390780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ IndexFromHash(r0, r0);
3908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
39090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
391080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
391180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
391280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) {
3914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label bailout, done, one_char_separator, long_separator, non_trivial_array,
3915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      not_size_one_array, loop, empty_separator_loop, one_char_separator_loop,
3916e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      one_char_separator_loop_entry, long_separator_loop;
39173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
3919e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  VisitForStackValue(args->at(1));
3920e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  VisitForAccumulatorValue(args->at(0));
3921e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3922e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // All aliases of the same register have disjoint lifetimes.
3923e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register array = r0;
3924e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register elements = no_reg;  // Will be r0.
3925e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register result = no_reg;  // Will be r0.
3926e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register separator = r1;
3927e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register array_length = r2;
3928e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register result_pos = no_reg;  // Will be r2
3929e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register string_length = r3;
3930e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register string = r4;
3931e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register element = r5;
3932e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register elements_end = r6;
3933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = r9;
3934e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Separator operand is on the stack.
3936e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ pop(separator);
3937e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3938e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check that the array is a JSArray.
3939e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ JumpIfSmi(array, &bailout);
3940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CompareObjectType(array, scratch, array_length, JS_ARRAY_TYPE);
3941e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(ne, &bailout);
3942e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check that the array has fast elements.
3944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CheckFastElements(scratch, array_length, &bailout);
3945e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3946e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // If the array has length zero, return the empty string.
3947e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
3948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ SmiUntag(array_length, SetCC);
3949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(ne, &non_trivial_array);
3950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(r0, Heap::kempty_stringRootIndex);
3951e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(&done);
3952e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3953e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&non_trivial_array);
3954e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3955e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Get the FixedArray containing array's elements.
3956e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  elements = array;
3957e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(elements, FieldMemOperand(array, JSArray::kElementsOffset));
3958e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  array = no_reg;  // End of array's live range.
3959e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that all array elements are sequential one-byte strings, and
3961e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // accumulate the sum of their lengths, as a smi-encoded value.
3962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(string_length, Operand::Zero());
3963e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(element,
3964e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3965e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2));
3966e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Loop condition: while (element < elements_end).
3967e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Live values in registers:
3968e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   elements: Fixed array of strings.
3969e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   array_length: Length of the fixed array of strings (not smi)
3970e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   separator: Separator string
3971e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   string_length: Accumulated sum of string lengths (smi).
3972e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   element: Current array element.
3973e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   elements_end: Array end.
3974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (generate_debug_code_) {
3975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(array_length, Operand::Zero());
3976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Assert(gt, kNoEmptyArraysHereInEmitFastOneByteArrayJoin);
3977e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
3978e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&loop);
3979e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
3980e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ JumpIfSmi(string, &bailout);
3981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset));
3982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
3983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch, scratch, &bailout);
3984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(scratch, FieldMemOperand(string, SeqOneByteString::kLengthOffset));
3985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(string_length, string_length, Operand(scratch), SetCC);
3986e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(vs, &bailout);
3987e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(element, elements_end);
3988e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(lt, &loop);
3989e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3990e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // If array_length is 1, return elements[0], a string.
3991e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(array_length, Operand(1));
3992e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(ne, &not_size_one_array);
3993e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize));
3994e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(&done);
3995e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3996e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&not_size_one_array);
3997e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3998e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Live values in registers:
3999e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   separator: Separator string
4000e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   array_length: Length of the array.
4001e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   string_length: Sum of string lengths (smi).
4002e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   elements: FixedArray of strings.
4003e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that the separator is a flat one-byte string.
4005e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ JumpIfSmi(separator, &bailout);
4006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(scratch, FieldMemOperand(separator, HeapObject::kMapOffset));
4007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
4008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch, scratch, &bailout);
4009e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4010e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Add (separator length times array_length) - separator length to the
4011e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // string_length to get the length of the result string. array_length is not
4012e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // smi but the other values are, so the result is a smi
4013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
4014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub(string_length, string_length, Operand(scratch));
4015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ smull(scratch, ip, array_length, scratch);
4016e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are
4017e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // zero.
4018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(ip, Operand::Zero());
4019e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(ne, &bailout);
4020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ tst(scratch, Operand(0x80000000));
4021e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(ne, &bailout);
4022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(string_length, string_length, Operand(scratch), SetCC);
4023e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(vs, &bailout);
4024e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ SmiUntag(string_length);
4025e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4026e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Get first element in the array to free up the elements register to be used
4027e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // for the result.
4028e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(element,
4029e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
4030e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  result = elements;  // End of live range for elements.
4031e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  elements = no_reg;
4032e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Live values in registers:
4033e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   element: First array element
4034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   separator: Separator string
4035e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   string_length: Length of result string (not smi)
4036e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   array_length: Length of the array.
4037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AllocateOneByteString(result, string_length, scratch,
4038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           string,        // used as scratch
4039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           elements_end,  // used as scratch
4040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           &bailout);
4041e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Prepare for looping. Set up elements_end to end of the array. Set
4042e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // result_pos to the position of the result where to write the first
4043e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // character.
4044e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2));
4045e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  result_pos = array_length;  // End of live range for array_length.
4046e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  array_length = no_reg;
4047e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(result_pos,
4048e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         result,
4049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
4050e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4051e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check the length of the separator.
4052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
4053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(scratch, Operand(Smi::FromInt(1)));
4054e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(eq, &one_char_separator);
4055e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(gt, &long_separator);
4056e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Empty separator case
4058e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&empty_separator_loop);
4059e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Live values in registers:
4060e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   result_pos: the position to which we are currently copying characters.
4061e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   element: Current array element.
4062e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   elements_end: Array end.
4063e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4064e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Copy next array element to the result.
4065e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
4066e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
4067e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ SmiUntag(string_length);
4068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(string,
4069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         string,
4070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
4071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CopyBytes(string, result_pos, string_length, scratch);
4072e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(element, elements_end);
4073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(lt, &empty_separator_loop);  // End while (element < elements_end).
4074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(result.is(r0));
4075e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(&done);
4076e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4077e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // One-character separator case
4078e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&one_char_separator);
4079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Replace separator with its one-byte character value.
4080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldrb(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize));
4081e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Jump into the loop after the code that copies the separator, so the first
4082e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // element is not preceded by a separator
4083e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ jmp(&one_char_separator_loop_entry);
4084e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4085e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&one_char_separator_loop);
4086e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Live values in registers:
4087e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   result_pos: the position to which we are currently copying characters.
4088e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   element: Current array element.
4089e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   elements_end: Array end.
4090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //   separator: Single separator one-byte char (in lower byte).
4091e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4092e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Copy the separator character to the result.
4093e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ strb(separator, MemOperand(result_pos, 1, PostIndex));
4094e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Copy next array element to the result.
4096e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&one_char_separator_loop_entry);
4097e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
4098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
4099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ SmiUntag(string_length);
4100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(string,
4101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         string,
4102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
4103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CopyBytes(string, result_pos, string_length, scratch);
4104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(element, elements_end);
4105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(lt, &one_char_separator_loop);  // End while (element < elements_end).
4106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(result.is(r0));
4107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(&done);
4108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Long separator case (separator is more than one character). Entry is at the
4110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // label long_separator below.
4111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&long_separator_loop);
4112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Live values in registers:
4113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   result_pos: the position to which we are currently copying characters.
4114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   element: Current array element.
4115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   elements_end: Array end.
4116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   separator: Separator string.
4117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Copy the separator to the result.
4119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string_length, FieldMemOperand(separator, String::kLengthOffset));
4120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ SmiUntag(string_length);
4121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(string,
4122e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         separator,
4123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
4124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CopyBytes(string, result_pos, string_length, scratch);
4125e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&long_separator);
4127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
4128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
4129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ SmiUntag(string_length);
4130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(string,
4131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         string,
4132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
4133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CopyBytes(string, result_pos, string_length, scratch);
4134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(element, elements_end);
4135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(lt, &long_separator_loop);  // End while (element < elements_end).
4136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(result.is(r0));
4137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(&done);
4138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&bailout);
41408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
4141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&done);
41428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  context()->Plug(r0);
41438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
41448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
41458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
4147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->arguments()->length() == 0);
4148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference debug_is_active =
4149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::debug_is_active_address(isolate());
4150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ip, Operand(debug_is_active));
4151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldrb(r0, MemOperand(ip));
4152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTag(r0);
4153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(r0);
4154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4157d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
4158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expr->function() != NULL &&
4159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      expr->function()->intrinsic_type == Runtime::INLINE) {
4160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ InlineRuntimeCall");
4161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitInlineRuntimeCall(expr);
4162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
4163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
4164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
41653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ CallRuntime");
41663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* args = expr->arguments();
4167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int arg_count = args->length();
41683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
4170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push the builtins object as the receiver.
4171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register receiver = LoadDescriptor::ReceiverRegister();
4172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(receiver, GlobalObjectOperand());
4173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(receiver, FieldMemOperand(receiver, GlobalObject::kBuiltinsOffset));
4174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(receiver);
4175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load the function from the receiver.
4177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(LoadDescriptor::NameRegister(), Operand(expr->name()));
4178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_vector_ics) {
4179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(VectorLoadICDescriptor::SlotRegister(),
4180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             Operand(Smi::FromInt(expr->CallRuntimeFeedbackSlot())));
4181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallLoadIC(NOT_CONTEXTUAL);
4182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
4184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
41853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push the target function under the receiver.
4187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(ip, MemOperand(sp, 0));
4188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(ip);
4189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ str(r0, MemOperand(sp, kPointerSize));
4190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push the arguments ("left-to-right").
4192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int arg_count = args->length();
4193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < arg_count; i++) {
4194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForStackValue(args->at(i));
4195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Record source position of the IC call.
4198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SetSourcePosition(expr->position());
4199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
4200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
4201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallStub(&stub);
4202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Restore context register.
4204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
4205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context()->DropAndPlug(1, r0);
4207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
4208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push the arguments ("left-to-right").
4209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < arg_count; i++) {
4210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForStackValue(args->at(i));
4211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call the C runtime function.
4214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(expr->function(), arg_count);
4215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context()->Plug(r0);
4216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
4217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
4218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4220d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
4221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
4222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Token::DELETE: {
4223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
4224589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Property* property = expr->expression()->AsProperty();
4225589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VariableProxy* proxy = expr->expression()->AsVariableProxy();
4226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4227589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (property != NULL) {
4228589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        VisitForStackValue(property->obj());
4229589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        VisitForStackValue(property->key());
4230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov(r1, Operand(Smi::FromInt(strict_mode())));
423169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ push(r1);
423269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
423369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        context()->Plug(r0);
4234589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else if (proxy != NULL) {
4235589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Variable* var = proxy->var();
4236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Delete of an unqualified identifier is disallowed in strict mode
4237589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // but "delete this" is allowed.
4238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(strict_mode() == SLOPPY || var->is_this());
4239589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (var->IsUnallocated()) {
4240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ ldr(r2, GlobalObjectOperand());
4241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ mov(r1, Operand(var->name()));
4242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ mov(r0, Operand(Smi::FromInt(SLOPPY)));
4243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ Push(r2, r1, r0);
4244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
4245e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(r0);
4246589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        } else if (var->IsStackAllocated() || var->IsContextSlot()) {
4247e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Result of deleting non-global, non-dynamic variables is false.
4248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // The subexpression does not have side effects.
4249589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          context()->Plug(var->is_this());
4250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else {
4251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Non-global variable.  Call the runtime to try to delete from the
4252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // context where the variable was introduced.
4253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          DCHECK(!context_register().is(r2));
4254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ mov(r2, Operand(var->name()));
4255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Push(context_register(), r2);
4256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ CallRuntime(Runtime::kDeleteLookupSlot, 2);
4257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(r0);
4258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
42591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
4260e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Result of deleting non-property, non-variable reference is true.
4261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // The subexpression may have side effects.
4262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
4263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        context()->Plug(true);
4264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
4265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
4266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
4267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
4269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
4270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
42710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(Heap::kUndefinedValueRootIndex);
4272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
4276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
4277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (context()->IsEffect()) {
4278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Unary NOT has no side effects so it's only necessary to visit the
4279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // subexpression.  Match the optimizing compiler by not branching.
4280e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
42813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (context()->IsTest()) {
42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        const TestContext* test = TestContext::cast(context());
42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The labels are swapped for the recursive call.
42843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VisitForControl(expr->expression(),
42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->false_label(),
42863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->true_label(),
42873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->fall_through());
42883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        context()->Plug(test->true_label(), test->false_label());
4289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
42903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We handle value contexts explicitly rather than simply visiting
42913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // for control and plugging the control flow into the context,
42923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // because we need to prepare a pair of extra administrative AST ids
42933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // for the optimizing compiler.
4294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue());
42953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label materialize_true, materialize_false, done;
42963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VisitForControl(expr->expression(),
42973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_false,
42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_true,
42993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_true);
43003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&materialize_true);
43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(r0, Heap::kTrueValueRootIndex);
43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (context()->IsStackValue()) __ push(r0);
43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&done);
43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&materialize_false);
43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(r0, Heap::kFalseValueRootIndex);
43083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (context()->IsStackValue()) __ push(r0);
43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&done);
4310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
4311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
4315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
43160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      { StackValueContext context(this);
43170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForTypeofValue(expr->expression());
43180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
4319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallRuntime(Runtime::kTypeof, 1);
43200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(r0);
4321d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
43223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
4323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4324d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
4325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
43263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
4327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
4328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4330d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
4331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->expression()->IsValidReferenceExpression());
4332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CountOperation");
433480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
433580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
4336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Expression can only be a property, a global or a (parameter or local)
43373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot.
4338e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
4339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LhsKind assign_type = VARIABLE;
4340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
4341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In case of a property we use the uninitialized expression context
4342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // of the key to detect a named property.
4343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (prop != NULL) {
4344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    assign_type =
4345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
4346d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
4347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
4349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
4350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
43510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
43523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    EmitVariableLoad(expr->expression()->AsVariableProxy());
43533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
4354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
43550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (expr->is_postfix() && !context()->IsEffect()) {
4356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(ip, Operand(Smi::FromInt(0)));
4357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ push(ip);
4358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
4359e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (assign_type == NAMED_PROPERTY) {
4360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Put the object both on the stack and in the register.
4361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForStackValue(prop->obj());
4362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
4363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitNamedPropertyLoad(prop);
4364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
43653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForStackValue(prop->obj());
4366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForStackValue(prop->key());
4367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldr(LoadDescriptor::ReceiverRegister(),
4368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(sp, 1 * kPointerSize));
4369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0));
4370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitKeyedPropertyLoad(prop);
4371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
4372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
4373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We need a second deoptimization point after loading the value
4375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // in case evaluating the property load my have a side effect.
43768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (assign_type == VARIABLE) {
43778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    PrepareForBailout(expr->expression(), TOS_REG);
43788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
4379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrepareForBailoutForId(prop->LoadId(), TOS_REG);
43808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
4381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Inline smi case if we are in a loop.
4383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label stub_call, done;
4384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpPatchSite patch_site(masm_);
4385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int count_value = expr->op() == Token::INC ? 1 : -1;
4387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (ShouldInlineSmiCase(expr->op())) {
4388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label slow;
4389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patch_site.EmitJumpIfNotSmi(r0, &slow);
4390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Save result for postfix expressions.
4392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (expr->is_postfix()) {
4393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!context()->IsEffect()) {
4394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Save the result on the stack. If we have a named or keyed property
4395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // we store the result under the receiver that is currently on top
4396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // of the stack.
4397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        switch (assign_type) {
4398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          case VARIABLE:
4399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ push(r0);
4400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
4401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          case NAMED_PROPERTY:
4402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ str(r0, MemOperand(sp, kPointerSize));
4403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
4404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          case KEYED_PROPERTY:
4405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ str(r0, MemOperand(sp, 2 * kPointerSize));
4406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
4407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
4408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
4409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC);
4412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(vc, &done);
4413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Call stub. Undo operation first.
4414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(r0, r0, Operand(Smi::FromInt(count_value)));
4415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&stub_call);
4416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&slow);
4417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ToNumberStub convert_stub(isolate());
44191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ CallStub(&convert_stub);
4420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
4422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
44230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (!context()->IsEffect()) {
44240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Save the result on the stack. If we have a named or keyed property
44250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // we store the result under the receiver that is currently on top
44260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // of the stack.
44270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
44280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
44290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ push(r0);
44300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
44310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
44320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ str(r0, MemOperand(sp, kPointerSize));
44330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
44340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
44350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ str(r0, MemOperand(sp, 2 * kPointerSize));
44360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
44370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
4438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
4439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
4440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4441d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
4442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&stub_call);
4443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r1, r0);
4444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r0, Operand(Smi::FromInt(count_value)));
4445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Record position before stub call.
4447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
4448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code =
4450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CodeFactory::BinaryOpIC(isolate(), Token::ADD, NO_OVERWRITE).code();
4451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(code, expr->CountBinOpFeedbackId());
44523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
4453d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
4454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in r0.
4456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
4457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case VARIABLE:
4458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
44590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        { EffectContext context(this);
44600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
44610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                 Token::ASSIGN);
4462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          context.Plug(r0);
44640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        }
44650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        // For all contexts except EffectConstant We have the result on
4466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
44670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
44680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
4469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
4470e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
4471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
44720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                               Token::ASSIGN);
4473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        context()->Plug(r0);
4475e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
4476d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
4478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(StoreDescriptor::NameRegister(),
4479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             Operand(prop->key()->AsLiteral()->value()));
4480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pop(StoreDescriptor::ReceiverRegister());
4481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallStoreIC(expr->CountStoreFeedbackId());
4482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
44840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
44850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
4486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
4487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
44880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(r0);
4489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
4490d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
4493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(StoreDescriptor::ReceiverRegister(),
4494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             StoreDescriptor::NameRegister());
4495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Code> ic =
4496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code();
4497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallIC(ic, expr->CountStoreFeedbackId());
4498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
45000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
45010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
4502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
4503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
45040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(r0);
4505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
4506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
45083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
45093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
45103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
45113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
45120d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
4513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!context()->IsEffect());
4514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!context()->IsTest());
451580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  VariableProxy* proxy = expr->AsVariableProxy();
4516589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (proxy != NULL && proxy->var()->IsUnallocated()) {
4517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment cmnt(masm_, "[ Global variable");
4518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
4519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(LoadDescriptor::NameRegister(), Operand(proxy->name()));
4520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_vector_ics) {
4521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(VectorLoadICDescriptor::SlotRegister(),
4522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             Operand(Smi::FromInt(proxy->VariableFeedbackSlot())));
4523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
452480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Use a regular load, not a contextual load, to avoid a reference
452580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // error.
4526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallLoadIC(NOT_CONTEXTUAL);
4527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailout(expr, TOS_REG);
45280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
4529589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
4530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment cmnt(masm_, "[ Lookup slot");
453159151504615d929945dc59db37bf1166937748c6Steve Block    Label done, slow;
453259151504615d929945dc59db37bf1166937748c6Steve Block
453359151504615d929945dc59db37bf1166937748c6Steve Block    // Generate code for loading from variables potentially shadowed
453459151504615d929945dc59db37bf1166937748c6Steve Block    // by eval-introduced variables.
4535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done);
453659151504615d929945dc59db37bf1166937748c6Steve Block
453759151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
453880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(r0, Operand(proxy->name()));
453980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ Push(cp, r0);
4540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
4541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailout(expr, TOS_REG);
454259151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&done);
454359151504615d929945dc59db37bf1166937748c6Steve Block
45440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
454580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
454680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // This expression cannot throw a reference error at the top level.
45473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitInDuplicateContext(expr);
4548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
4549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
4550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
45513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
45523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
45533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Expression* sub_expr,
45543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Handle<String> check) {
45553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label materialize_true, materialize_false;
45563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* if_true = NULL;
45573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* if_false = NULL;
45583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* fall_through = NULL;
45593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
45603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         &if_true, &if_false, &fall_through);
45613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  { AccumulatorValueContext context(this);
45633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForTypeofValue(sub_expr);
45640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
45653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate()->factory();
4568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (String::Equals(check, factory->number_string())) {
4569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(r0, if_true);
457080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
457180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
457280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r0, ip);
457380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
4574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->string_string())) {
4575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(r0, if_false);
457680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
4577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE);
4578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ b(ge, if_false);
457980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
4580e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ tst(r1, Operand(1 << Map::kIsUndetectable));
4581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(eq, if_true, if_false, fall_through);
4582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->symbol_string())) {
4583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(r0, if_false);
4584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareObjectType(r0, r0, r1, SYMBOL_TYPE);
4585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Split(eq, if_true, if_false, fall_through);
4586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->boolean_string())) {
4587e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CompareRoot(r0, Heap::kTrueValueRootIndex);
4588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(eq, if_true);
4589e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CompareRoot(r0, Heap::kFalseValueRootIndex);
459080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
4591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->undefined_string())) {
4592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
4593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(eq, if_true);
4594e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(r0, if_false);
459580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => true.
459680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
459780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
4598e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ tst(r1, Operand(1 << Map::kIsUndetectable));
4599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(ne, if_true, if_false, fall_through);
4600e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->function_string())) {
4602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(r0, if_false);
46033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
46043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareObjectType(r0, r0, r1, JS_FUNCTION_TYPE);
46053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(eq, if_true);
46063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(r1, Operand(JS_FUNCTION_PROXY_TYPE));
46073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Split(eq, if_true, if_false, fall_through);
4608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->object_string())) {
4609e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(r0, if_false);
4610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(r0, Heap::kNullValueRootIndex);
4611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(eq, if_true);
461280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for JS objects => true.
46133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ CompareObjectType(r0, r0, r1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
46143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ b(lt, if_false);
46153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ CompareInstanceType(r0, r1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
46163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ b(gt, if_false);
4617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Check for undetectable objects => false.
4618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
4619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ tst(r1, Operand(1 << Map::kIsUndetectable));
4620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(eq, if_true, if_false, fall_through);
462180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
462280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (if_false != fall_through) __ jmp(if_false);
4623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
46243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->Plug(if_true, if_false);
4625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
4626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
463080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
4631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
46323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First we try a fast inlined version of the compare when one of
46333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the operands is a literal.
46343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (TryLiteralCompare(expr)) return;
46353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
4637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
4638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
4639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
4640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
464180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
46420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
46430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
464480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
46453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Token::Value op = expr->op();
46460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->left());
464780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
4648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
46490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
4650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
46513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
4652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ LoadRoot(ip, Heap::kTrueValueRootIndex);
4653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ cmp(r0, ip);
465480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(eq, if_true, if_false, fall_through);
4655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
46580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
4659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      InstanceofStub stub(isolate(), InstanceofStub::kNoFlags);
4660d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
46613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
466280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // The stub returns 0 for true.
4663d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ tst(r0, r0);
466480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(eq, if_true, if_false, fall_through);
4665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4666d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
46690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->right());
4670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Condition cond = CompareIC::ComputeCondition(op);
46713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(r1);
4672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
46730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      bool inline_smi_code = ShouldInlineSmiCase(op);
46741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      JumpPatchSite patch_site(masm_);
46750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (inline_smi_code) {
467680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Label slow_case;
467780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ orr(r2, r0, Operand(r1));
46781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        patch_site.EmitJumpIfNotSmi(r2, &slow_case);
467980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ cmp(r1, r0);
46801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Split(cond, if_true, if_false, NULL);
468180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&slow_case);
468280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
46831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
46841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Record position and call the compare IC.
46851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      SetSourcePosition(expr->position());
4686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
4687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallIC(ic, expr->CompareOperationFeedbackId());
46883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      patch_site.EmitPatchInfo();
46893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmp(r0, Operand::Zero());
46911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Split(cond, if_true, if_false, fall_through);
46923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
46933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
46943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
4696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
46970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
4698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
46993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
47013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
47023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              Expression* sub_expr,
47033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              NilValue nil) {
470480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
470580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
470680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
470780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
47080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
47090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
471080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
47113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitForAccumulatorValue(sub_expr);
47123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
47133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expr->op() == Token::EQ_STRICT) {
4714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Heap::RootListIndex nil_value = nil == kNullValue ?
4715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Heap::kNullValueRootIndex :
4716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Heap::kUndefinedValueRootIndex;
4717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(r1, nil_value);
471880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r0, r1);
471980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
4720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
4722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallIC(ic, expr->CompareOperationFeedbackId());
4723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(r0, Operand(0));
4724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Split(ne, if_true, if_false, fall_through);
472580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
47260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
472780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
472880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
472980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
4730d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
47320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
4733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
47360d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() {
47370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return r0;
47380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
47410d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() {
47420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return cp;
47430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
47440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
47450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4746d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
4748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ str(value, MemOperand(fp, frame_offset));
4749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
47503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4752d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
475359151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(dst, ContextOperand(cp, context_index));
47543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
47553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
47573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
47583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Scope* declaration_scope = scope()->DeclarationScope();
4759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (declaration_scope->is_global_scope() ||
4760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      declaration_scope->is_module_scope()) {
4761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Contexts nested in the native context have a canonical empty function
47623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // as their closure, not the anonymous closure containing the global
47633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // code.  Pass a smi sentinel and let the runtime look up the empty
47643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // function.
47653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ mov(ip, Operand(Smi::FromInt(0)));
47663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else if (declaration_scope->is_eval_scope()) {
47673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Contexts created by a call to eval have the same closure as the
47683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // context calling eval, not the anonymous closure containing the eval
47693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // code.  Fetch it from the context.
47703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ ldr(ip, ContextOperand(cp, Context::CLOSURE_INDEX));
47713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
4772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(declaration_scope->is_function_scope());
47733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ ldr(ip, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
47743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
47753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ push(ip);
47763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
47773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4779e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ----------------------------------------------------------------------------
4780e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support.
4781e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4782d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() {
4783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result_register().is(r1));
4784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store result register while executing finally block.
4785e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
4786e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Cook return address in link register to stack (smi encoded Code* delta)
4787e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ sub(r1, lr, Operand(masm_->CodeObject()));
4788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTag(r1);
4789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Store result register while executing finally block.
4791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(r1);
4792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Store pending message while executing finally block.
4794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference pending_message_obj =
4795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_pending_message_obj(isolate());
4796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ip, Operand(pending_message_obj));
4797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r1, MemOperand(ip));
4798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(r1);
4799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference has_pending_message =
4801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_has_pending_message(isolate());
4802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ip, Operand(has_pending_message));
4803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(sizeof(bool) == 1);   // NOLINT(runtime/sizeof)
4804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldrb(r1, MemOperand(ip));
4805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTag(r1);
4806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(r1);
4807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference pending_message_script =
4809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_pending_message_script(isolate());
4810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ip, Operand(pending_message_script));
4811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r1, MemOperand(ip));
4812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(r1);
4813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4814e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4816d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() {
4817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result_register().is(r1));
4818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore pending message from stack.
4819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(r1);
4820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference pending_message_script =
4821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_pending_message_script(isolate());
4822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ip, Operand(pending_message_script));
4823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r1, MemOperand(ip));
4824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(r1);
4826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiUntag(r1);
4827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference has_pending_message =
4828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_has_pending_message(isolate());
4829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ip, Operand(has_pending_message));
4830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(sizeof(bool) == 1);   // NOLINT(runtime/sizeof)
4831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ strb(r1, MemOperand(ip));
4832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(r1);
4834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference pending_message_obj =
4835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_pending_message_obj(isolate());
4836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ip, Operand(pending_message_obj));
4837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r1, MemOperand(ip));
4838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4839e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Restore result register from stack.
4840e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(r1);
4841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Uncook return address and return.
4843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(result_register());
4844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiUntag(r1);
4845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(pc, r1, Operand(masm_->CodeObject()));
4846e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4847e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef __
4850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
485169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#define __ ACCESS_MASM(masm())
485269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
485369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochFullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
485469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int* stack_depth,
485569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int* context_length) {
485669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // The macros used here must preserve the result register.
485769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
485869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Because the handler block contains the context of the finally
485969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // code, we can restore it directly from there for the finally code
486069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // rather than iteratively unwinding contexts via their previous
486169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // links.
486269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ Drop(*stack_depth);  // Down to the handler block.
486369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (*context_length > 0) {
486469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Restore the context to its dedicated register and the stack.
486569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ ldr(cp, MemOperand(sp, StackHandlerConstants::kContextOffset));
486669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
486769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
486869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ PopTryHandler();
486969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bl(finally_entry_);
487069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
487169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  *stack_depth = 0;
487269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  *context_length = 0;
487369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return previous_;
487469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
487569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
487669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
487769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#undef __
487869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
4879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Address GetInterruptImmediateLoadAddress(Address pc) {
4881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address load_address = pc - 2 * Assembler::kInstrSize;
4882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_enable_ool_constant_pool) {
4883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(load_address)));
4884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (Assembler::IsLdrPpRegOffset(Memory::int32_at(load_address))) {
4885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This is an extended constant pool lookup.
4886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (CpuFeatures::IsSupported(ARMv7)) {
4887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      load_address -= 2 * Assembler::kInstrSize;
4888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Assembler::IsMovW(Memory::int32_at(load_address)));
4889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Assembler::IsMovT(
4890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Memory::int32_at(load_address + Assembler::kInstrSize)));
4891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      load_address -= 4 * Assembler::kInstrSize;
4893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Assembler::IsMovImmed(Memory::int32_at(load_address)));
4894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Assembler::IsOrrImmed(
4895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Memory::int32_at(load_address + Assembler::kInstrSize)));
4896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Assembler::IsOrrImmed(
4897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Memory::int32_at(load_address + 2 * Assembler::kInstrSize)));
4898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Assembler::IsOrrImmed(
4899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Memory::int32_at(load_address + 3 * Assembler::kInstrSize)));
4900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (CpuFeatures::IsSupported(ARMv7) &&
4902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             Assembler::IsMovT(Memory::int32_at(load_address))) {
4903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This is a movw / movt immediate load.
4904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    load_address -= Assembler::kInstrSize;
4905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsMovW(Memory::int32_at(load_address)));
4906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (!CpuFeatures::IsSupported(ARMv7) &&
4907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             Assembler::IsOrrImmed(Memory::int32_at(load_address))) {
4908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This is a mov / orr immediate load.
4909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    load_address -= 3 * Assembler::kInstrSize;
4910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsMovImmed(Memory::int32_at(load_address)));
4911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsOrrImmed(
4912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Memory::int32_at(load_address + Assembler::kInstrSize)));
4913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsOrrImmed(
4914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Memory::int32_at(load_address + 2 * Assembler::kInstrSize)));
4915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This is a small constant pool lookup.
4917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(load_address)));
4918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return load_address;
4920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BackEdgeTable::PatchAt(Code* unoptimized_code,
4924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Address pc,
4925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            BackEdgeState target_state,
4926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Code* replacement_code) {
4927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc);
4928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address branch_address = pc_immediate_load_address - Assembler::kInstrSize;
4929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodePatcher patcher(branch_address, 1);
4930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (target_state) {
4931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case INTERRUPT:
4932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
4933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  <decrement profiling counter>
4934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   bpl ok
4935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; load interrupt stub address into ip - either of (for ARMv7):
4936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; <small cp load>      |  <extended cp load> |  <immediate load>
4937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ldr ip, [pc/pp, #imm]  |   movw ip, #imm     |   movw ip, #imm
4938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   movt ip, #imm     |   movw ip, #imm
4939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   ldr  ip, [pp, ip]
4940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; or (for ARMv6):
4941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; <small cp load>      |  <extended cp load> |  <immediate load>
4942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ldr ip, [pc/pp, #imm]  |   mov ip, #imm      |   mov ip, #imm
4943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
4944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
4945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
4946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   blx ip
4947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  <reset profiling counter>
4948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  ok-label
4949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Calculate branch offset to the ok-label - this is the difference
4951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // between the branch address and |pc| (which points at <blx ip>) plus
4952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // kProfileCounterResetSequence instructions
4953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int branch_offset = pc - Instruction::kPCReadOffset - branch_address +
4954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          kProfileCounterResetSequenceLength;
4955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      patcher.masm()->b(branch_offset, pl);
4956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
4957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case ON_STACK_REPLACEMENT:
4959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case OSR_AFTER_STACK_CHECK:
4960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  <decrement profiling counter>
4961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   mov r0, r0 (NOP)
4962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; load on-stack replacement address into ip - either of (for ARMv7):
4963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; <small cp load>      |  <extended cp load> |  <immediate load>
4964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ldr ip, [pc/pp, #imm]  |   movw ip, #imm     |   movw ip, #imm
4965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   movt ip, #imm>    |   movw ip, #imm
4966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   ldr  ip, [pp, ip]
4967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; or (for ARMv6):
4968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ; <small cp load>      |  <extended cp load> |  <immediate load>
4969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ldr ip, [pc/pp, #imm]  |   mov ip, #imm      |   mov ip, #imm
4970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
4971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
4972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //                          |   orr ip, ip, #imm> |   orr ip, ip, #imm
4973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   blx ip
4974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  <reset profiling counter>
4975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //  ok-label
4976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      patcher.masm()->nop();
4977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
4978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Replace the call address.
4981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler::set_target_address_at(pc_immediate_load_address, unoptimized_code,
4982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      replacement_code->entry());
4983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
4985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      unoptimized_code, pc_immediate_load_address, replacement_code);
4986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
4990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Isolate* isolate,
4991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Code* unoptimized_code,
4992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Address pc) {
4993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Assembler::IsBlxIp(Memory::int32_at(pc - Assembler::kInstrSize)));
4994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc);
4996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address branch_address = pc_immediate_load_address - Assembler::kInstrSize;
4997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address interrupt_address = Assembler::target_address_at(
4998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      pc_immediate_load_address, unoptimized_code);
4999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (Assembler::IsBranch(Assembler::instr_at(branch_address))) {
5001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(interrupt_address ==
5002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           isolate->builtins()->InterruptCheck()->entry());
5003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return INTERRUPT;
5004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Assembler::IsNop(Assembler::instr_at(branch_address)));
5007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (interrupt_address ==
5009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate->builtins()->OnStackReplacement()->entry()) {
5010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return ON_STACK_REPLACEMENT;
5011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(interrupt_address ==
5014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         isolate->builtins()->OsrAfterStackCheck()->entry());
5015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return OSR_AFTER_STACK_CHECK;
5016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
50193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} }  // namespace v8::internal
5020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
5022