13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
23ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Redistribution and use in source and binary forms, with or without
33ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// modification, are permitted provided that the following conditions are
43ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// met:
53ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
63ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//     * Redistributions of source code must retain the above copyright
73ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       notice, this list of conditions and the following disclaimer.
83ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//     * Redistributions in binary form must reproduce the above
93ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       copyright notice, this list of conditions and the following
103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       disclaimer in the documentation and/or other materials provided
113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       with the distribution.
123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//     * Neither the name of Google Inc. nor the names of its
133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       contributors may be used to endorse or promote products derived
143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       from this software without specific prior written permission.
153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "v8.h"
293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_ARM)
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "code-stubs.h"
338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h"
34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h"
35d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "debug.h"
36d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "full-codegen.h"
373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "isolate-inl.h"
383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "parser.h"
396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "scopes.h"
408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#include "stub-cache.h"
413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block#include "arm/code-stubs-arm.h"
433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "arm/macro-assembler-arm.h"
449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 {
463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal {
473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_)
493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// A patch site is a location in the code which it is possible to patch. This
521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// class has a number of methods to emit the code which is patchable and the
531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// method EmitPatchInfo to record a marker back to the patchable code. This
541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// marker is a cmp rx, #yyy instruction, and x * 0x00000fff + yyy (raw 12 bit
551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// immediate value is used) is the delta from the pc to the first instruction of
561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// the patchable code.
571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass JumpPatchSite BASE_EMBEDDED {
581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    info_emitted_ = false;
621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ~JumpPatchSite() {
661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(patch_site_.is_bound() == info_emitted_);
671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // When initially emitting this ensure that a jump is always generated to skip
701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the inlined smi code.
711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EmitJumpIfNotSmi(Register reg, Label* target) {
721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(!patch_site_.is_bound() && !info_emitted_);
73db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch    Assembler::BlockConstPoolScope block_const_pool(masm_);
741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&patch_site_);
751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cmp(reg, Operand(reg));
761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Don't use b(al, ...) as that might emit the constant pool right after the
771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // branch. After patching when the branch is no longer unconditional
781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // execution can continue into the constant pool.
791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(eq, target);  // Always taken before patched.
801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // When initially emitting this ensure that a jump is never generated to skip
831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the inlined smi code.
841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EmitJumpIfSmi(Register reg, Label* target) {
851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(!patch_site_.is_bound() && !info_emitted_);
86db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch    Assembler::BlockConstPoolScope block_const_pool(masm_);
871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&patch_site_);
881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cmp(reg, Operand(reg));
891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(ne, target);  // Never taken before patched.
901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EmitPatchInfo() {
933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (patch_site_.is_bound()) {
943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_);
953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Register reg;
963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      reg.set_code(delta_to_patch_site / kOff12Mask);
973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ cmp_raw_immediate(reg, delta_to_patch_site % kOff12Mask);
981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      info_emitted_ = true;
1001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
1013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
1023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ nop();  // Signals no inlined code.
1033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
1041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
1071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  MacroAssembler* masm_;
1081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Label patch_site_;
1091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
1101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool info_emitted_;
1111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
1121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
1131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// TODO(jkummerow): Obsolete as soon as x64 is updated. Remove.
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint FullCodeGenerator::self_optimization_header_size() {
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return 24;
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function.  On entry to the function the receiver
1233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right.  The actual
1243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// argument count matches the formal parameter count expected by the
1253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// function.
1263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
1273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are:
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   o r1: the JS function object being called (i.e., ourselves)
1293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o cp: our context
1303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o fp: our caller's frame pointer
1313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o sp: stack pointer
1323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o lr: return address
1333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
1343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame.  Please see JavaScriptFrameConstants in
1353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-arm.h for its layout.
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::Generate() {
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompilationInfo* info = info_;
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  handler_table_ =
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell(
1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget)));
1423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  SetFunctionPosition(function());
1436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comment cmnt(masm_, "[ function compiled by full code generator");
1443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
145f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG
146f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (strlen(FLAG_stop_at) > 0 &&
147f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
148f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ stop("stop-at");
149f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
150f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif
151f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Strict mode functions and builtins need to replace the receiver
1533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // with undefined when called as functions (without an explicit
1543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // receiver object). r5 is zero for method calls and non-zero for
1553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // function calls.
1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!info->is_classic_mode() || info->is_native()) {
157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label ok;
158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ cmp(r5, Operand(0));
159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ b(eq, &ok);
1603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int receiver_offset = info->scope()->num_parameters() * kPointerSize;
161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ str(r2, MemOperand(sp, receiver_offset));
163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&ok);
164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Open a frame scope to indicate that there is a frame on the stack.  The
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // MANUAL indicates that the scope shouldn't actually generate code to set up
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the frame (that is done below).
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameScope frame_scope(masm_, StackFrame::MANUAL);
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int locals_count = info->scope()->num_stack_slots();
1723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
173756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ Push(lr, fp, cp, r1);
174756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (locals_count > 0) {
175756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Load undefined value here, so the value is ready for the loop
176756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // below.
177756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
178756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
179756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Adjust fp to point to caller's fp.
180756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ add(fp, sp, Operand(2 * kPointerSize));
1813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
182756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  { Comment cmnt(masm_, "[ Allocate locals");
183756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (int i = 0; i < locals_count; i++) {
184756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ push(ip);
1854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
186756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
188756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  bool function_in_register = true;
1894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
190756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate a local context.
1913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
192756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (heap_slots > 0) {
193756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate local context");
194756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Argument to NewContext is the function, which is in r1.
195756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ push(r1);
196756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
197756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      FastNewContextStub stub(heap_slots);
198756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ CallStub(&stub);
199756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
2003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ CallRuntime(Runtime::kNewFunctionContext, 1);
201756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
202756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    function_in_register = false;
203756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Context is returned in both r0 and cp.  It replaces the context
204756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // passed to us.  It's saved in the stack and kept live in cp.
205756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
206756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Copy any necessary parameters into the context.
2073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int num_parameters = info->scope()->num_parameters();
208756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (int i = 0; i < num_parameters; i++) {
209589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Variable* var = scope()->parameter(i);
210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (var->IsContextSlot()) {
211756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
212756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick            (num_parameters - 1 - i) * kPointerSize;
213756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Load parameter from stack.
214756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ ldr(r0, MemOperand(fp, parameter_offset));
215756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Store it in the context.
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        MemOperand target = ContextOperand(cp, var->index());
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ str(r0, target);
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Update the write barrier.
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ RecordWriteContextSlot(
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            cp, target.offset(), r0, r3, kLRHasBeenSaved, kDontSaveFPRegs);
222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
224756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Variable* arguments = scope()->arguments();
227756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (arguments != NULL) {
228756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Function uses arguments object.
229756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate arguments object");
230756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (!function_in_register) {
231756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      // Load this again, if it's used by the local context below.
232756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
233756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
234756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ mov(r3, r1);
235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
236756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Receiver is just before the parameters on the caller's stack.
2373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int num_parameters = info->scope()->num_parameters();
2383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int offset = num_parameters * kPointerSize;
239756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ add(r2, fp,
240756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           Operand(StandardFrameConstants::kCallerSPOffset + offset));
2413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ mov(r1, Operand(Smi::FromInt(num_parameters)));
242756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ Push(r3, r2, r1);
243756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
244756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Arguments to ArgumentsAccessStub:
245756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    //   function, receiver address, parameter count.
246756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The stub will rewrite receiever and parameter count if the previous
247756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // stack frame was an arguments adapter frame.
2483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ArgumentsAccessStub::Type type;
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!is_classic_mode()) {
2503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      type = ArgumentsAccessStub::NEW_STRICT;
2513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else if (function()->has_duplicate_parameters()) {
2523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
2533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
2543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      type = ArgumentsAccessStub::NEW_NON_STRICT_FAST;
2553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ArgumentsAccessStub stub(type);
257756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
25844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
259589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SetVar(arguments, r0, r1, r2);
260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace) {
263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ CallRuntime(Runtime::kTraceEnter, 0);
264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Visit the declarations and body unless there is an illegal
267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // redeclaration.
268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (scope()->HasIllegalRedeclaration()) {
269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Comment cmnt(masm_, "[ Declarations");
270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    scope()->VisitIllegalRedeclaration(this);
2713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
273589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    { Comment cmnt(masm_, "[ Declarations");
275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // For named function expressions, declare the function name as a
276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // constant.
277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (scope()->is_function_scope() && scope()->function() != NULL) {
2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VariableProxy* proxy = scope()->function();
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(proxy->var()->mode() == CONST ||
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               proxy->var()->mode() == CONST_HARMONY);
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(proxy->var()->location() != Variable::UNALLOCATED);
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        EmitDeclaration(proxy, proxy->var()->mode(), NULL);
283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      VisitDeclarations(scope()->declarations());
285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    { Comment cmnt(masm_, "[ Stack check");
288589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS);
289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Label ok;
290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ LoadRoot(ip, Heap::kStackLimitRootIndex);
291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ cmp(sp, Operand(ip));
292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(hs, &ok);
293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      StackCheckStub stub;
294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ CallStub(&stub);
295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ bind(&ok);
296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
298e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    { Comment cmnt(masm_, "[ Body");
299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(loop_depth() == 0);
300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      VisitStatements(function()->body());
301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(loop_depth() == 0);
302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
3033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
3043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Always emit a 'return undefined' in case control fell off the end of
306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the body.
3073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
3083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  EmitReturnSequence();
311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Force emit the constant pool, so it doesn't get emitted in the middle
313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // of the stack check table.
314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  masm()->CheckConstPool(true, false);
315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
318db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdochvoid FullCodeGenerator::ClearAccumulator() {
319db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  __ mov(r0, Operand(Smi::FromInt(0)));
320db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch}
321db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
322db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r2, Operand(profiling_counter_));
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(r3, r3, Operand(Smi::FromInt(delta)), SetCC);
3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitProfilingCounterReset() {
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int reset_value = FLAG_interrupt_budget;
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) {
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Self-optimization is a one-off thing: if it fails, don't try again.
3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    reset_value = Smi::kMaxValue;
3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->IsDebuggerActive()) {
3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Detect debug break requests as soon as possible.
3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    reset_value = 10;
3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r2, Operand(profiling_counter_));
3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r3, Operand(Smi::FromInt(reset_value)));
3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kMaxBackEdgeWeight = 127;
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kBackEdgeDistanceDivisor = 142;
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStackCheck(IterationStatement* stmt,
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Label* back_edge_target) {
353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Comment cmnt(masm_, "[ Stack check");
354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label ok;
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_count_based_interrupts) {
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int weight = 1;
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_weighted_back_edges) {
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(back_edge_target->is_bound());
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      weight = Min(kMaxBackEdgeWeight,
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Max(1, distance / kBackEdgeDistanceDivisor));
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitProfilingCounterDecrement(weight);
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(pl, &ok);
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InterruptStub stub;
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(ip, Heap::kStackLimitRootIndex);
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(sp, Operand(ip));
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(hs, &ok);
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    StackCheckStub stub;
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
376086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Record a mapping of this PC offset to the OSR id.  This is used to find
377086aeeaae12517475c22695a200be45495516549Ben Murdoch  // the AST id from the unoptimized code in order to use it as a key into
378086aeeaae12517475c22695a200be45495516549Ben Murdoch  // the deoptimization input data found in the optimized code.
379086aeeaae12517475c22695a200be45495516549Ben Murdoch  RecordStackCheck(stmt->OsrEntryId());
380086aeeaae12517475c22695a200be45495516549Ben Murdoch
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_count_based_interrupts) {
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitProfilingCounterReset();
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&ok);
386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
387086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Record a mapping of the OSR id to this PC.  This is used if the OSR
388086aeeaae12517475c22695a200be45495516549Ben Murdoch  // entry becomes the target of a bailout.  We don't expect it to be, but
389086aeeaae12517475c22695a200be45495516549Ben Murdoch  // we want it to work if it is.
390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() {
395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ b(&return_label_);
398d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
399d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
4003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
4013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // Push the return value on the stack as the parameter.
4023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // Runtime::TraceExit returns its parameter in r0.
4033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(r0);
4043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ CallRuntime(Runtime::kTraceExit, 1);
4053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_interrupt_at_exit || FLAG_self_optimization) {
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Pretend that the exit is a backwards jump to the entry.
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int weight = 1;
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (info_->ShouldSelfOptimize()) {
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        weight = FLAG_interrupt_budget / FLAG_self_opt_count;
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (FLAG_weighted_back_edges) {
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int distance = masm_->pc_offset();
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        weight = Min(kMaxBackEdgeWeight,
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Max(1, distance / kBackEdgeDistanceDivisor));
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitProfilingCounterDecrement(weight);
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label ok;
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ b(pl, &ok);
4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(r0);
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) {
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ push(r2);
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1);
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        InterruptStub stub;
4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CallStub(&stub);
4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(r0);
4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitProfilingCounterReset();
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&ok);
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
4323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG
434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Add a label for checking the size of the code used for returning.
435d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Label check_exit_codesize;
436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    masm_->bind(&check_exit_codesize);
4376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
4386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Make sure that the constant pool is not emitted inside of the return
4396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // sequence.
4406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    { Assembler::BlockConstPoolScope block_const_pool(masm_);
4416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Here we use masm_-> instead of the __ macro to avoid the code coverage
4426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // tool from instrumenting as we rely on the code size here.
4433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize;
444bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
4456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ RecordJSReturn();
4466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      masm_->mov(sp, fp);
4476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      masm_->ldm(ia_w, sp, fp.bit() | lr.bit());
4486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      masm_->add(sp, sp, Operand(sp_delta));
4496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      masm_->Jump(lr);
450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG
4531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check that the size of the code used for returning is large enough
4541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // for the debugger's requirements.
4551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(Assembler::kJSReturnSequenceInstructions <=
4561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           masm_->InstructionsGeneratedSince(&check_exit_codesize));
4576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
462589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EffectContext::Plug(Variable* var) const {
463589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
4640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
467589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
468589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
469589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  codegen()->GetVar(result_register(), var);
4700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
473589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
474589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
475589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  codegen()->GetVar(result_register(), var);
4760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(result_register());
477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
479d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
480589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::TestContext::Plug(Variable* var) const {
481589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
4820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
483589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  codegen()->GetVar(result_register(), var);
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
4853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  codegen()->DoTest(this);
486d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
487d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
488d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4890d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
4900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4930d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
4940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
4950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), index);
4960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4990d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
5000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
5010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), index);
5020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(result_register());
5030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5060d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
5110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (index == Heap::kUndefinedValueRootIndex ||
5120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kNullValueRootIndex ||
5130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kFalseValueRootIndex) {
514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (false_label_ != fall_through_) __ b(false_label_);
5150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (index == Heap::kTrueValueRootIndex) {
516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (true_label_ != fall_through_) __ b(true_label_);
5170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
5180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ LoadRoot(result_register(), index);
5193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    codegen()->DoTest(this);
520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5240d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
5250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
526e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5280d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
5290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Handle<Object> lit) const {
5300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), Operand(lit));
5310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5340d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Immediates cannot be pushed directly.
5360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), Operand(lit));
5370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(result_register());
5380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5410d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
5460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!lit->IsUndetectableObject());  // There are no undetectable literals.
5470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (false_label_ != fall_through_) __ b(false_label_);
5490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsTrue() || lit->IsJSObject()) {
550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (true_label_ != fall_through_) __ b(true_label_);
5510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsString()) {
5520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (String::cast(*lit)->length() == 0) {
5538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (false_label_ != fall_through_) __ b(false_label_);
5540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ b(true_label_);
5560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
5570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsSmi()) {
5580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (Smi::cast(*lit)->value() == 0) {
559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (false_label_ != fall_through_) __ b(false_label_);
5600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ b(true_label_);
5620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
5630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
5640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // For simplicity we always test the accumulator register.
5650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ mov(result_register(), Operand(lit));
5663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    codegen()->DoTest(this);
567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5710d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count,
5720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                   Register reg) const {
573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(count > 0);
5740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
5750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
576e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5780d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
5790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    int count,
5800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Register reg) const {
5810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
5820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
5830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
5840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5870d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count,
5880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                       Register reg) const {
5890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
5900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (count > 1) __ Drop(count - 1);
5910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ str(reg, MemOperand(sp, 0));
592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5950d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count,
5960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                 Register reg) const {
5970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
5990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
6000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
6023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  codegen()->DoTest(this);
6030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6060d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
6070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            Label* materialize_false) const {
608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(materialize_true == materialize_false);
6090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
6100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6130d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
6140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
6150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
6160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label done;
6170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
6180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
6190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ jmp(&done);
6200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
6210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
6220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
624d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6260d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
6270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
6280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
6290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label done;
6300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
6310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(ip, Heap::kTrueValueRootIndex);
6320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(ip);
6330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ jmp(&done);
6340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
6350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(ip, Heap::kFalseValueRootIndex);
6360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(ip);
6370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
6380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6410d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true,
6420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                          Label* materialize_false) const {
6430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(materialize_true == true_label_);
644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(materialize_false == false_label_);
6450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6480d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const {
6490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6520d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
6530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
6540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
6550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), value_root_index);
6560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6590d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const {
6600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
6610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
6620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(ip, value_root_index);
6630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(ip);
6640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6670d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const {
6683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
6720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (flag) {
6730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (true_label_ != fall_through_) __ b(true_label_);
6740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
6750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (false_label_ != fall_through_) __ b(false_label_);
676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
678f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
6803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::DoTest(Expression* condition,
6813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               Label* if_true,
68280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* if_false,
68380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* fall_through) {
6848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (CpuFeatures::IsSupported(VFP3)) {
685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ToBooleanStub stub(result_register());
686e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CallStub(&stub);
687e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ tst(result_register(), result_register());
688e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
689e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Call the runtime to find the boolean value of the source and then
690e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // translate it into control flow to the pair of labels.
691e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ push(result_register());
692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CallRuntime(Runtime::kToBool, 1);
693e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ LoadRoot(ip, Heap::kFalseValueRootIndex);
694e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ cmp(r0, ip);
695e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Split(ne, if_true, if_false, fall_through);
69780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
7001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid FullCodeGenerator::Split(Condition cond,
70180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_true,
70280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_false,
70380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* fall_through) {
70480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (if_false == fall_through) {
7051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(cond, if_true);
70680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (if_true == fall_through) {
7071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(NegateCondition(cond), if_false);
70880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
7091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(cond, if_true);
71080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(if_false);
711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
715589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) {
716589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsStackAllocated());
717589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Offset is negative because higher indexes are at lower addresses.
718589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int offset = -var->index() * kPointerSize;
719589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Adjust by a (parameter or local) base offset.
720589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsParameter()) {
721589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
722589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else {
723589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    offset += JavaScriptFrameConstants::kLocal0Offset;
724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
725589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return MemOperand(fp, offset);
726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
729589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
730589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
731589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsContextSlot()) {
732589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    int context_chain_length = scope()->ContextChainLength(var->scope());
733589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ LoadContext(scratch, context_chain_length);
734589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return ContextOperand(scratch, var->index());
735589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else {
736589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return StackOperand(var);
737589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
738589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
739589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
740589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
741589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) {
742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Use destination as scratch.
743589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand location = VarOperand(var, dest);
744589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ ldr(dest, location);
745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
748589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::SetVar(Variable* var,
749589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register src,
750589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register scratch0,
751589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register scratch1) {
752589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
753589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(!scratch0.is(src));
754589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(!scratch0.is(scratch1));
755589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(!scratch1.is(src));
756589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand location = VarOperand(var, scratch0);
757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ str(src, location);
7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
759e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
760589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsContextSlot()) {
7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteContextSlot(scratch0,
7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              location.offset(),
7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              src,
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              scratch1,
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              kLRHasBeenSaved,
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              kDontSaveFPRegs);
767e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     bool should_normalize,
773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_true,
774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_false) {
775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Only prepare for bailouts before splits if we're in a test
776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // context. Otherwise, we let the Visit function deal with the
777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // preparation to avoid preparing with the same AST id twice.
778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!context()->IsTest() || !info_->IsOptimizable()) return;
779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label skip;
781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (should_normalize) __ b(&skip);
7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailout(expr, TOS_REG);
783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (should_normalize) {
784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ LoadRoot(ip, Heap::kTrueValueRootIndex);
785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ cmp(r0, ip);
786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Split(eq, if_true, if_false, NULL);
787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ bind(&skip);
788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
792589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        VariableMode mode,
7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        FunctionLiteral* function) {
795589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // If it was not possible to allocate the variable at compile time, we
796589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // need to "declare" it at runtime to make sure it actually exists in the
797589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // local context.
798589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Variable* variable = proxy->var();
7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool binding_needs_init = (function == NULL) &&
8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (mode == CONST || mode == CONST_HARMONY || mode == LET);
801589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (variable->location()) {
802589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::UNALLOCATED:
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ++global_count_;
804589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
805589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
806589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::PARAMETER:
807589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOCAL:
80869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (function != NULL) {
809589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Comment cmnt(masm_, "[ Declaration");
81069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        VisitForAccumulatorValue(function);
811589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ str(result_register(), StackOperand(variable));
8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (binding_needs_init) {
813589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Comment cmnt(masm_, "[ Declaration");
81469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
815589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ str(ip, StackOperand(variable));
816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
81769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
819589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::CONTEXT:
82069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // The variable in the decl always resides in the current function
82169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // context.
82269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
82369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (FLAG_debug_code) {
82469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // Check that we're not inside a with or catch context.
82569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset));
82669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ CompareRoot(r1, Heap::kWithContextMapRootIndex);
82769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ Check(ne, "Declaration in with context.");
82869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ CompareRoot(r1, Heap::kCatchContextMapRootIndex);
82969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ Check(ne, "Declaration in catch context.");
8301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
83169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (function != NULL) {
832589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Comment cmnt(masm_, "[ Declaration");
83369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        VisitForAccumulatorValue(function);
834589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ str(result_register(), ContextOperand(cp, variable->index()));
835589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        int offset = Context::SlotOffset(variable->index());
83669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // We know that we have written a function, which is not a smi.
8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ RecordWriteContextSlot(cp,
8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  offset,
8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  result_register(),
8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  r2,
8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  kLRHasBeenSaved,
8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  kDontSaveFPRegs,
8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  EMIT_REMEMBERED_SET,
8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  OMIT_SMI_CHECK);
845589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (binding_needs_init) {
847589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Comment cmnt(masm_, "[ Declaration");
84869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
849589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ str(ip, ContextOperand(cp, variable->index()));
85069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // No write barrier since the_hole_value is in old space.
851589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
85269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
85369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
855589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOOKUP: {
856589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Comment cmnt(masm_, "[ Declaration");
85769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov(r2, Operand(variable->name()));
8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Declaration nodes are always introduced in one of four modes.
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(mode == VAR ||
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             mode == CONST ||
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             mode == CONST_HARMONY ||
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             mode == LET);
8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY)
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? READ_ONLY : NONE;
86569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov(r1, Operand(Smi::FromInt(attr)));
86669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // Push initial value, if any.
86769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // Note: For variables we must not push an initial value (such as
86869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // 'undefined') because we may have a (legal) redeclaration and we
86969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // must not destroy the current value.
87069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (function != NULL) {
87169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ Push(cp, r2, r1);
87269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // Push initial value for function declaration.
87369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        VisitForStackValue(function);
8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (binding_needs_init) {
87569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
87669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ Push(cp, r2, r1, r0);
87769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      } else {
878589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ mov(r0, Operand(Smi::FromInt(0)));  // Indicates no initial value.
87969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ Push(cp, r2, r1, r0);
88069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
88169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ CallRuntime(Runtime::kDeclareContextSlot, 4);
88269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
888d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
8903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // The context is the first argument.
891589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ mov(r1, Operand(pairs));
892589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags())));
893589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ Push(cp, r1, r0);
894589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ CallRuntime(Runtime::kDeclareGlobals, 3);
8953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
8963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ SwitchStatement");
901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Breakable nested_statement(this, stmt);
902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Keep the switch value on the stack until a case matches.
9050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(stmt->tag());
906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<CaseClause*>* clauses = stmt->cases();
909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label next_test;  // Recycled for each test.
912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the tests with branches to their bodies.
913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
9158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    clause->body_target()->Unuse();
9161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The default is not a test, but remember it as final fall through.
918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (clause->is_default()) {
919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      default_clause = clause;
920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      continue;
921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case comparison");
924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&next_test);
925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    next_test.Unuse();
926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Compile the label expression.
9280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(clause->label());
929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
93080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Perform the comparison as if via '==='.
931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(r1, MemOperand(sp, 0));  // Switch value.
9320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
9331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    JumpPatchSite patch_site(masm_);
9340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (inline_smi_code) {
93580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label slow_case;
93680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ orr(r2, r1, r0);
9371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      patch_site.EmitJumpIfNotSmi(r2, &slow_case);
9381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
93980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ cmp(r1, r0);
94080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ b(ne, &next_test);
94180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ Drop(1);  // Switch value is no longer needed.
9428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      __ b(clause->body_target());
9431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ bind(&slow_case);
94480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
94580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
9461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Record position before stub call for type feedback.
9471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    SetSourcePosition(clause->position());
9481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
9493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId());
9503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    patch_site.EmitPatchInfo();
951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
9521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cmp(r0, Operand(0));
953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(ne, &next_test);
954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
9558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ b(clause->body_target());
956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Discard the test value and jump to the default if present, otherwise to
959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the end of the statement.
960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&next_test);
961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(1);  // Switch value is no longer needed.
962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (default_clause == NULL) {
96369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ b(nested_statement.break_label());
964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
9658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ b(default_clause->body_target());
966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the case bodies.
969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case body");
971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
9728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ bind(clause->body_target());
97344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitStatements(clause->statements());
975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
97769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(nested_statement.break_label());
978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ ForInStatement");
984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label loop, exit;
987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ForIn loop_statement(this, stmt);
988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  increment_loop_depth();
989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the object to enumerate over. Both SpiderMonkey and JSC
991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ignore null and undefined in contrast to the specification; see
992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ECMA-262 section 12.6.4.
9930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(stmt->enumerable());
994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, ip);
996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, &exit);
997e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register null_value = r5;
998e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ LoadRoot(null_value, Heap::kNullValueRootIndex);
999e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(r0, null_value);
1000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, &exit);
1001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the object to a JS object.
1005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label convert, done_convert;
10061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, &convert);
10073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
10083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ b(ge, &done_convert);
1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&convert);
1010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);
1011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done_convert);
1013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);
1014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for proxies.
10163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label call_runtime;
10173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
10183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE);
10193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(le, &call_runtime);
10203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1021e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check cache validity in generated code. This is a fast case for
1022e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
1023e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // guarantee cache validity, call the runtime system to check cache
1024e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // validity or get the property names in a fixed array.
10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckEnumCache(null_value, &call_runtime);
1026e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1027e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // The enum cache is valid.  Load the map of the object being
1028e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // iterated over and use the cache for the iteration.
1029e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Label use_cache;
1030e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
1031e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(&use_cache);
1032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the set of properties to enumerate.
1034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&call_runtime);
1035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);  // Duplicate the enumerable object on the stack.
1036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If we got a map from the runtime call, we can do a fast
1039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // modification check. Otherwise, we got a fixed array, and we have
1040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // to do a slow check.
1041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label fixed_array;
1042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r2, r0);
1043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));
1044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(ip, Heap::kMetaMapRootIndex);
1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, ip);
1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &fixed_array);
1047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a map in register r0. Get the enumeration cache from it.
1049e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&use_cache);
1050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadInstanceDescriptors(r0, r1);
1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset));
1052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));
1053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the four remaining stack slots.
1055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);  // Map.
1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r2, FixedArray::kLengthOffset));
1057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r0, Operand(Smi::FromInt(0)));
1058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Push enumeration cache, enumeration cache length (as smi) and zero.
1059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(r2, r1, r0);
1060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
1061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a fixed array in register r0. Iterate through that.
10633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label non_proxy;
1064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&fixed_array);
10653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSGlobalPropertyCell> cell =
10673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->factory()->NewJSGlobalPropertyCell(
10683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Handle<Object>(
10693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker)));
10703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordTypeFeedbackCell(stmt->PrepareId(), cell);
10713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(r1, cell);
10723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)));
10733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ str(r2, FieldMemOperand(r1, JSGlobalPropertyCell::kValueOffset));
10743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r1, Operand(Smi::FromInt(1)));  // Smi indicates slow check
10763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(r2, MemOperand(sp, 0 * kPointerSize));  // Get enumerated object
10773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE);
10793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(gt, &non_proxy);
10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r1, Operand(Smi::FromInt(0)));  // Zero indicates proxy
10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&non_proxy);
10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(r1, r0);  // Smi and array
1083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset));
1084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r0, Operand(Smi::FromInt(0)));
1085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(r1, r0);  // Fixed array length (as smi) and initial index.
1086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for doing the condition check.
10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&loop);
1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the current count to r0, load the length to r1.
1091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
1092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, r1);  // Compare to the array length.
109369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ b(hs, loop_statement.break_label());
1094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the current entry of the array into register r3.
1096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(sp, 2 * kPointerSize));
1097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
11003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the expected map from the stack or a smi in the
1101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // permanent slow case into register r2.
1102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(sp, 3 * kPointerSize));
1103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the expected map still matches that of the enumerable.
11053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If not, we may have to filter the key.
1106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label update_each;
1107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, MemOperand(sp, 4 * kPointerSize));
1108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset));
1109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r4, Operand(r2));
1110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, &update_each);
1111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For proxies, no filtering is done.
11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r2, Operand(Smi::FromInt(0)));
11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(eq, &update_each);
11163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1117756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Convert the entry to a string or (smi) 0 if it isn't a property
1118756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // any more. If the property has been removed while iterating, we
1119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // just skip it.
1120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r1);  // Enumerable.
1121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r3);  // Current entry.
1122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1123756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ mov(r3, Operand(r0), SetCC);
112469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ b(eq, loop_statement.continue_label());
1125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the 'each' property or variable from the possibly filtered
1127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // entry in register r3.
1128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&update_each);
1129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(result_register(), r3);
1130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Perform the assignment as if via '='.
1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { EffectContext context(this);
11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAssignment(stmt->each());
1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the body of the loop.
1136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Visit(stmt->body());
1137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the going to the next element by incrementing
1139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the index (smi) stored on top of the stack.
114069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.continue_label());
1141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r0);
1142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(r0, r0, Operand(Smi::FromInt(1)));
1143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);
1144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
11453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitStackCheck(stmt, &loop);
1146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ b(&loop);
1147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Remove the pointers stored on the stack.
114969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.break_label());
1150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(5);
1151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Exit and decrement the loop depth.
11533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
1155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  decrement_loop_depth();
1156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
11573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
11608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                       bool pretenure) {
1161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Use the fast case closure allocation code that allocates in new
1162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // space for nested functions that don't need literals cloning. If
1163e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // we're running with the --always-opt or the --prepare-always-opt
1164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // flag, we need to use the runtime function so that the new function
1165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // we are creating here gets a chance to have its code optimized and
1166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // doesn't just get a copy of the existing unoptimized code.
1167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!FLAG_always_opt &&
1168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      !FLAG_prepare_always_opt &&
116944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      !pretenure &&
1170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      scope()->is_function_scope() &&
117144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      info->num_literals() == 0) {
11723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastNewClosureStub stub(info->language_mode());
1173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r0, Operand(info));
1174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(r0);
1175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
1176f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r0, Operand(info));
11788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ LoadRoot(r1, pretenure ? Heap::kTrueValueRootIndex
11798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                              : Heap::kFalseValueRootIndex);
11808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Push(cp, r0, r1);
11818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ CallRuntime(Runtime::kNewClosure, 3);
1182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
11830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
11843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1187d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
11883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ VariableProxy");
11893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  EmitVariableLoad(expr);
1190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1193589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
1194589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                      TypeofState typeof_state,
1195589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                      Label* slow) {
1196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register current = cp;
1197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register next = r1;
1198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register temp = r2;
1199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Scope* s = scope();
1201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  while (s != NULL) {
1202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (s->num_heap_slots() > 0) {
12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (s->calls_non_strict_eval()) {
1204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Check that extension is NULL.
1205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX));
1206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ tst(temp, temp);
1207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ b(ne, slow);
1208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
1209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Load next context in chain.
12103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ ldr(next, ContextOperand(current, Context::PREVIOUS_INDEX));
1211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Walk the rest of the chain without clobbering cp.
1212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      current = next;
1213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // If no outer scope calls eval, we do not need to check more
1215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // context extensions.
12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break;
1217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    s = s->outer_scope();
1218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (s->is_eval_scope()) {
1221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label loop, fast;
1222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!current.is(next)) {
1223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Move(next, current);
1224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&loop);
1226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Terminate at global context.
1227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset));
1228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(ip, Heap::kGlobalContextMapRootIndex);
1229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ cmp(temp, ip);
1230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ b(eq, &fast);
1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that extension is NULL.
1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX));
1233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ tst(temp, temp);
1234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ b(ne, slow);
1235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Load next context in chain.
12363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ ldr(next, ContextOperand(next, Context::PREVIOUS_INDEX));
1237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ b(&loop);
1238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&fast);
1239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ldr(r0, GlobalObjectOperand());
1242589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ mov(r2, Operand(var->name()));
1243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
1244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? RelocInfo::CODE_TARGET
1245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : RelocInfo::CODE_TARGET_CONTEXT;
1246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
12473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(ic, mode);
1248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1251589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1252589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                                Label* slow) {
1253589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsContextSlot());
1254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register context = cp;
125559151504615d929945dc59db37bf1166937748c6Steve Block  Register next = r3;
125659151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = r4;
125759151504615d929945dc59db37bf1166937748c6Steve Block
1258589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
125959151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (s->calls_non_strict_eval()) {
126159151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
1262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX));
126359151504615d929945dc59db37bf1166937748c6Steve Block        __ tst(temp, temp);
126459151504615d929945dc59db37bf1166937748c6Steve Block        __ b(ne, slow);
126559151504615d929945dc59db37bf1166937748c6Steve Block      }
12663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ ldr(next, ContextOperand(context, Context::PREVIOUS_INDEX));
126759151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering cp.
1268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      context = next;
126959151504615d929945dc59db37bf1166937748c6Steve Block    }
127059151504615d929945dc59db37bf1166937748c6Steve Block  }
127159151504615d929945dc59db37bf1166937748c6Steve Block  // Check that last extension is NULL.
1272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX));
127359151504615d929945dc59db37bf1166937748c6Steve Block  __ tst(temp, temp);
127459151504615d929945dc59db37bf1166937748c6Steve Block  __ b(ne, slow);
1275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // This function is used only for loads, not stores, so it's safe to
1277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // return an cp-based operand (the write barrier cannot be allowed to
1278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // destroy the cp register).
1279589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return ContextOperand(context, var->index());
128059151504615d929945dc59db37bf1166937748c6Steve Block}
128159151504615d929945dc59db37bf1166937748c6Steve Block
128259151504615d929945dc59db37bf1166937748c6Steve Block
1283589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
1284589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                  TypeofState typeof_state,
1285589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                  Label* slow,
1286589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                  Label* done) {
128759151504615d929945dc59db37bf1166937748c6Steve Block  // Generate fast-case code for variables that might be shadowed by
128859151504615d929945dc59db37bf1166937748c6Steve Block  // eval-introduced variables.  Eval is used a lot without
128959151504615d929945dc59db37bf1166937748c6Steve Block  // introducing variables.  In those cases, we do not want to
129059151504615d929945dc59db37bf1166937748c6Steve Block  // perform a runtime call for all variables in the scope
129159151504615d929945dc59db37bf1166937748c6Steve Block  // containing the eval.
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (var->mode() == DYNAMIC_GLOBAL) {
1293589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
129459151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(done);
12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (var->mode() == DYNAMIC_LOCAL) {
1296589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Variable* local = var->local_if_not_shadowed();
1297589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow));
12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (local->mode() == CONST ||
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        local->mode() == CONST_HARMONY ||
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        local->mode() == LET) {
1301589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (local->mode() == CONST) {
13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {  // LET || CONST_HARMONY
13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ b(ne, done);
13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(r0, Operand(var->name()));
13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ push(r0);
13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CallRuntime(Runtime::kThrowReferenceError, 1);
13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
131059151504615d929945dc59db37bf1166937748c6Steve Block    }
1311589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ jmp(done);
131259151504615d929945dc59db37bf1166937748c6Steve Block  }
131359151504615d929945dc59db37bf1166937748c6Steve Block}
131459151504615d929945dc59db37bf1166937748c6Steve Block
131559151504615d929945dc59db37bf1166937748c6Steve Block
13163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
13173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Record position before possible IC call.
13183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SetSourcePosition(proxy->position());
13193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Variable* var = proxy->var();
13203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1321589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Three cases: global variables, lookup variables, and all other types of
1322589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // variables.
1323589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (var->location()) {
1324589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::UNALLOCATED: {
1325589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Comment cmnt(masm_, "Global variable");
1326589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Use inline caching. Variable name is passed in r2 and the global
1327589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // object (receiver) in r0.
1328589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ ldr(r0, GlobalObjectOperand());
1329589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(r2, Operand(var->name()));
1330589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
13313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
1332589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      context()->Plug(r0);
1333589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1334589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
133559151504615d929945dc59db37bf1166937748c6Steve Block
1336589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::PARAMETER:
1337589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOCAL:
1338589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::CONTEXT: {
1339589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Comment cmnt(masm_, var->IsContextSlot()
1340589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                              ? "Context variable"
1341589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                              : "Stack variable");
13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (var->binding_needs_init()) {
13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // var->scope() may be NULL when the proxy is located in eval code and
13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // refers to a potential outside binding. Currently those bindings are
13453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // always looked up dynamically, i.e. in that case
13463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //     var->location() == LOOKUP.
13473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // always holds.
13483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(var->scope() != NULL);
13493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Check if the binding really needs an initialization check. The check
13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // can be skipped in the following situation: we have a LET or CONST
13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // binding in harmony mode, both the Variable and the VariableProxy have
13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // the same declaration scope (i.e. they are both in global code, in the
13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // same function or in the same eval code) and the VariableProxy is in
13553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // the source physically located after the initializer of the variable.
13563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
13573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We cannot skip any initialization checks for CONST in non-harmony
13583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // mode because const variables may be declared but never initialized:
13593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //   if (false) { const x; }; var y = x;
13603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
13613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The condition on the declaration scopes is a conservative check for
13623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // nested functions that access a binding and are called before the
13633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // binding is initialized:
13643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //   function() { f(); let x = 1; function f() { x = 2; } }
13653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
13663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bool skip_init_check;
13673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          skip_init_check = false;
1369589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        } else {
13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Check that we always have valid source position.
13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ASSERT(proxy->position() != RelocInfo::kNoPosition);
13733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          skip_init_check = var->mode() != CONST &&
13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              var->initializer_position() < proxy->position();
13753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!skip_init_check) {
13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Let and const need a read barrier.
13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          GetVar(r0, var);
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (var->mode() == LET || var->mode() == CONST_HARMONY) {
13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // Throw a reference error when using an uninitialized let/const
13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // binding in harmony mode.
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Label done;
13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ b(ne, &done);
13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ mov(r0, Operand(var->name()));
13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ push(r0);
13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ CallRuntime(Runtime::kThrowReferenceError, 1);
13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ bind(&done);
13903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else {
13913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // Uninitalized const bindings outside of harmony mode are unholed.
13923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ASSERT(var->mode() == CONST);
13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
13943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          context()->Plug(r0);
13963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          break;
1397589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        }
1398589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      context()->Plug(var);
1400589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1401589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
1402d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1403589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOOKUP: {
1404589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Label done, slow;
1405589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Generate code for loading from variables potentially shadowed
1406589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // by eval-introduced variables.
1407589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
1408589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ bind(&slow);
1409589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Comment cmnt(masm_, "Lookup variable");
1410589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(r1, Operand(var->name()));
1411589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ Push(cp, r1);  // Context and name.
1412589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CallRuntime(Runtime::kLoadContextSlot, 2);
141369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ bind(&done);
141469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      context()->Plug(r0);
14150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
14163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
14173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
14183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1420d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ RegExpLiteral");
1422bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label materialized;
14233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Registers will be used as follows:
1424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // r5 = materialized value (RegExp literal)
14253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r4 = JS function, literals array
14263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r3 = literal index
14273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r2 = RegExp pattern
14283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r1 = RegExp flags
1429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // r0 = RegExp literal clone
143080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
143180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
14323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int literal_offset =
143380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(r5, FieldMemOperand(r4, literal_offset));
14353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(r5, ip);
1437bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(ne, &materialized);
143880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
143980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Create regexp literal using runtime function.
144080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Result will be in r0.
14413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r3, Operand(Smi::FromInt(expr->literal_index())));
14423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r2, Operand(expr->pattern()));
14433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r1, Operand(expr->flags()));
14446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(r4, r3, r2, r1);
14453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ mov(r5, r0);
144780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1448bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&materialized);
1449bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Label allocated, runtime_allocate;
1451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ AllocateInNewSpace(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT);
1452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ jmp(&allocated);
1453e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&runtime_allocate);
1455e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(r5);
1456bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(r0, Operand(Smi::FromInt(size)));
1457bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(r0);
1458bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1459e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ pop(r5);
146080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1461e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&allocated);
1462bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // After this, registers are used as follows:
1463bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // r0: Newly allocated regexp.
1464e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // r5: Materialized regexp.
1465bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // r2: temp.
1466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CopyFields(r0, r5, r2.bit(), size / kPointerSize);
14670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
1468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAccessor(Expression* expression) {
14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expression == NULL) {
14733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(r1, Heap::kNullValueRootIndex);
14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r1);
14753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForStackValue(expression);
14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1481d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1482d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> constant_properties = expr->constant_properties();
14846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r3, MemOperand(fp,  JavaScriptFrameConstants::kFunctionOffset));
14856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
14866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r1, Operand(constant_properties));
148844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int flags = expr->fast_elements()
148944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? ObjectLiteral::kFastElements
149044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : ObjectLiteral::kNoFlags;
149144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  flags |= expr->has_function()
149244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? ObjectLiteral::kHasFunction
149344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : ObjectLiteral::kNoFlags;
149444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(r0, Operand(Smi::FromInt(flags)));
14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(r3, r2, r1, r0);
14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int properties_count = constant_properties->length() / 2;
1497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->depth() > 1) {
14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (flags != ObjectLiteral::kFastElements ||
15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
150185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastCloneShallowObjectStub stub(properties_count);
15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
1505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
1508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in r0.
1509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
1510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
15113e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Mark all computed expressions that are bound to a key that
15123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // is shadowed by a later occurrence of the same key. For the
15133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // marked expressions, no store code is emitted.
15143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  expr->CalculateEmitStore();
15153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AccessorTable accessor_table(isolate()->zone());
1517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < expr->properties()->length(); i++) {
1518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectLiteral::Property* property = expr->properties()->at(i);
1519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
1520d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = property->key();
1522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
1523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
1524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ push(r0);  // Save result on stack
1525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
1526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
1528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::CONSTANT:
1529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        UNREACHABLE();
1530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value()));
1532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
1534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (key->handle()->IsSymbol()) {
15353e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          if (property->emit_store()) {
1536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            VisitForAccumulatorValue(value);
1537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            __ mov(r2, Operand(key->handle()));
1538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            __ ldr(r1, MemOperand(sp));
15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<Code> ic = is_classic_mode()
15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                ? isolate()->builtins()->StoreIC_Initialize()
15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                : isolate()->builtins()->StoreIC_Initialize_Strict();
15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            CallIC(ic, RelocInfo::CODE_TARGET, key->id());
1543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            PrepareForBailoutForId(key->id(), NO_REGISTERS);
1544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else {
1545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            VisitForEffect(value);
15463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          }
1547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Fall through.
1550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::PROTOTYPE:
1551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Duplicate receiver on stack.
1552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ ldr(r0, MemOperand(sp));
1553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(r0);
15540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(key);
15550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(value);
15563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        if (property->emit_store()) {
1557e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ mov(r0, Operand(Smi::FromInt(NONE)));  // PropertyAttributes
1558e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(r0);
1559e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ CallRuntime(Runtime::kSetProperty, 4);
15603e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        } else {
15613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          __ Drop(3);
15623e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        }
1563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::GETTER:
15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        accessor_table.lookup(key)->second->getter = value;
15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
1567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::SETTER:
15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        accessor_table.lookup(key)->second->setter = value;
1569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Emit code to define accessors, using only a single call to the runtime for
15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // each pair of corresponding getters and setters.
15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (AccessorTable::Iterator it = accessor_table.begin();
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       it != accessor_table.end();
15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       ++it) {
15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, MemOperand(sp));  // Duplicate receiver.
15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);
15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForStackValue(it->first);
15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAccessor(it->second->getter);
15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAccessor(it->second->setter);
15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r0, Operand(Smi::FromInt(NONE)));
15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);
15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
158844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (expr->has_function()) {
158944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(result_saved);
159044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ ldr(r0, MemOperand(sp));
159144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ push(r0);
159244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
159344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
159444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
15960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
15980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
15993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
16003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1603d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
16043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
1605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<Expression*>* subexprs = expr->values();
1607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int length = subexprs->length();
16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> constant_elements = expr->constant_elements();
16093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(2, constant_elements->length());
16103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsKind constant_elements_kind =
16113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
16123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_fast_elements = constant_elements_kind == FAST_ELEMENTS;
16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArrayBase> constant_elements_values(
16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FixedArrayBase::cast(constant_elements->get(1)));
1615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
16163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
16173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
16183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r1, Operand(constant_elements));
16206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(r3, r2, r1);
16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (has_fast_elements && constant_elements_values->map() ==
162244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->heap()->fixed_cow_array_map()) {
1623756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    FastCloneShallowArrayStub stub(
1624756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
1625756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
162644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ IncrementCounter(
162744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate()->counters()->cow_arrays_created_stub(), 1, r1, r2);
1628756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (expr->depth() > 1) {
1629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
1630756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
1631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
1632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
16333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(constant_elements_kind == FAST_ELEMENTS ||
16343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           constant_elements_kind == FAST_SMI_ONLY_ELEMENTS ||
16353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FLAG_smi_only_arrays);
16363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastCloneShallowArrayStub::Mode mode = has_fast_elements
16373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? FastCloneShallowArrayStub::CLONE_ELEMENTS
16383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS;
16393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastCloneShallowArrayStub stub(mode, length);
1640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
16413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
16423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
16443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
16463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
1647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < length; i++) {
16483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Expression* subexpr = subexprs->at(i);
16493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
16503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
16513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (subexpr->AsLiteral() != NULL ||
16523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        CompileTimeValue::IsCompileTimeValue(subexpr)) {
16533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      continue;
16543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
16553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
16573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(r0);
16583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
16593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
16600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(subexpr);
16613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (constant_elements_kind == FAST_ELEMENTS) {
16633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int offset = FixedArray::kHeaderSize + (i * kPointerSize);
16643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r6, MemOperand(sp));  // Copy of array literal.
16653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r1, FieldMemOperand(r6, JSObject::kElementsOffset));
16663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(result_register(), FieldMemOperand(r1, offset));
16673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Update the write barrier for the array store.
16683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWriteField(r1, offset, result_register(), r2,
16693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          kLRHasBeenSaved, kDontSaveFPRegs,
16703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          EMIT_REMEMBERED_SET, INLINE_SMI_CHECK);
16713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
16723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r1, MemOperand(sp));  // Copy of array literal.
16733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r2, FieldMemOperand(r1, JSObject::kMapOffset));
16743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(r3, Operand(Smi::FromInt(i)));
16753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(r4, Operand(Smi::FromInt(expr->literal_index())));
16763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StoreArrayLiteralElementStub stub;
16773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CallStub(&stub);
16783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
16813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
16823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
16840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
16860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
16873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
16883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1691402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1692402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Comment cmnt(masm_, "[ Assignment");
1693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // on the left-hand side.
1695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->target()->IsValidLeftHandSide()) {
1696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->target());
1697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1700402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Left-hand side can only be a property, a global or a (parameter or local)
17013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot.
1702402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1703402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LhsKind assign_type = VARIABLE;
170480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Property* property = expr->target()->AsProperty();
170580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (property != NULL) {
170680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    assign_type = (property->key()->IsPropertyName())
170780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? NAMED_PROPERTY
170880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : KEYED_PROPERTY;
1709402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1710402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1711402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate LHS expression.
1712402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1713402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1714402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Nothing to do here.
1715402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1716402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1717402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1718402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // We need the receiver both on the stack and in the accumulator.
17190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(property->obj());
1720402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1721402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
17220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
1723402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1724402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1725402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
172625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      if (expr->is_compound()) {
17273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->obj());
17283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForAccumulatorValue(property->key());
172925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        __ ldr(r1, MemOperand(sp, 0));
173025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        __ push(r0);
173125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      } else {
17323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->obj());
17333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->key());
173425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      }
1735402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1736402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1737402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
17388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // For compound assignments we need another deoptimization point after the
17398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // variable/property load.
1740402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
17410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    { AccumulatorValueContext context(this);
17420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
17430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
17443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          EmitVariableLoad(expr->target()->AsVariableProxy());
17458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          PrepareForBailout(expr->target(), TOS_REG);
17460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
17470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
17480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitNamedPropertyLoad(property);
17498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
17500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
17510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
17520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitKeyedPropertyLoad(property);
17538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
17540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
17550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
1756402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1757402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
175880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Token::Value op = expr->binary_op();
1759e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ push(r0);  // Left operand goes on the stack.
1760e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    VisitForAccumulatorValue(expr->value());
1761402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
176280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
176380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? OVERWRITE_RIGHT
176480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : NO_OVERWRITE;
176580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    SetSourcePosition(expr->position() + 1);
17660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
176780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (ShouldInlineSmiCase(op)) {
1768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitInlineSmiBinaryOp(expr->binary_operation(),
176980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            op,
177080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            mode,
177180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            expr->target(),
1772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                            expr->value());
177380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    } else {
1774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitBinaryOp(expr->binary_operation(), op, mode);
177580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
1776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Deoptimization point in case the binary operation may have side effects.
1778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailout(expr->binary_operation(), TOS_REG);
177980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
17800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->value());
1781402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1782402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1783402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Record source position before possible IC call.
1784402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  SetSourcePosition(expr->position());
1785402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1786402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Store the value.
1787402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1788402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1789402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
17900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             expr->op());
1791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      context()->Plug(r0);
1793402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1794402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1795402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitNamedPropertyAssignment(expr);
1796402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1797402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1798402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitKeyedPropertyAssignment(expr);
1799402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1800402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1801402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1802402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1803402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1804d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1805e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1806e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Literal* key = prop->key()->AsLiteral();
1807e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(r2, Operand(key->handle()));
1808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call load IC. It has arguments receiver and property name r0 and r2.
180944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
18103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(ic, RelocInfo::CODE_TARGET, prop->id());
1811e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1814d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
181625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Call keyed load IC. It has arguments key and receiver in r0 and r1.
181744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
18183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(ic, RelocInfo::CODE_TARGET, prop->id());
1819e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
182380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Token::Value op,
182480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              OverwriteMode mode,
1825e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              Expression* left_expr,
1826e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              Expression* right_expr) {
1827e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Label done, smi_case, stub_call;
1828e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1829e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register scratch1 = r2;
1830e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register scratch2 = r3;
1831e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1832e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Get the arguments.
1833e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register left = r1;
1834e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register right = r0;
1835e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ pop(left);
1836e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Perform combined smi check on both operands.
1838e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ orr(scratch1, left, Operand(right));
1839e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1840e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  JumpPatchSite patch_site(masm_);
1841e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  patch_site.EmitJumpIfSmi(scratch1, &smi_case);
1842e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1843e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&stub_call);
1844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpStub stub(op, mode);
18453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
18463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
1847e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ jmp(&done);
1848e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1849e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&smi_case);
1850e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Smi case. This code works the same way as the smi-smi case in the type
1851e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // recording binary operation stub, see
1852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // BinaryOpStub::GenerateSmiSmiOperation for comments.
1853e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  switch (op) {
1854e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::SAR:
1855e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(&stub_call);
1856e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ GetLeastBitsFromSmi(scratch1, right, 5);
1857e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(right, Operand(left, ASR, scratch1));
1858e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ bic(right, right, Operand(kSmiTagMask));
1859e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1860e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::SHL: {
1861e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(&stub_call);
1862e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ SmiUntag(scratch1, left);
1863e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ GetLeastBitsFromSmi(scratch2, right, 5);
1864e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(scratch1, Operand(scratch1, LSL, scratch2));
1865e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ add(scratch2, scratch1, Operand(0x40000000), SetCC);
1866e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(mi, &stub_call);
1867e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ SmiTag(right, scratch1);
1868e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1869e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1870e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::SHR: {
1871e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(&stub_call);
1872e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ SmiUntag(scratch1, left);
1873e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ GetLeastBitsFromSmi(scratch2, right, 5);
1874e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(scratch1, Operand(scratch1, LSR, scratch2));
1875e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ tst(scratch1, Operand(0xc0000000));
1876e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(ne, &stub_call);
1877e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ SmiTag(right, scratch1);
1878e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1879e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1880e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::ADD:
1881e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ add(scratch1, left, Operand(right), SetCC);
1882e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(vs, &stub_call);
1883e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(right, scratch1);
1884e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1885e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::SUB:
1886e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ sub(scratch1, left, Operand(right), SetCC);
1887e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(vs, &stub_call);
1888e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(right, scratch1);
1889e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1890e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::MUL: {
1891e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ SmiUntag(ip, right);
1892e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ smull(scratch1, scratch2, left, ip);
1893e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(ip, Operand(scratch1, ASR, 31));
1894e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ cmp(ip, Operand(scratch2));
1895e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(ne, &stub_call);
18963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(scratch1, Operand(0));
1897e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(right, Operand(scratch1), LeaveCC, ne);
1898e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(ne, &done);
1899e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ add(scratch2, right, Operand(left), SetCC);
1900e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ mov(right, Operand(Smi::FromInt(0)), LeaveCC, pl);
1901e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ b(mi, &stub_call);
1902e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1904e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::BIT_OR:
1905e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ orr(right, left, Operand(right));
1906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::BIT_AND:
1908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ and_(right, left, Operand(right));
1909e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1910e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::BIT_XOR:
1911e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ eor(right, left, Operand(right));
1912e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1913e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    default:
1914e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      UNREACHABLE();
1915e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1916e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1917e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&done);
1918e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  context()->Plug(r0);
191980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
192080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
192180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
1923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Token::Value op,
192480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                     OverwriteMode mode) {
1925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(r1);
1926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpStub stub(op, mode);
19273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
19283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
19293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
19300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
1931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1933e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
19343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr) {
1935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw
1936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ReferenceError' on the left-hand side.
1937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->IsValidLeftHandSide()) {
1938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr);
1939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand side can only be a property, a global or a (parameter or local)
19433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot.
1944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  LhsKind assign_type = VARIABLE;
1946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = expr->AsProperty();
1947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (prop != NULL) {
1948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    assign_type = (prop->key()->IsPropertyName())
1949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ? NAMED_PROPERTY
1950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        : KEYED_PROPERTY;
1951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (assign_type) {
1954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case VARIABLE: {
1955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->AsVariableProxy()->var();
19560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EffectContext context(this);
19570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitVariableAssignment(var, Token::ASSIGN);
1958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case NAMED_PROPERTY: {
1961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(r0);  // Preserve value.
19620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
1963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(r1, r0);
1964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r0);  // Restore value.
1965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
19663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> ic = is_classic_mode()
19673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? isolate()->builtins()->StoreIC_Initialize()
19683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          : isolate()->builtins()->StoreIC_Initialize_Strict();
19693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallIC(ic);
1970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case KEYED_PROPERTY: {
1973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(r0);  // Preserve value.
19743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForStackValue(prop->obj());
19753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForAccumulatorValue(prop->key());
19763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ mov(r1, r0);
19773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ pop(r2);
1978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r0);  // Restore value.
19793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> ic = is_classic_mode()
19803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? isolate()->builtins()->KeyedStoreIC_Initialize()
19813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
19823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallIC(ic);
1983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(r0);
1987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1990d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var,
19910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                               Token::Value op) {
1992589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsUnallocated()) {
1993589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Global var, const, or let.
19943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(r2, Operand(var->name()));
19958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r1, GlobalObjectOperand());
19963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic = is_classic_mode()
19973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ? isolate()->builtins()->StoreIC_Initialize()
19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : isolate()->builtins()->StoreIC_Initialize_Strict();
19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
2000d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2001e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (op == Token::INIT_CONST) {
2002589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Const initializers need a write barrier.
2003589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ASSERT(!var->IsParameter());  // No const parameters.
2004589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (var->IsStackLocal()) {
2005589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Label skip;
2006589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ ldr(r1, StackOperand(var));
2007589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CompareRoot(r1, Heap::kTheHoleValueRootIndex);
2008589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ b(ne, &skip);
2009589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ str(result_register(), StackOperand(var));
2010589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ bind(&skip);
2011589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else {
2012589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ASSERT(var->IsContextSlot() || var->IsLookupSlot());
2013589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Like var declarations, const declarations are hoisted to function
2014589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // scope.  However, unlike var initializers, const initializers are
2015589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // able to drill a hole to that function context, even from inside a
2016589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // 'with' context.  We thus bypass the normal static scope lookup for
2017589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // var->IsContextSlot().
2018589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(r0);
2019589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(r0, Operand(var->name()));
2020589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ Push(cp, r0);  // Context and name.
2021589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
2022e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2023e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
20243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (var->mode() == LET && op != Token::INIT_LET) {
2025589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Non-initializing assignment to let variable needs a write barrier.
2026589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (var->IsLookupSlot()) {
2027589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(r0);  // Value.
2028589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(r1, Operand(var->name()));
20293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(r0, Operand(Smi::FromInt(language_mode())));
2030589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ Push(cp, r1, r0);  // Context, name, strict mode.
2031589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CallRuntime(Runtime::kStoreContextSlot, 4);
2032589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else {
2033589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2034589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Label assign;
2035589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      MemOperand location = VarOperand(var, r1);
2036589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ ldr(r3, location);
2037589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
2038589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ b(ne, &assign);
2039589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(r3, Operand(var->name()));
2040589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(r3);
2041589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CallRuntime(Runtime::kThrowReferenceError, 1);
2042589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Perform the assignment.
2043589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ bind(&assign);
2044589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ str(result_register(), location);
2045589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (var->IsContextSlot()) {
204669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // RecordWrite may destroy all its register arguments.
204769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ mov(r3, result_register());
2048589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        int offset = Context::SlotOffset(var->index());
20493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ RecordWriteContextSlot(
20503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs);
205169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
205269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
205369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
20543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
20553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Assignment to var or initializing assignment to let/const
20563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // in harmony mode.
2057589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (var->IsStackAllocated() || var->IsContextSlot()) {
2058589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      MemOperand location = VarOperand(var, r1);
2059589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (FLAG_debug_code && op == Token::INIT_LET) {
2060589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // Check for an uninitialized let binding.
2061589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ ldr(r2, location);
2062589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
2063589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ Check(eq, "Let binding re-initialization.");
20643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
2065589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Perform the assignment.
2066589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ str(r0, location);
2067589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (var->IsContextSlot()) {
2068589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ mov(r3, r0);
20693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int offset = Context::SlotOffset(var->index());
20703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ RecordWriteContextSlot(
20713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs);
2072589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
2073589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else {
2074589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ASSERT(var->IsLookupSlot());
2075589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(r0);  // Value.
2076589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(r1, Operand(var->name()));
20773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(r0, Operand(Smi::FromInt(language_mode())));
2078589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ Push(cp, r1, r0);  // Context, name, strict mode.
2079589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CallRuntime(Runtime::kStoreContextSlot, 4);
20803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
20813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2082589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Non-initializing assignments to consts are ignored.
20833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
20843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2086d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2087d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
2088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
2089d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop != NULL);
2090d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop->key()->AsLiteral() != NULL);
20913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2092d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
2093d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
2094d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
2095d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
2096e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
2097e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ ldr(ip, MemOperand(sp, kPointerSize));  // Receiver is now under value.
2098d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(ip);
2099d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
2100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
2101d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2102d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
2104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
2105d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
2106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load receiver to r1. Leave a copy in the stack if needed for turning the
2107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // receiver into fast case.
2108402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->ends_initialization_block()) {
2109402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ ldr(r1, MemOperand(sp));
2110402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  } else {
2111402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop(r1);
2112402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
2113402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
21143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic = is_classic_mode()
21153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? isolate()->builtins()->StoreIC_Initialize()
21163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : isolate()->builtins()->StoreIC_Initialize_Strict();
21173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
2118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2119d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
2120d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
2121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(r0);  // Result of assignment, saved even if not needed.
2122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Receiver is under the result value.
2123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(ip, MemOperand(sp, kPointerSize));
2124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(ip);
2125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
2126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(r0);
2127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ Drop(1);
2128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(r0);
2131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2134d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
2136d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
2138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
2139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
2140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
2141e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
2142e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Receiver is now under the key and value.
2143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(ip, MemOperand(sp, 2 * kPointerSize));
2144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(ip);
2145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
2146e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
2147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2149e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
2150e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r1);  // Key.
2152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load receiver to r2. Leave a copy in the stack if needed for turning the
2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // receiver into fast case.
2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (expr->ends_initialization_block()) {
2155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(r2, MemOperand(sp));
2156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
2157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ pop(r2);
2158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic = is_classic_mode()
21613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? isolate()->builtins()->KeyedStoreIC_Initialize()
21623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
21633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
2164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
2166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
2167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(r0);  // Result of assignment, saved even if not needed.
2168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Receiver is under the result value.
2169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(ip, MemOperand(sp, kPointerSize));
2170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(ip);
2171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
2172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(r0);
2173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ Drop(1);
2174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(r0);
2177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2180d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) {
2181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Property");
2182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* key = expr->key();
2183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2184e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (key->IsPropertyName()) {
21850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->obj());
2186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitNamedPropertyLoad(expr);
2187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    context()->Plug(r0);
2188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
21890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(expr->obj());
21900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->key());
219125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ pop(r1);
2192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitKeyedPropertyLoad(expr);
2193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    context()->Plug(r0);
2194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
21973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::CallIC(Handle<Code> code,
21993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               RelocInfo::Mode rmode,
22003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               unsigned ast_id) {
22013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ic_total_count_++;
22023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Call(code, rmode, ast_id);
22033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2205d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr,
2206402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                       Handle<Object> name,
2207e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       RelocInfo::Mode mode) {
2208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the IC.
2209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
22103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
2211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { PreservePositionScope scope(masm()->positions_recorder());
22123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
22133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
22143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
22153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    __ mov(r2, Operand(name));
22163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
2218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
22193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the IC initialization code.
222044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic =
2221589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
22223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(ic, mode, expr->id());
2223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RecordJSReturnSite(expr);
2224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Restore context register.
2225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
22260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
22309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Expression* key) {
22328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the key.
22338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForAccumulatorValue(key);
22348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
22358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Swap the name of the function and the receiver on the stack to follow
22368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // the calling convention for call ICs.
22378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ pop(r1);
22388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(r0);
22398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(r1);
22408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
22419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Code common for calls using the IC.
22429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ZoneList<Expression*>* args = expr->arguments();
22439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  int arg_count = args->length();
2244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { PreservePositionScope scope(masm()->positions_recorder());
22453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
22463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
22473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
22489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
22499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Record source position for debugger.
2250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
22519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Call the IC initialization code.
225244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic =
2253589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
22548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize));  // Key.
22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
2256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RecordJSReturnSite(expr);
22579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Restore context register.
22589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
22598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  context()->DropAndPlug(1, r0);  // Drop the key still on the stack.
22609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
22619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
22629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
2264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the call stub.
2265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
2267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { PreservePositionScope scope(masm()->positions_recorder());
22683e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
22693e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
22703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
2273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
2274589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  CallFunctionStub stub(arg_count, flags);
22753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ CallStub(&stub);
2277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RecordJSReturnSite(expr);
22783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore context register.
22793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
22800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->DropAndPlug(1, r0);
2281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
22843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Push copy of the first argument or undefined if it doesn't exist.
2286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (arg_count > 0) {
2287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
2288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
2289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
2290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(r1);
2292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
22933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the receiver of the enclosing function.
22943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int receiver_offset = 2 + info_->scope()->num_parameters();
22953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ldr(r1, MemOperand(fp, receiver_offset * kPointerSize));
2296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(r1);
22973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the language mode.
22983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r1, Operand(Smi::FromInt(language_mode())));
2299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(r1);
2300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the start position of the scope the calls resides in.
23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r1, Operand(Smi::FromInt(scope()->start_position())));
23033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(r1);
23043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do the runtime call.
23063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
2307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2310d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) {
2311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
2312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We want to verify that RecordJSReturnSite gets called on all paths
2313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // through this function.  Avoid early returns.
2314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->return_is_recorded_ = false;
2315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
2316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Call");
2318589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Expression* callee = expr->expression();
2319589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  VariableProxy* proxy = callee->AsVariableProxy();
2320589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Property* property = callee->AsProperty();
2321d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2322589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (proxy != NULL && proxy->var()->is_possibly_eval()) {
2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // In a call to eval, we first call %ResolvePossiblyDirectEval to
2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // resolve the function we need to call and the receiver of the
2325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // call.  Then we call the resolved function using the given
2326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // arguments.
2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    ZoneList<Expression*>* args = expr->arguments();
2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    int arg_count = args->length();
2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope pos_scope(masm()->positions_recorder());
2331589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VisitForStackValue(callee);
23323e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
23333e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ push(r2);  // Reserved receiver slot.
2334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23353e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Push the arguments.
23363e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      for (int i = 0; i < arg_count; i++) {
23373e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        VisitForStackValue(args->at(i));
23383e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      }
23393e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
2340589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Push a copy of the function (found below the arguments) and
2341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // resolve eval.
2342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
23431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ push(r1);
23443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitResolvePossiblyDirectEval(arg_count);
23453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
23463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // The runtime call returns a pair of values in r0 (function) and
23473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // r1 (receiver). Touch up the stack with the right values.
23483e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
23493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ str(r1, MemOperand(sp, arg_count * kPointerSize));
23503e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Record source position for debugger.
2353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetSourcePosition(expr->position());
2354589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT);
23553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
2357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    RecordJSReturnSite(expr);
2358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Restore context register.
2359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
23600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->DropAndPlug(1, r0);
2361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
2362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Push global object as receiver for the call IC.
23638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r0, GlobalObjectOperand());
2364402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(r0);
2365589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
2366589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
236759151504615d929945dc59db37bf1166937748c6Steve Block    // Call to a lookup slot (dynamically introduced variable).
236859151504615d929945dc59db37bf1166937748c6Steve Block    Label slow, done;
236959151504615d929945dc59db37bf1166937748c6Steve Block
2370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope scope(masm()->positions_recorder());
23713e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Generate code for loading from variables potentially shadowed
23723e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // by eval-introduced variables.
2373589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
23743e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
237559151504615d929945dc59db37bf1166937748c6Steve Block
237659151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
23770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Call the runtime to find the function to call (returned in r0)
237859151504615d929945dc59db37bf1166937748c6Steve Block    // and the object holding it (returned in edx).
2379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(context_register());
2380589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ mov(r2, Operand(proxy->name()));
2381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(r2);
2382f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
238359151504615d929945dc59db37bf1166937748c6Steve Block    __ Push(r0, r1);  // Function, receiver.
238459151504615d929945dc59db37bf1166937748c6Steve Block
238559151504615d929945dc59db37bf1166937748c6Steve Block    // If fast case code has been generated, emit code to push the
238659151504615d929945dc59db37bf1166937748c6Steve Block    // function and receiver and have the slow path jump around this
238759151504615d929945dc59db37bf1166937748c6Steve Block    // code.
238859151504615d929945dc59db37bf1166937748c6Steve Block    if (done.is_linked()) {
238959151504615d929945dc59db37bf1166937748c6Steve Block      Label call;
239059151504615d929945dc59db37bf1166937748c6Steve Block      __ b(&call);
239159151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&done);
239259151504615d929945dc59db37bf1166937748c6Steve Block      // Push function.
239359151504615d929945dc59db37bf1166937748c6Steve Block      __ push(r0);
23943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // The receiver is implicitly the global receiver. Indicate this
23953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // by passing the hole to the call function stub.
23963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ LoadRoot(r1, Heap::kTheHoleValueRootIndex);
239759151504615d929945dc59db37bf1166937748c6Steve Block      __ push(r1);
239859151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&call);
239959151504615d929945dc59db37bf1166937748c6Steve Block    }
240059151504615d929945dc59db37bf1166937748c6Steve Block
2401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The receiver is either the global receiver or an object found
2402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // by LoadContextSlot. That object could be the hole if the
2403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // receiver is implicitly the global object.
2404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT);
2405589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (property != NULL) {
2406589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    { PreservePositionScope scope(masm()->positions_recorder());
2407589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VisitForStackValue(property->obj());
2408589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
2409589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (property->key()->IsPropertyName()) {
2410589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      EmitCallWithIC(expr,
2411589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     property->key()->AsLiteral()->handle(),
2412589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     RelocInfo::CODE_TARGET);
2413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
2414589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      EmitKeyedCallWithIC(expr, property->key());
2415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
24163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2417589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Call to an arbitrary expression not handled specially above.
2418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope scope(masm()->positions_recorder());
2419589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VisitForStackValue(callee);
24203e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load global receiver object.
24228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r1, GlobalObjectOperand());
2423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
2424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(r1);
2425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit function call.
2426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
24273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
2430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // RecordJSReturnSite should have been called.
2431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(expr->return_is_recorded_);
2432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
24333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
24343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
24353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2436d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
2437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
2438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
2439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
2440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
244180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
244280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Push constructor on the stack.  If it's not a function it's used as
244380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
244480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ignored.
24450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->expression());
2446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
2448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2449d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
2450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
24510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
2452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
2455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
2456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
2457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
245880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load function and argument count into r1 and r0.
2459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(r0, Operand(arg_count));
246080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
2461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
24623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Record call targets in unoptimized code, but not in the snapshot.
24633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallFunctionFlags flags;
24643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!Serializer::enabled()) {
24653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    flags = RECORD_CALL_TARGET;
24663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> uninitialized =
24673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        TypeFeedbackCells::UninitializedSentinel(isolate());
24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell =
24693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RecordTypeFeedbackCell(expr->id(), cell);
24713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r2, Operand(cell));
24723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
24733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    flags = NO_CALL_FUNCTION_FLAGS;
24743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
24753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallConstructStub stub(flags);
24773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
24783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
24790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2480d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2481d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2482d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
24833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
24843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
249280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ tst(r0, Operand(kSmiTagMask));
2498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Split(eq, if_true, if_false, fall_through);
2499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
25053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
251380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
25150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ tst(r0, Operand(kSmiTagMask | 0x80000000));
251980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
2520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
25263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
253480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
25360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
253780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
25381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, if_false);
2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(ip, Heap::kNullValueRootIndex);
2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, ip);
2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, if_true);
2542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Undetectable objects behave like undefined when tested with typeof.
2544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
2545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ tst(r1, Operand(1 << Map::kIsUndetectable));
2546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, if_false);
2547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset));
25483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(lt, if_false);
25503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
25513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
255280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(le, if_true, if_false, fall_through);
2553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
25593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
25603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(args->length() == 1);
25613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
25633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label materialize_true, materialize_false;
25653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_true = NULL;
25663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_false = NULL;
256780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
25690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
25703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, if_false);
25723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
25733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
257480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(ge, if_true, if_false, fall_through);
25753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
25773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
25783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
25813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
258980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
25910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, if_false);
2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ tst(r1, Operand(1 << Map::kIsUndetectable));
25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
259880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(ne, if_true, if_false, fall_through);
2599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2604756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
26053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime* expr) {
26063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2607756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ASSERT(args->length() == 1);
2608756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
26090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2610756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2611756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label materialize_true, materialize_false;
2612756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_true = NULL;
2613756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_false = NULL;
261480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
26150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
26160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2617756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
26188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (FLAG_debug_code) __ AbortIfSmi(r0);
26198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
26208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
26218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldrb(ip, FieldMemOperand(r1, Map::kBitField2Offset));
26228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ tst(ip, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
26238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ b(ne, if_true);
26248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
26258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Check for fast case object. Generate false result for slow case object.
26268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r2, FieldMemOperand(r0, JSObject::kPropertiesOffset));
26278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
26288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
26298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ cmp(r2, ip);
26308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ b(eq, if_false);
26318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
26328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Look for valueOf symbol in the descriptor array, and indicate false if
26338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // found. The type is not checked, so if it is a transition it is a false
26348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // negative.
2635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadInstanceDescriptors(r1, r4);
26368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r3, FieldMemOperand(r4, FixedArray::kLengthOffset));
26378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // r4: descriptor array
26388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // r3: length of descriptor array
26398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Calculate the end of the descriptor array.
26408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
26418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  STATIC_ASSERT(kSmiTagSize == 1);
26428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  STATIC_ASSERT(kPointerSize == 4);
26438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ add(r2, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
26448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ add(r2, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
26458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
26468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Calculate location of the first key name.
26478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ add(r4,
26488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch         r4,
26498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch         Operand(FixedArray::kHeaderSize - kHeapObjectTag +
26508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                 DescriptorArray::kFirstIndex * kPointerSize));
26518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Loop through all the keys in the descriptor array. If one of these is the
26528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // symbol valueOf the result is false.
26538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Label entry, loop;
26548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // The use of ip to store the valueOf symbol asumes that it is not otherwise
26558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // used in the loop below.
26568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ mov(ip, Operand(FACTORY->value_of_symbol()));
26578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ jmp(&entry);
26588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ bind(&loop);
26598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r3, MemOperand(r4, 0));
26608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ cmp(r3, ip);
26618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ b(eq, if_false);
26628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ add(r4, r4, Operand(kPointerSize));
26638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ bind(&entry);
26648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ cmp(r4, Operand(r2));
26658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ b(ne, &loop);
26668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
26678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // If a valueOf property is not found on the object check that it's
26688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // prototype is the un-modified String prototype. If not result is false.
26698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r2, FieldMemOperand(r1, Map::kPrototypeOffset));
26703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(r2, if_false);
26718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
26728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r3, ContextOperand(cp, Context::GLOBAL_INDEX));
26738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r3, FieldMemOperand(r3, GlobalObject::kGlobalContextOffset));
26748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldr(r3, ContextOperand(r3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
26758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ cmp(r2, r3);
26768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ b(ne, if_false);
26778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
26788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Set the bit in the map to indicate that it has been checked safe for
26798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // default valueOf and set true result.
26808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ ldrb(r2, FieldMemOperand(r1, Map::kBitField2Offset));
26818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ orr(r2, r2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
26828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ strb(r2, FieldMemOperand(r1, Map::kBitField2Offset));
26838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ jmp(if_true);
26848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
26853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
26860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2687756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2688756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2689756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
26903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
26913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
269980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
27000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
27010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, if_false);
2704589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE);
27053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
270680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
2707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
27133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
272180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
27220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
27230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, if_false);
2726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
27273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
272880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
2729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
27353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2736f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
274380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
27440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
27450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, if_false);
2748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
27493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
275080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
2751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(expr->arguments()->length() == 0);
2759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
276380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
27640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
27650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the frame pointer for the calling frame.
2768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Skip the arguments adaptor frame if it exists.
2771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label check_frame_marker;
2772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset));
2773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &check_frame_marker);
2775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset));
2776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check the marker in the calling frame.
2778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&check_frame_marker);
2779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
2780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
27813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
278280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
2783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
27893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the two objects into registers and perform the comparison.
27930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
27940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
2795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
279980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
28000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
28010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r1);
2804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, r1);
28053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
280680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
2807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArguments(CallRuntime* expr) {
28133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ArgumentsAccessStub expects the key in edx and the formal
28170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // parameter count in r0.
28180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r1, r0);
28203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
2821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
28230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
28283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(expr->arguments()->length() == 0);
2829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label exit;
2830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the number of formal parameters.
28313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
2832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the calling frame is an arguments adaptor frame.
2834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
2836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &exit);
2838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Arguments adaptor case: Read the arguments length from the
2840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // adaptor frame.
2841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
2842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
28440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
28493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, null, function, non_function_constructor;
2852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, we return null.
28561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, &null);
2857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check that the object is a JS object but take special care of JS
2859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // functions to make sure they have 'Function' as their class.
28603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Assume that there are only two callable types, and one of them is at
28613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // either end of the type range for JS object types. Saves extra comparisons.
28623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
28633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CompareObjectType(r0, r0, r1, FIRST_SPEC_OBJECT_TYPE);
28643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Map is now in r0.
2865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(lt, &null);
28663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                FIRST_SPEC_OBJECT_TYPE + 1);
28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(eq, &function);
28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r1, Operand(LAST_SPEC_OBJECT_TYPE));
28713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
28723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                LAST_SPEC_OBJECT_TYPE - 1);
28733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(eq, &function);
28743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Assume that there is no larger type.
28753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
28763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the constructor in the map is a JS function.
2878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, Map::kConstructorOffset));
2879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
2880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &non_function_constructor);
2881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r0 now contains the constructor function. Grab the
2883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // instance class name from there.
2884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
2885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset));
2886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(&done);
2887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Functions have class 'Function'.
2889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&function);
2890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex);
2891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Objects with a non-function constructor have class 'Object'.
2894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&non_function_constructor);
289569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ LoadRoot(r0, Heap::kObject_symbolRootIndex);
2896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-JS objects have class null.
2899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&null);
2900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(r0, Heap::kNullValueRootIndex);
2901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // All done.
2903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLog(CallRuntime* expr) {
2910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Conditionally generate a log call.
2911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Args:
2912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   0 (literal string): The type of logging (corresponds to the flags).
2913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     This is used to determine whether or not to generate the log call.
2914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   1 (string): Format string.  Access the string at argument index 2
2915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     with '%2s' (see Logger::LogRuntime for all the formats).
2916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   2 (array): Arguments to the format string.
29173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 3);
2919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
29200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(1));
29210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(2));
2922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLog, 2);
2923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
29243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Finally, we're expected to leave a value on the top of the stack.
2926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
29270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
29323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(expr->arguments()->length() == 0);
2933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label slow_allocate_heapnumber;
2934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label heapnumber_allocated;
2935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
29379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber);
2938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&heapnumber_allocated);
2939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&slow_allocate_heapnumber);
29413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Allocate a heap number.
29423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CallRuntime(Runtime::kNumberAlloc, 0);
2943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r4, Operand(r0));
2944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&heapnumber_allocated);
2946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert 32 random bits in r0 to 0.(32 random bits) in a double
2948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // by computing:
2949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
29508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (CpuFeatures::IsSupported(VFP3)) {
29518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ PrepareCallCFunction(1, r0);
29523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, ContextOperand(context_register(), Context::GLOBAL_INDEX));
29533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset));
29548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
2955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CpuFeatures::Scope scope(VFP3);
2957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0x41300000 is the top half of 1.0 x 2^20 as a double.
2958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Create this constant using mov/orr to avoid PC relative load.
2959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r1, Operand(0x41000000));
2960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ orr(r1, r1, Operand(0x300000));
2961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Move 0x41300000xxxxxxxx (x = random bits) to VFP.
2962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ vmov(d7, r0, r1);
2963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Move 0x4130000000000000 to VFP.
29649ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    __ mov(r0, Operand(0, RelocInfo::NONE));
2965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ vmov(d8, r0, r1);
2966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Subtract and store the result in the heap number.
2967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ vsub(d7, d7, d8);
2968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ sub(r0, r4, Operand(kHeapObjectTag));
2969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ vstr(d7, r0, HeapNumber::kValueOffset);
2970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r0, r4);
2971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
29728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ PrepareCallCFunction(2, r0);
29733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r1, ContextOperand(context_register(), Context::GLOBAL_INDEX));
2974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r0, Operand(r4));
29753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalContextOffset));
2976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallCFunction(
29778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        ExternalReference::fill_heap_number_with_random_function(isolate()), 2);
2978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSubString(CallRuntime* expr) {
2985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SubStringStub stub;
29873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
29890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
29900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
29910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
2992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
29930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
2998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  RegExpExecStub stub;
30003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 4);
30020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
30030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
30040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
30050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(3));
3006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
30070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
30123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
30140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));  // Load the object.
3015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
3017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi return the object.
30181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, &done);
3019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the object.
3020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE);
3021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &done);
3022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
3023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
30250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitDateField(CallRuntime* expr) {
30303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(args->length() == 2);
30323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_NE(NULL, args->at(1)->AsLiteral());
30333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->handle()));
30343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitForAccumulatorValue(args->at(0));  // Load the object.
30363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label runtime, done;
30383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = r0;
30393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = r0;
30403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch0 = r9;
30413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch1 = r1;
30423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
30443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ AbortIfSmi(object);
30453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareObjectType(object, scratch1, scratch1, JS_DATE_TYPE);
30463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Assert(eq, "Trying to get date field from non-date.");
30473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
30483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (index->value() == 0) {
30503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
30513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
30523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (index->value() < JSDate::kFirstUncachedField) {
30533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
30543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(scratch1, Operand(stamp));
30553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(scratch1, MemOperand(scratch1));
30563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(scratch0, FieldMemOperand(object, JSDate::kCacheStampOffset));
30573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(scratch1, scratch0);
30583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ b(ne, &runtime);
30593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset +
30603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             kPointerSize * index->value()));
30613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&done);
30623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
30633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&runtime);
30643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ PrepareCallCFunction(2, scratch1);
30653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r1, Operand(index));
30663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&done);
30683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
30693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->Plug(r0);
30703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
30713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
3074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the runtime function.
30753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
30770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
30780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
30793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (CpuFeatures::IsSupported(VFP3)) {
30803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MathPowStub stub(MathPowStub::ON_STACK);
30813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
30823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
30833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kMath_pow, 2);
30843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
30850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
30903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
30920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));  // Load the object.
30930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));  // Load the value.
3094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r1);  // r0 = value. r1 = object.
3095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
3097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, return the value.
30981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r1, &done);
3099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the value.
3101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE);
3102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &done);
3103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Store the value.
3105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
3106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the write barrier.  Save the value as it will be
3107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // overwritten by the write barrier code and is needed afterward.
31083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r2, r0);
31093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWriteField(
31103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      r1, JSValue::kValueOffset, r2, r3, kLRHasBeenSaved, kDontSaveFPRegs);
3111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
31130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
31183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 1);
3120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
31210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
3122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  NumberToStringStub stub;
3124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
31250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
31303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
31320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
31357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharFromCodeGenerator generator(r0, r1);
31367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
31377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
3138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
31407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
3141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
31430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r1);
3144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
31483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
31497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
31500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
31510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
31527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = r1;
31547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = r0;
31557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = r3;
31567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
31587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
31607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
31617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
31627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharCodeAtGenerator generator(object,
31637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      index,
31647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      result,
31657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
31667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
31677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &index_out_of_range,
31687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      STRING_INDEX_IS_NUMBER);
31697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
31707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
31717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
31737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
31747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // NaN.
31757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kNanValueRootIndex);
31767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
31777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
31797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Load the undefined value into the result register, which will
31807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // trigger conversion.
31817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
31827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
31837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
31857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
31867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
31880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
31897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
31907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
31933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
31947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
31950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
31960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
31977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = r1;
31997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = r0;
32003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = r3;
32017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = r0;
32027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
32047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
32067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
32077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
32087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharAtGenerator generator(object,
32097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  index,
32103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  scratch,
32117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  result,
32127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
32137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
32147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &index_out_of_range,
32157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  STRING_INDEX_IS_NUMBER);
32167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
32177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
32187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
32207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
32217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the empty string.
32227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kEmptyStringRootIndex);
32237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
32247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
32267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move smi zero into the result register, which will trigger
32277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // conversion.
32287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(result, Operand(Smi::FromInt(0)));
32297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
32307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
32327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
32337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
32350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
3236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
32403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
32420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
32430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
3244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringAddStub stub(NO_STRING_ADD_FLAGS);
3246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
32470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
32523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
32540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
32550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
3256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringCompareStub stub;
3258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
32590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
3264e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Load the argument on the stack and call the stub.
3265e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  TranscendentalCacheStub stub(TranscendentalCache::SIN,
3266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               TranscendentalCacheStub::TAGGED);
32673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
32690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
3270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CallStub(&stub);
32710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
3276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Load the argument on the stack and call the stub.
3277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  TranscendentalCacheStub stub(TranscendentalCache::COS,
3278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               TranscendentalCacheStub::TAGGED);
32793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
32803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(args->length() == 1);
32813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitForStackValue(args->at(0));
32823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallStub(&stub);
32833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->Plug(r0);
32843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathTan(CallRuntime* expr) {
32883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the argument on the stack and call the stub.
32893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  TranscendentalCacheStub stub(TranscendentalCache::TAN,
32903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               TranscendentalCacheStub::TAGGED);
32913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
32930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
3294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CallStub(&stub);
32950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
3300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Load the argument on the stack and call the stub.
3301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  TranscendentalCacheStub stub(TranscendentalCache::LOG,
3302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               TranscendentalCacheStub::TAGGED);
33033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
33050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
3306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CallStub(&stub);
33070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
3312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the argument on the stack and call the runtime function.
33133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(args->length() == 1);
3315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForStackValue(args->at(0));
3316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CallRuntime(Runtime::kMath_sqrt, 1);
3317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(r0);
3318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
33213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
33223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() >= 2);
3324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int arg_count = args->length() - 2;  // 2 ~ receiver and function.
3326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < arg_count + 1; i++) {
3327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VisitForStackValue(args->at(i));
3328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  VisitForAccumulatorValue(args->last());  // Function.
3330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for proxy.
33323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label proxy, done;
33333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareObjectType(r0, r1, r1, JS_FUNCTION_PROXY_TYPE);
33343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(eq, &proxy);
33353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // InvokeFunction requires the function in r1. Move it in there.
3337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(r1, result_register());
3338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ParameterCount count(arg_count);
3339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(r1, count, CALL_FUNCTION,
3340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), CALL_AS_METHOD);
3341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
33423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&done);
33433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&proxy);
33453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(r0);
33463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallRuntime(Runtime::kCall, args->length());
33473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
33483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RegExpConstructResultStub stub;
33553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
33570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
33580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
33590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
3360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CallStub(&stub);
33610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
33663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
3368f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_NE(NULL, args->at(0)->AsLiteral());
3369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
3370f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<FixedArray> jsfunction_result_caches(
337244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->global_context()->jsfunction_result_caches());
3373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (jsfunction_result_caches->length() <= cache_id) {
3374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Abort("Attempt to use undefined cache.");
3375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
33760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
3377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
3381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3382f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register key = r0;
3383f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register cache = r1;
338459151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(cache, ContextOperand(cp, Context::GLOBAL_INDEX));
3385f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(cache, FieldMemOperand(cache, GlobalObject::kGlobalContextOffset));
338659151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
3387f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(cache,
3388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
3389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3390f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3391f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, not_found;
3392f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // tmp now holds finger offset as a smi.
339369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset));
3395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r2 now holds finger offset as a smi.
3396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r3 now points to the start of fixed array elements.
3398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2 - kSmiTagSize, PreIndex));
3399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Note side effect of PreIndex: r3 now points to the key of the pair.
3400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(key, r2);
3401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &not_found);
3402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3403f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, MemOperand(r3, kPointerSize));
3404f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(&done);
3405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&not_found);
3407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call runtime to perform the lookup.
3408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(cache, key);
3409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetFromCache, 2);
3410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
34120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
34163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
34173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3418bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT_EQ(2, args->length());
3419bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3420bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register right = r0;
3421bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register left = r1;
3422bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register tmp = r2;
3423bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register tmp2 = r3;
3424bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
34250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
34260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
3427bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(left);
3428bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3429bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label done, fail, ok;
3430bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(left, Operand(right));
3431bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(eq, &ok);
3432bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Fail if either is a non-HeapObject.
3433bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ and_(tmp, left, Operand(right));
34343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(tmp, &fail);
3435bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ldr(tmp, FieldMemOperand(left, HeapObject::kMapOffset));
3436bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ldrb(tmp2, FieldMemOperand(tmp, Map::kInstanceTypeOffset));
3437bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(tmp2, Operand(JS_REGEXP_TYPE));
3438bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(ne, &fail);
3439bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
3440bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(tmp, Operand(tmp2));
3441bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(ne, &fail);
3442bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ldr(tmp, FieldMemOperand(left, JSRegExp::kDataOffset));
3443bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ldr(tmp2, FieldMemOperand(right, JSRegExp::kDataOffset));
3444bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(tmp, tmp2);
3445bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(eq, &ok);
3446bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&fail);
3447bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ LoadRoot(r0, Heap::kFalseValueRootIndex);
3448bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ jmp(&done);
3449bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&ok);
3450bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ LoadRoot(r0, Heap::kTrueValueRootIndex);
3451bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&done);
3452bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
34530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3454bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
3455bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3456bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
34573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
34583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
34590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
346080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
346180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
346280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
346380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
346480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
34650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
34660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
346780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
346880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
346980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ tst(r0, Operand(String::kContainsCachedArrayIndexMask));
34703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Split(eq, if_true, if_false, fall_through);
347280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
34730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
347480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
347580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
347680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
34773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
34783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
347980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(args->length() == 1);
34800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3481e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (FLAG_debug_code) {
3483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ AbortIfNotString(r0);
3484e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
3485e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
348680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
348780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ IndexFromHash(r0, r0);
3488e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
34890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
349080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
349180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
349280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
34933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
3494e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Label bailout, done, one_char_separator, long_separator,
3495e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      non_trivial_array, not_size_one_array, loop,
3496e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      empty_separator_loop, one_char_separator_loop,
3497e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      one_char_separator_loop_entry, long_separator_loop;
34983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3499e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(args->length() == 2);
3500e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  VisitForStackValue(args->at(1));
3501e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  VisitForAccumulatorValue(args->at(0));
3502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3503e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // All aliases of the same register have disjoint lifetimes.
3504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register array = r0;
3505e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register elements = no_reg;  // Will be r0.
3506e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register result = no_reg;  // Will be r0.
3507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register separator = r1;
3508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register array_length = r2;
3509e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register result_pos = no_reg;  // Will be r2
3510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register string_length = r3;
3511e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register string = r4;
3512e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register element = r5;
3513e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register elements_end = r6;
3514e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register scratch1 = r7;
3515e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register scratch2 = r9;
3516e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3517e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Separator operand is on the stack.
3518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ pop(separator);
3519e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3520e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check that the array is a JSArray.
3521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ JumpIfSmi(array, &bailout);
3522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CompareObjectType(array, scratch1, scratch2, JS_ARRAY_TYPE);
3523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(ne, &bailout);
3524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check that the array has fast elements.
35263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CheckFastElements(scratch1, scratch2, &bailout);
3527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // If the array has length zero, return the empty string.
3529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
3530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ SmiUntag(array_length, SetCC);
3531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(ne, &non_trivial_array);
3532e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ LoadRoot(r0, Heap::kEmptyStringRootIndex);
3533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(&done);
3534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&non_trivial_array);
3536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Get the FixedArray containing array's elements.
3538e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  elements = array;
3539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(elements, FieldMemOperand(array, JSArray::kElementsOffset));
3540e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  array = no_reg;  // End of array's live range.
3541e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check that all array elements are sequential ASCII strings, and
3543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // accumulate the sum of their lengths, as a smi-encoded value.
3544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ mov(string_length, Operand(0));
3545e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(element,
3546e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2));
3548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Loop condition: while (element < elements_end).
3549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Live values in registers:
3550e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   elements: Fixed array of strings.
3551e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   array_length: Length of the fixed array of strings (not smi)
3552e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   separator: Separator string
3553e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   string_length: Accumulated sum of string lengths (smi).
3554e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   element: Current array element.
3555e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   elements_end: Array end.
3556e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (FLAG_debug_code) {
3557e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ cmp(array_length, Operand(0));
3558e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ Assert(gt, "No empty arrays here in EmitFastAsciiArrayJoin");
3559e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
3560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&loop);
3561e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
3562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ JumpIfSmi(string, &bailout);
3563e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(scratch1, FieldMemOperand(string, HeapObject::kMapOffset));
3564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
3565e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
3566e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(scratch1, FieldMemOperand(string, SeqAsciiString::kLengthOffset));
3567e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(string_length, string_length, Operand(scratch1));
3568e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(vs, &bailout);
3569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(element, elements_end);
3570e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(lt, &loop);
3571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // If array_length is 1, return elements[0], a string.
3573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(array_length, Operand(1));
3574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(ne, &not_size_one_array);
3575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize));
3576e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(&done);
3577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&not_size_one_array);
3579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3580e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Live values in registers:
3581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   separator: Separator string
3582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   array_length: Length of the array.
3583e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   string_length: Sum of string lengths (smi).
3584e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   elements: FixedArray of strings.
3585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check that the separator is a flat ASCII string.
3587e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ JumpIfSmi(separator, &bailout);
3588e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset));
3589e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
3590e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
3591e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Add (separator length times array_length) - separator length to the
3593e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // string_length to get the length of the result string. array_length is not
3594e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // smi but the other values are, so the result is a smi
3595e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset));
3596e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ sub(string_length, string_length, Operand(scratch1));
3597e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ smull(scratch2, ip, array_length, scratch1);
3598e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are
3599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // zero.
3600e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(ip, Operand(0));
3601e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(ne, &bailout);
3602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ tst(scratch2, Operand(0x80000000));
3603e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(ne, &bailout);
3604e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(string_length, string_length, Operand(scratch2));
3605e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(vs, &bailout);
3606e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ SmiUntag(string_length);
3607e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3608e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Get first element in the array to free up the elements register to be used
3609e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // for the result.
3610e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(element,
3611e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  result = elements;  // End of live range for elements.
3613e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  elements = no_reg;
3614e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Live values in registers:
3615e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   element: First array element
3616e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   separator: Separator string
3617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   string_length: Length of result string (not smi)
3618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   array_length: Length of the array.
3619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ AllocateAsciiString(result,
3620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         string_length,
3621e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         scratch1,
3622e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         scratch2,
3623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         elements_end,
3624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         &bailout);
3625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Prepare for looping. Set up elements_end to end of the array. Set
3626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // result_pos to the position of the result where to write the first
3627e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // character.
3628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2));
3629e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  result_pos = array_length;  // End of live range for array_length.
3630e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  array_length = no_reg;
3631e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(result_pos,
3632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         result,
3633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
3634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3635e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check the length of the separator.
3636e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset));
3637e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(scratch1, Operand(Smi::FromInt(1)));
3638e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(eq, &one_char_separator);
3639e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(gt, &long_separator);
3640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3641e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Empty separator case
3642e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&empty_separator_loop);
3643e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Live values in registers:
3644e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   result_pos: the position to which we are currently copying characters.
3645e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   element: Current array element.
3646e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   elements_end: Array end.
3647e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3648e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Copy next array element to the result.
3649e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
3650e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
3651e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ SmiUntag(string_length);
3652e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
3653e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CopyBytes(string, result_pos, string_length, scratch1);
3654e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(element, elements_end);
3655e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(lt, &empty_separator_loop);  // End while (element < elements_end).
3656e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(result.is(r0));
3657e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(&done);
3658e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3659e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // One-character separator case
3660e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&one_char_separator);
36613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Replace separator with its ASCII character value.
3662e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldrb(separator, FieldMemOperand(separator, SeqAsciiString::kHeaderSize));
3663e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Jump into the loop after the code that copies the separator, so the first
3664e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // element is not preceded by a separator
3665e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ jmp(&one_char_separator_loop_entry);
3666e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3667e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&one_char_separator_loop);
3668e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Live values in registers:
3669e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   result_pos: the position to which we are currently copying characters.
3670e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   element: Current array element.
3671e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   elements_end: Array end.
36723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //   separator: Single separator ASCII char (in lower byte).
3673e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3674e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Copy the separator character to the result.
3675e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ strb(separator, MemOperand(result_pos, 1, PostIndex));
3676e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3677e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Copy next array element to the result.
3678e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&one_char_separator_loop_entry);
3679e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
3680e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
3681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ SmiUntag(string_length);
3682e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
3683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CopyBytes(string, result_pos, string_length, scratch1);
3684e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(element, elements_end);
3685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(lt, &one_char_separator_loop);  // End while (element < elements_end).
3686e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(result.is(r0));
3687e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(&done);
3688e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3689e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Long separator case (separator is more than one character). Entry is at the
3690e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // label long_separator below.
3691e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&long_separator_loop);
3692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Live values in registers:
3693e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   result_pos: the position to which we are currently copying characters.
3694e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   element: Current array element.
3695e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   elements_end: Array end.
3696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   separator: Separator string.
3697e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3698e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Copy the separator to the result.
3699e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string_length, FieldMemOperand(separator, String::kLengthOffset));
3700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ SmiUntag(string_length);
3701e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(string,
3702e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         separator,
3703e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
3704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CopyBytes(string, result_pos, string_length, scratch1);
3705e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3706e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&long_separator);
3707e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
3708e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
3709e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ SmiUntag(string_length);
3710e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
3711e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CopyBytes(string, result_pos, string_length, scratch1);
3712e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(element, elements_end);
3713e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(lt, &long_separator_loop);  // End while (element < elements_end).
3714e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(result.is(r0));
3715e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(&done);
3716e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3717e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&bailout);
37188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
3719e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&done);
37208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  context()->Plug(r0);
37218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
37228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
37238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3724d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
3725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<String> name = expr->name();
3726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (name->length() > 0 && name->Get(0) == '_') {
3727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ InlineRuntimeCall");
3728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitInlineRuntimeCall(expr);
3729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3730f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
37323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ CallRuntime");
37333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* args = expr->arguments();
37343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
3736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Prepare for calling JS runtime function.
37378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r0, GlobalObjectOperand());
3738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset));
3739402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(r0);
3740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
37413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
37423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Push the arguments ("left-to-right").
37433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
37443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
37450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
3746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
3749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call the JS runtime function.
3750402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(r2, Operand(expr->name()));
3751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
375244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Code> ic =
3753589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
37543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallIC(ic, mode, expr->id());
3755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Restore context register.
3756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
3757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
3758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call the C runtime function.
3759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(expr->function(), arg_count);
3760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
37610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3762d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3765d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
3767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Token::DELETE: {
3768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
3769589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Property* property = expr->expression()->AsProperty();
3770589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VariableProxy* proxy = expr->expression()->AsVariableProxy();
3771e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3772589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (property != NULL) {
3773589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        VisitForStackValue(property->obj());
3774589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        VisitForStackValue(property->key());
37753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE)
37763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ? kNonStrictMode : kStrictMode;
37773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(r1, Operand(Smi::FromInt(strict_mode_flag)));
377869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ push(r1);
377969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
378069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        context()->Plug(r0);
3781589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else if (proxy != NULL) {
3782589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Variable* var = proxy->var();
3783e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Delete of an unqualified identifier is disallowed in strict mode
3784589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // but "delete this" is allowed.
37853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(language_mode() == CLASSIC_MODE || var->is_this());
3786589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (var->IsUnallocated()) {
3787e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ ldr(r2, GlobalObjectOperand());
3788e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ mov(r1, Operand(var->name()));
3789e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ mov(r0, Operand(Smi::FromInt(kNonStrictMode)));
3790e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ Push(r2, r1, r0);
3791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3792e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(r0);
3793589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        } else if (var->IsStackAllocated() || var->IsContextSlot()) {
3794e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Result of deleting non-global, non-dynamic variables is false.
3795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // The subexpression does not have side effects.
3796589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          context()->Plug(var->is_this());
3797e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else {
3798e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Non-global variable.  Call the runtime to try to delete from the
3799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // context where the variable was introduced.
3800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(context_register());
3801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ mov(r2, Operand(var->name()));
3802e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(r2);
3803e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ CallRuntime(Runtime::kDeleteContextSlot, 2);
3804e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(r0);
3805e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
38061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
3807e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Result of deleting non-property, non-variable reference is true.
3808e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // The subexpression may have side effects.
3809e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
3810e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        context()->Plug(true);
3811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
3812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
3813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
3814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
3816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
3817e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
38180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(Heap::kUndefinedValueRootIndex);
3819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
3823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
3824e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (context()->IsEffect()) {
3825e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Unary NOT has no side effects so it's only necessary to visit the
3826e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // subexpression.  Match the optimizing compiler by not branching.
3827e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
38283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (context()->IsTest()) {
38293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        const TestContext* test = TestContext::cast(context());
38303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The labels are swapped for the recursive call.
38313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VisitForControl(expr->expression(),
38323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->false_label(),
38333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->true_label(),
38343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->fall_through());
38353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        context()->Plug(test->true_label(), test->false_label());
3836e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
38373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We handle value contexts explicitly rather than simply visiting
38383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // for control and plugging the control flow into the context,
38393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // because we need to prepare a pair of extra administrative AST ids
38403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // for the optimizing compiler.
38413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
38423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label materialize_true, materialize_false, done;
38433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VisitForControl(expr->expression(),
38443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_false,
38453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_true,
38463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_true);
38473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&materialize_true);
38483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
38493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(r0, Heap::kTrueValueRootIndex);
38503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (context()->IsStackValue()) __ push(r0);
38513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&done);
38523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&materialize_false);
38533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
38543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(r0, Heap::kFalseValueRootIndex);
38553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (context()->IsStackValue()) __ push(r0);
38563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&done);
3857e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
3858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
3862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
38630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      { StackValueContext context(this);
38640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForTypeofValue(expr->expression());
38650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
3866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallRuntime(Runtime::kTypeof, 1);
38670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(r0);
3868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
38693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
3870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3871d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Token::ADD: {
3872d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Comment cmt(masm_, "[ UnaryOperation (ADD)");
38730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->expression());
3874d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Label no_conversion;
38753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ JumpIfSmi(result_register(), &no_conversion);
38761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ToNumberStub convert_stub;
38771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ CallStub(&convert_stub);
3878d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ bind(&no_conversion);
38790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(result_register());
3880d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      break;
3881d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3882d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::SUB:
3884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
38854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
38864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::BIT_NOT:
3888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
38894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
38904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
3892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
38933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
3894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
3898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                           const char* comment) {
3899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // TODO(svenpanne): Allowing format strings in Comment would be nice here...
3900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Comment cmt(masm_, comment);
3901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
3902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  UnaryOverwriteMode overwrite =
3903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
3904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  UnaryOpStub stub(expr->op(), overwrite);
3905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // UnaryOpStub expects the argument to be in the
3906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // accumulator register r0.
3907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  VisitForAccumulatorValue(expr->expression());
3908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SetSourcePosition(expr->position());
39093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
3910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  context()->Plug(r0);
3911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3914d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CountOperation");
391680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
391780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
3919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // as the left-hand side.
3920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->expression()->IsValidLeftHandSide()) {
3921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->expression());
3922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Expression can only be a property, a global or a (parameter or local)
39263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot.
3927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
3928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LhsKind assign_type = VARIABLE;
3929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
3930e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In case of a property we use the uninitialized expression context
3931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // of the key to detect a named property.
3932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (prop != NULL) {
3933e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    assign_type =
3934e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
3935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3936e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
3938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
3939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
39400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
39413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    EmitVariableLoad(expr->expression()->AsVariableProxy());
39423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
3943e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
39440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (expr->is_postfix() && !context()->IsEffect()) {
3945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(ip, Operand(Smi::FromInt(0)));
3946e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ push(ip);
3947e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3948e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (assign_type == NAMED_PROPERTY) {
3949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Put the object both on the stack and in the accumulator.
39500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
3951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(r0);
3952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitNamedPropertyLoad(prop);
3953e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
39543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForStackValue(prop->obj());
39553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForAccumulatorValue(prop->key());
395625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      __ ldr(r1, MemOperand(sp, 0));
395725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      __ push(r0);
3958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitKeyedPropertyLoad(prop);
3959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3960d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We need a second deoptimization point after loading the value
3963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // in case evaluating the property load my have a side effect.
39648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (assign_type == VARIABLE) {
39658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    PrepareForBailout(expr->expression(), TOS_REG);
39668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
39678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    PrepareForBailoutForId(expr->CountId(), TOS_REG);
39688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
3969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3970d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Call ToNumber only if operand is not a smi.
3971d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label no_conversion;
39721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, &no_conversion);
39731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ToNumberStub convert_stub;
39741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ CallStub(&convert_stub);
3975d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&no_conversion);
3976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3977e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
3978e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
39790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (!context()->IsEffect()) {
39800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Save the result on the stack. If we have a named or keyed property
39810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // we store the result under the receiver that is currently on top
39820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // of the stack.
39830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
39840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
39850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ push(r0);
39860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
39870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
39880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ str(r0, MemOperand(sp, kPointerSize));
39890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
39900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
39910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ str(r0, MemOperand(sp, 2 * kPointerSize));
39920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
39930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
3994e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3995e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3996e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3997d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3998d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Inline smi case if we are in a loop.
3999d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label stub_call, done;
4000e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  JumpPatchSite patch_site(masm_);
4001e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
400210e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu  int count_value = expr->op() == Token::INC ? 1 : -1;
400380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (ShouldInlineSmiCase(expr->op())) {
400410e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu    __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC);
4005d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ b(vs, &stub_call);
4006d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // We could eliminate this smi check if we split the code at
4007d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // the first smi check before calling ToNumber.
4008e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    patch_site.EmitJumpIfSmi(r0, &done);
4009e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4010d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ bind(&stub_call);
4011d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Call stub. Undo operation first.
401210e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu    __ sub(r0, r0, Operand(Smi::FromInt(count_value)));
4013d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
401410e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu  __ mov(r1, Operand(Smi::FromInt(count_value)));
4015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Record position before stub call.
4017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
4018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpStub stub(Token::ADD, NO_OVERWRITE);
40203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId());
40213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
4022d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
4023e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4024e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in r0.
4025e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
4026e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case VARIABLE:
4027e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
40280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        { EffectContext context(this);
40290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
40300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                 Token::ASSIGN);
4031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          context.Plug(r0);
40330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        }
40340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        // For all contexts except EffectConstant We have the result on
4035e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
40360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
40370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
4038e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
4039e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
4040e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
40410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                               Token::ASSIGN);
4042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        context()->Plug(r0);
4044e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
4045d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4046e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
4047e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
4048402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ pop(r1);
40493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> ic = is_classic_mode()
40503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? isolate()->builtins()->StoreIC_Initialize()
40513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          : isolate()->builtins()->StoreIC_Initialize_Strict();
40523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
4053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4054e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
40550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
40560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
4057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
4058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
40590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(r0);
4060e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
4061d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4062d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4063e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
4064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r1);  // Key.
4065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r2);  // Receiver.
40663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> ic = is_classic_mode()
40673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? isolate()->builtins()->KeyedStoreIC_Initialize()
40683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
40693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
4070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
40720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
40730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
4074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
4075e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
40760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(r0);
4077e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
4078d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4079d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
40803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
40813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
40823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
40833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
40840d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
40850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!context()->IsEffect());
40860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!context()->IsTest());
408780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  VariableProxy* proxy = expr->AsVariableProxy();
4088589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (proxy != NULL && proxy->var()->IsUnallocated()) {
408980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Comment cmnt(masm_, "Global variable");
40908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r0, GlobalObjectOperand());
409180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(r2, Operand(proxy->name()));
409244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
409380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Use a regular load, not a contextual load, to avoid a reference
409480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // error.
40953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallIC(ic);
4096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailout(expr, TOS_REG);
40970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
4098589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
409959151504615d929945dc59db37bf1166937748c6Steve Block    Label done, slow;
410059151504615d929945dc59db37bf1166937748c6Steve Block
410159151504615d929945dc59db37bf1166937748c6Steve Block    // Generate code for loading from variables potentially shadowed
410259151504615d929945dc59db37bf1166937748c6Steve Block    // by eval-introduced variables.
4103589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
410459151504615d929945dc59db37bf1166937748c6Steve Block
410559151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
410680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(r0, Operand(proxy->name()));
410780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ Push(cp, r0);
410880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
4109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailout(expr, TOS_REG);
411059151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&done);
411159151504615d929945dc59db37bf1166937748c6Steve Block
41120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
411380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
411480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // This expression cannot throw a reference error at the top level.
41153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitInDuplicateContext(expr);
4116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
4117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
4118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
41193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
41203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
41213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Expression* sub_expr,
41223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Handle<String> check) {
41233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label materialize_true, materialize_false;
41243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* if_true = NULL;
41253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* if_false = NULL;
41263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* fall_through = NULL;
41273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
41283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         &if_true, &if_false, &fall_through);
41293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  { AccumulatorValueContext context(this);
41313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForTypeofValue(sub_expr);
41320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
41333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
413544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (check->Equals(isolate()->heap()->number_symbol())) {
4136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(r0, if_true);
413780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
413880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
413980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r0, ip);
414080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
414144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (check->Equals(isolate()->heap()->string_symbol())) {
4142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(r0, if_false);
414380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
4144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE);
4145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ b(ge, if_false);
414680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
4147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ tst(r1, Operand(1 << Map::kIsUndetectable));
4148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(eq, if_true, if_false, fall_through);
414944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (check->Equals(isolate()->heap()->boolean_symbol())) {
4150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CompareRoot(r0, Heap::kTrueValueRootIndex);
4151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(eq, if_true);
4152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CompareRoot(r0, Heap::kFalseValueRootIndex);
415380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
415469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  } else if (FLAG_harmony_typeof &&
415569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch             check->Equals(isolate()->heap()->null_symbol())) {
415669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ CompareRoot(r0, Heap::kNullValueRootIndex);
415769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Split(eq, if_true, if_false, fall_through);
415844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (check->Equals(isolate()->heap()->undefined_symbol())) {
4159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
4160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(eq, if_true);
4161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(r0, if_false);
416280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => true.
416380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
416480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
4165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ tst(r1, Operand(1 << Map::kIsUndetectable));
4166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(ne, if_true, if_false, fall_through);
4167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
416844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (check->Equals(isolate()->heap()->function_symbol())) {
4169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(r0, if_false);
41703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
41713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareObjectType(r0, r0, r1, JS_FUNCTION_TYPE);
41723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(eq, if_true);
41733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(r1, Operand(JS_FUNCTION_PROXY_TYPE));
41743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Split(eq, if_true, if_false, fall_through);
417544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (check->Equals(isolate()->heap()->object_symbol())) {
4176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(r0, if_false);
417769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (!FLAG_harmony_typeof) {
417869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ CompareRoot(r0, Heap::kNullValueRootIndex);
417969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ b(eq, if_true);
418069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
418180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for JS objects => true.
41823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ CompareObjectType(r0, r0, r1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
41833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ b(lt, if_false);
41843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ CompareInstanceType(r0, r1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
41853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ b(gt, if_false);
4186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Check for undetectable objects => false.
4187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
4188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ tst(r1, Operand(1 << Map::kIsUndetectable));
4189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(eq, if_true, if_false, fall_through);
419080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
419180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (if_false != fall_through) __ jmp(if_false);
4192f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
41933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->Plug(if_true, if_false);
4194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
4195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4197d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
419980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
4200e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
42013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First we try a fast inlined version of the compare when one of
42023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the operands is a literal.
42033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (TryLiteralCompare(expr)) return;
42043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4205e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
4206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
4207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
4208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
4209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
421080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
42110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
42120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
421380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
42143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Token::Value op = expr->op();
42150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->left());
421680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
4217e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
42180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
4219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
42203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
4221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ LoadRoot(ip, Heap::kTrueValueRootIndex);
4222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ cmp(r0, ip);
422380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(eq, if_true, if_false, fall_through);
4224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
42270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
4228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      InstanceofStub stub(InstanceofStub::kNoFlags);
4229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
42303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
423180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // The stub returns 0 for true.
4232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ tst(r0, r0);
423380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(eq, if_true, if_false, fall_through);
4234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
42380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->right());
42391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Condition cond = eq;
424080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      switch (op) {
4241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::EQ_STRICT:
424280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        case Token::EQ:
42431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          cond = eq;
4244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LT:
42461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          cond = lt;
4247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GT:
42493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          cond = gt;
4250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block         break;
4251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LTE:
42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          cond = le;
4253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GTE:
42551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          cond = ge;
4256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::IN:
4258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::INSTANCEOF:
4259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default:
4260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
4261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(r1);
4263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
42640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      bool inline_smi_code = ShouldInlineSmiCase(op);
42651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      JumpPatchSite patch_site(masm_);
42660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (inline_smi_code) {
426780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Label slow_case;
426880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ orr(r2, r0, Operand(r1));
42691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        patch_site.EmitJumpIfNotSmi(r2, &slow_case);
427080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ cmp(r1, r0);
42711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Split(cond, if_true, if_false, NULL);
427280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&slow_case);
427380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
42741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
42751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Record position and call the compare IC.
42761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      SetSourcePosition(expr->position());
42771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Handle<Code> ic = CompareIC::GetUninitialized(op);
42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
42793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      patch_site.EmitPatchInfo();
42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
42811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ cmp(r0, Operand(0));
42821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Split(cond, if_true, if_false, fall_through);
42833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
42843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
42853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
4287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
42880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
4289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
42903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
42923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
42933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              Expression* sub_expr,
42943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              NilValue nil) {
429580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
429680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
429780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
429880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
42990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
43000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
430180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitForAccumulatorValue(sub_expr);
43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Heap::RootListIndex nil_value = nil == kNullValue ?
43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Heap::kNullValueRootIndex :
43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Heap::kUndefinedValueRootIndex;
43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(r1, nil_value);
430880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ cmp(r0, r1);
43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expr->op() == Token::EQ_STRICT) {
431080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
431180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
43123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Heap::RootListIndex other_nil_value = nil == kNullValue ?
43133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Heap::kUndefinedValueRootIndex :
43143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Heap::kNullValueRootIndex;
431580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(eq, if_true);
43163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(r1, other_nil_value);
431780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r0, r1);
431880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(eq, if_true);
43193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(r0, if_false);
432080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // It can be an undetectable object.
432180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
432280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
432380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
432480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r1, Operand(1 << Map::kIsUndetectable));
432580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
432680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
43270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
432880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
432980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
433080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
4331d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
43330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
4334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
43370d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() {
43380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return r0;
43390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
43420d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() {
43430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return cp;
43440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
43450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
43460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4347d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
4349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ str(value, MemOperand(fp, frame_offset));
4350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
43513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4353d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
435459151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(dst, ContextOperand(cp, context_index));
43553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
43563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
43583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
43593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Scope* declaration_scope = scope()->DeclarationScope();
43603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (declaration_scope->is_global_scope()) {
43613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Contexts nested in the global context have a canonical empty function
43623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // as their closure, not the anonymous closure containing the global
43633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // code.  Pass a smi sentinel and let the runtime look up the empty
43643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // function.
43653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ mov(ip, Operand(Smi::FromInt(0)));
43663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else if (declaration_scope->is_eval_scope()) {
43673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Contexts created by a call to eval have the same closure as the
43683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // context calling eval, not the anonymous closure containing the eval
43693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // code.  Fetch it from the context.
43703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ ldr(ip, ContextOperand(cp, Context::CLOSURE_INDEX));
43713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
43723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(declaration_scope->is_function_scope());
43733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ ldr(ip, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
43743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
43753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ push(ip);
43763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
43773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ----------------------------------------------------------------------------
4380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support.
4381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4382d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() {
4383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(r1));
4384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store result register while executing finally block.
4385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
4386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Cook return address in link register to stack (smi encoded Code* delta)
4387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ sub(r1, lr, Operand(masm_->CodeObject()));
4388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
438969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
4390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(r1, r1, Operand(r1));  // Convert to smi.
4391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(r1);
4392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4395d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() {
4396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(r1));
4397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Restore result register from stack.
4398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(r1);
4399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Uncook return address and return.
4400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(result_register());
4401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
4402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(r1, Operand(r1, ASR, 1));  // Un-smi-tag value.
4403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(pc, r1, Operand(masm_->CodeObject()));
4404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef __
4408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
440969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#define __ ACCESS_MASM(masm())
441069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
441169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochFullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
441269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int* stack_depth,
441369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int* context_length) {
441469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // The macros used here must preserve the result register.
441569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
441669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Because the handler block contains the context of the finally
441769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // code, we can restore it directly from there for the finally code
441869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // rather than iteratively unwinding contexts via their previous
441969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // links.
442069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ Drop(*stack_depth);  // Down to the handler block.
442169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (*context_length > 0) {
442269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Restore the context to its dedicated register and the stack.
442369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ ldr(cp, MemOperand(sp, StackHandlerConstants::kContextOffset));
442469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
442569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
442669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ PopTryHandler();
442769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bl(finally_entry_);
442869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
442969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  *stack_depth = 0;
443069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  *context_length = 0;
443169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return previous_;
443269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
443369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
443469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
443569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#undef __
443669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
44373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} }  // namespace v8::internal
4438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
4440