full-codegen-arm.cc revision 756813857a4c2a4d8ad2e805969d5768d3cf43a0
13ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Copyright 2009 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
323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "codegen-inl.h"
33d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h"
34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "debug.h"
35d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "full-codegen.h"
363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "parser.h"
376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "scopes.h"
383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 {
403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal {
413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_)
433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function.  On entry to the function the receiver
453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right.  The actual
463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// argument count matches the formal parameter count expected by the
473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// function.
483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are:
503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o r1: the JS function object being called (ie, ourselves)
513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o cp: our context
523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o fp: our caller's frame pointer
533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o sp: stack pointer
543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o lr: return address
553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame.  Please see JavaScriptFrameConstants in
573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-arm.h for its layout.
58756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::Generate(CompilationInfo* info) {
593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ASSERT(info_ == NULL);
603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  info_ = info;
613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  SetFunctionPosition(function());
626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comment cmnt(masm_, "[ function compiled by full code generator");
633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
64756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int locals_count = scope()->num_stack_slots();
653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
66756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ Push(lr, fp, cp, r1);
67756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (locals_count > 0) {
68756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Load undefined value here, so the value is ready for the loop
69756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // below.
70756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
71756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
72756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Adjust fp to point to caller's fp.
73756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ add(fp, sp, Operand(2 * kPointerSize));
743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
75756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  { Comment cmnt(masm_, "[ Allocate locals");
76756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (int i = 0; i < locals_count; i++) {
77756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ push(ip);
784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
79756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
80d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
81756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  bool function_in_register = true;
824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
83756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate a local context.
84756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
85756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (heap_slots > 0) {
86756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate local context");
87756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Argument to NewContext is the function, which is in r1.
88756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ push(r1);
89756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
90756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      FastNewContextStub stub(heap_slots);
91756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ CallStub(&stub);
92756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
93756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ CallRuntime(Runtime::kNewContext, 1);
94756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
95756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    function_in_register = false;
96756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Context is returned in both r0 and cp.  It replaces the context
97756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // passed to us.  It's saved in the stack and kept live in cp.
98756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
99756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Copy any necessary parameters into the context.
100756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    int num_parameters = scope()->num_parameters();
101756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (int i = 0; i < num_parameters; i++) {
102756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      Slot* slot = scope()->parameter(i)->slot();
103756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      if (slot != NULL && slot->type() == Slot::CONTEXT) {
104756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
105756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick            (num_parameters - 1 - i) * kPointerSize;
106756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Load parameter from stack.
107756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ ldr(r0, MemOperand(fp, parameter_offset));
108756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Store it in the context.
109756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ mov(r1, Operand(Context::SlotOffset(slot->index())));
110756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ str(r0, MemOperand(cp, r1));
111756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Update the write barrier. This clobbers all involved
112756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // registers, so we have to use two more registers to avoid
113756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // clobbering cp.
114756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ mov(r2, Operand(cp));
115756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ RecordWrite(r2, Operand(r1), r3, r0);
116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
118756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
119d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
120756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Variable* arguments = scope()->arguments()->AsVariable();
121756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (arguments != NULL) {
122756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Function uses arguments object.
123756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate arguments object");
124756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (!function_in_register) {
125756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      // Load this again, if it's used by the local context below.
126756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
127756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
128756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ mov(r3, r1);
129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
130756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Receiver is just before the parameters on the caller's stack.
131756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    int offset = scope()->num_parameters() * kPointerSize;
132756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ add(r2, fp,
133756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           Operand(StandardFrameConstants::kCallerSPOffset + offset));
134756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ mov(r1, Operand(Smi::FromInt(scope()->num_parameters())));
135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ Push(r3, r2, r1);
136756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
137756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Arguments to ArgumentsAccessStub:
138756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    //   function, receiver address, parameter count.
139756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The stub will rewrite receiever and parameter count if the previous
140756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // stack frame was an arguments adapter frame.
141756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
142756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
143756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Duplicate the value; move-to-slot operation might clobber registers.
144756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ mov(r3, r0);
145756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Move(arguments->slot(), r0, r1, r2);
146756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Slot* dot_arguments_slot =
147756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        scope()->arguments_shadow()->AsVariable()->slot();
148756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Move(dot_arguments_slot, r3, r1, r2);
149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  { Comment cmnt(masm_, "[ Declarations");
152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // For named function expressions, declare the function name as a
153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // constant.
154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (scope()->is_function_scope() && scope()->function() != NULL) {
155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      EmitDeclaration(scope()->function(), Variable::CONST, NULL);
156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Visit all the explicit declarations unless there is an illegal
158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // redeclaration.
159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (scope()->HasIllegalRedeclaration()) {
160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      scope()->VisitIllegalRedeclaration(this);
161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitDeclarations(scope()->declarations());
163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Check the stack for overflow or break request.
167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Put the lr setup instruction in the delay slot.  The kInstrSize is
168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // added to the implicit 8 byte offset that always applies to operations
169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // with pc and gives a return address 12 bytes down.
170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { Comment cmnt(masm_, "[ Stack check");
1714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ LoadRoot(r2, Heap::kStackLimitRootIndex);
1724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ add(lr, pc, Operand(Assembler::kInstrSize));
1734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ cmp(sp, Operand(r2));
1744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    StackCheckStub stub;
1754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ mov(pc,
1764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           Operand(reinterpret_cast<intptr_t>(stub.GetCode().location()),
1774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                   RelocInfo::CODE_TARGET),
1784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           LeaveCC,
1794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           lo);
1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (FLAG_trace) {
1833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CallRuntime(Runtime::kTraceEnter, 0);
1843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ Body");
187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    VisitStatements(function()->body());
189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
1933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Emit a 'return undefined' in case control fell off the end of the
1943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // body.
1953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  EmitReturnSequence();
198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() {
202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ b(&return_label_);
205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
2073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
2083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // Push the return value on the stack as the parameter.
2093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // Runtime::TraceExit returns its parameter in r0.
2103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(r0);
2113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ CallRuntime(Runtime::kTraceExit, 1);
2123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
2133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG
215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Add a label for checking the size of the code used for returning.
216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Label check_exit_codesize;
217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    masm_->bind(&check_exit_codesize);
2186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Make sure that the constant pool is not emitted inside of the return
2206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // sequence.
2216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    { Assembler::BlockConstPoolScope block_const_pool(masm_);
2226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Here we use masm_-> instead of the __ macro to avoid the code coverage
2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // tool from instrumenting as we rely on the code size here.
2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize;
225bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ RecordJSReturn();
2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      masm_->mov(sp, fp);
2286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      masm_->ldm(ia_w, sp, fp.bit() | lr.bit());
2296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      masm_->add(sp, sp, Operand(sp_delta));
2306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      masm_->Jump(lr);
231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG
234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Check that the size of the code used for returning matches what is
2356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // expected by the debugger. If the sp_delts above cannot be encoded in the
2366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // add instruction the add will generate two instructions.
2376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int return_sequence_length =
2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        masm_->InstructionsGeneratedSince(&check_exit_codesize);
2397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    CHECK(return_sequence_length ==
2407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          Assembler::kJSReturnSequenceInstructions ||
2417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          return_sequence_length ==
2427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          Assembler::kJSReturnSequenceInstructions + 1);
2436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
248d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Register reg) {
249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Nothing to do.
255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValue:
258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Move value into place.
259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (!reg.is(result_register())) __ mov(result_register(), reg);
262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(reg);
265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Push an extra copy of the value in case it's needed.
272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ push(reg);
273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Fall through.
274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTest:
276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // We always call the runtime on ARM, so push the value as argument.
277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ push(reg);
278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
284d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Slot* slot) {
285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Nothing to do.
290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // On ARM we have to move the value into a register to do anything
296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // with it.
297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Move(result_register(), slot);
298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Apply(context, result_register());
299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
301d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
304d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Literal* lit) {
305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Nothing to do.
311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // On ARM we have to move the value into a register to do anything
316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // with it.
317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(result_register(), Operand(lit->handle()));
318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Apply(context, result_register());
319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
321d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
322d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
324d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ApplyTOS(Expression::Context context) {
325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
326d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
331d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
335e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
337e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
338e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTestValue:
345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Duplicate the value on the stack in case it's needed.
346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ ldr(ip, MemOperand(sp));
347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ push(ip);
348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Fall through.
349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
352d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
353d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
357d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DropAndApply(int count,
358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     Expression::Context context,
359e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     Register reg) {
360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(count > 0);
361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!reg.is(sp));
362d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(count);
368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
372e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Drop(count);
374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (!reg.is(result_register())) __ mov(result_register(), reg);
375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (count > 1) __ Drop(count - 1);
378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ str(reg, MemOperand(sp));
379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (count > 1) __ Drop(count - 1);
385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ str(reg, MemOperand(sp));
386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTestValue:
391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (count == 1) {
392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ str(reg, MemOperand(sp));
393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(reg);
394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {  // count > 1
395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ Drop(count - 2);
396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ str(reg, MemOperand(sp, kPointerSize));
397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ str(reg, MemOperand(sp));
398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
401d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
404f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::PrepareTest(Label* materialize_true,
405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                    Label* materialize_false,
406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                    Label** if_true,
407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                    Label** if_false) {
408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (context_) {
409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kUninitialized:
410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      UNREACHABLE();
411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
412f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kEffect:
413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // In an effect context, the true and the false case branch to the
414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // same label.
415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_true = *if_false = materialize_true;
416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kValue:
418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_true = materialize_true;
419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_false = materialize_false;
420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kTest:
422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_true = true_label_;
423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_false = false_label_;
424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kValueTest:
426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_true = materialize_true;
427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_false = false_label_;
428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kTestValue:
430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_true = true_label_;
431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_false = materialize_false;
432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
437d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context,
438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                              Label* materialize_true,
439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                              Label* materialize_false) {
440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT_EQ(materialize_true, materialize_false);
445e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(materialize_true);
446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
448e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue: {
449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Label done;
450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ bind(materialize_true);
453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ jmp(&done);
455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ bind(materialize_false);
456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ bind(materialize_true);
460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ LoadRoot(ip, Heap::kTrueValueRootIndex);
461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(ip);
462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ jmp(&done);
463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ bind(materialize_false);
464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ LoadRoot(ip, Heap::kFalseValueRootIndex);
465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(ip);
466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ bind(&done);
469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
473e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
474e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
475e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(materialize_true);
477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ LoadRoot(ip, Heap::kTrueValueRootIndex);
483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(ip);
484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(true_label_);
487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(materialize_false);
491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ LoadRoot(ip, Heap::kFalseValueRootIndex);
497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(ip);
498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(false_label_);
501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// Convert constant control flow (true or false) to the result expected for
507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// a given expression context.
508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, bool flag) {
509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (context) {
510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kUninitialized:
511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      UNREACHABLE();
512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kEffect:
514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kValue: {
516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Heap::RootListIndex value_root_index =
517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      switch (location_) {
519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kAccumulator:
520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ LoadRoot(result_register(), value_root_index);
521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kStack:
523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ LoadRoot(ip, value_root_index);
524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(ip);
525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kTest:
530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ b(flag ? true_label_ : false_label_);
531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kTestValue:
533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      switch (location_) {
534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kAccumulator:
535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // If value is false it's needed.
536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (!flag) __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kStack:
539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // If value is false it's needed.
540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (!flag) {
541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            __ LoadRoot(ip, Heap::kFalseValueRootIndex);
542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            __ push(ip);
543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          }
544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ b(flag ? true_label_ : false_label_);
547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kValueTest:
549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      switch (location_) {
550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kAccumulator:
551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // If value is true it's needed.
552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (flag) __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kStack:
555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // If value is true it's needed.
556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (flag) {
557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            __ LoadRoot(ip, Heap::kTrueValueRootIndex);
558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            __ push(ip);
559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          }
560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ b(flag ? true_label_ : false_label_);
563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
568d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DoTest(Expression::Context context) {
569e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // The value to test is pushed on the stack, and duplicated on the stack
570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // if necessary (for value/test and test/value contexts).
571e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_NE(NULL, true_label_);
572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_NE(NULL, false_label_);
573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
574e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call the runtime to find the boolean value of the source and then
575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // translate it into control flow to the pair of labels.
576e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallRuntime(Runtime::kToBool, 1);
577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ LoadRoot(ip, Heap::kTrueValueRootIndex);
578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(r0, ip);
579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Complete based on the context.
581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValue:
585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTest:
588e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ b(eq, true_label_);
589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(false_label_);
590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValueTest: {
593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Label discard;
594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
596e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ b(ne, &discard);
597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(true_label_);
599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
600e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ b(eq, true_label_);
602e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ bind(&discard);
605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ jmp(false_label_);
607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
608d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTestValue: {
611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Label discard;
612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ b(eq, &discard);
615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(false_label_);
617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ b(ne, false_label_);
620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
621d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ bind(&discard);
623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
624d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ jmp(true_label_);
625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
628d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
631d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (slot->type()) {
633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::PARAMETER:
634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOCAL:
635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return MemOperand(fp, SlotOffset(slot));
636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::CONTEXT: {
637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      int context_chain_length =
6383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          scope()->ContextChainLength(slot->var()->scope());
639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ LoadContext(scratch, context_chain_length);
640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return CodeGenerator::ContextOperand(scratch, slot->index());
641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOOKUP:
643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  UNREACHABLE();
646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return MemOperand(r0, 0);
647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
650d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) {
651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Use destination as scratch.
652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand slot_operand = EmitSlotSearch(source, destination);
653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ldr(destination, slot_operand);
654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
657d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst,
658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register src,
659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch1,
660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch2) {
661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(dst->type() != Slot::LOOKUP);  // Not yet implemented.
662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!scratch1.is(src) && !scratch2.is(src));
663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(dst, scratch1);
664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ str(src, location);
665e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
666e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (dst->type() == Slot::CONTEXT) {
6679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ RecordWrite(scratch1,
6689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                   Operand(Context::SlotOffset(dst->index())),
6699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                   scratch2,
6709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                   src);
671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitDeclaration(Variable* variable,
676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Variable::Mode mode,
677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        FunctionLiteral* function) {
678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Declaration");
679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(variable != NULL);  // Must have been resolved.
680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Slot* slot = variable->slot();
681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = variable->AsProperty();
682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (slot != NULL) {
684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOCAL:
687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ str(ip, MemOperand(fp, SlotOffset(slot)));
690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          VisitForValue(function, kAccumulator);
692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT:
697e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // We bypass the general EmitSlotSearch because we know more about
698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // this specific context.
699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // The variable in the decl always resides in the current context.
701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (FLAG_debug_code) {
703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Check if we have the correct context pointer.
704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ ldr(r1,
705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                 CodeGenerator::ContextOperand(cp, Context::FCONTEXT_INDEX));
706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ cmp(r1, cp);
707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Check(eq, "Unexpected declaration in current context.");
708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ str(ip, CodeGenerator::ContextOperand(cp, slot->index()));
712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // No write barrier since the_hole_value is in old space.
713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          VisitForValue(function, kAccumulator);
715e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ str(result_register(),
716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                 CodeGenerator::ContextOperand(cp, slot->index()));
717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          int offset = Context::SlotOffset(slot->index());
718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // We know that we have written a function, which is not a smi.
7194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ mov(r1, Operand(cp));
7209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          __ RecordWrite(r1, Operand(offset), r2, result_register());
721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP: {
725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(r2, Operand(variable->name()));
726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Declaration nodes are always introduced in one of two modes.
727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ASSERT(mode == Variable::VAR ||
728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke               mode == Variable::CONST);
729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        PropertyAttributes attr =
730f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            (mode == Variable::VAR) ? NONE : READ_ONLY;
731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ mov(r1, Operand(Smi::FromInt(attr)));
732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Push initial value, if any.
733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Note: For variables we must not push an initial value (such as
734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // 'undefined') because we may have a (legal) redeclaration and we
735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // must not destroy the current value.
736f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ Push(cp, r2, r1, r0);
739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ Push(cp, r2, r1);
741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Push initial value for function declaration.
742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          VisitForValue(function, kStack);
743d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else {
744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ mov(r0, Operand(Smi::FromInt(0)));  // No initial value!
745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ Push(cp, r2, r1, r0);
746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDeclareContextSlot, 4);
748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (prop != NULL) {
753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (function != NULL || mode == Variable::CONST) {
754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // We are declaring a function or constant that rewrites to a
755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // property.  Use (keyed) IC to set the initial value.
756e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->obj(), kStack);
757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (function != NULL) {
758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForValue(prop->key(), kStack);
759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForValue(function, kAccumulator);
760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ pop(r1);  // Key.
761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForValue(prop->key(), kAccumulator);
763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(r1, result_register());  // Key.
764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex);
765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r2);  // Receiver.
767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ Call(ic, RelocInfo::CODE_TARGET);
770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Value in r0 is ignored (declarations are statements).
771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
7723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
7733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
7743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) {
777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
781d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
7823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
7833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // The context is the first argument.
7843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r1, Operand(pairs));
7853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(cp, r1, r0);
7873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kDeclareGlobals, 3);
7883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
7893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
7903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ SwitchStatement");
794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Breakable nested_statement(this, stmt);
795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Keep the switch value on the stack until a case matches.
797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(stmt->tag(), kStack);
798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<CaseClause*>* clauses = stmt->cases();
800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label next_test;  // Recycled for each test.
803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the tests with branches to their bodies.
804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The default is not a test, but remember it as final fall through.
807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (clause->is_default()) {
808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      default_clause = clause;
809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      continue;
810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case comparison");
813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&next_test);
814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    next_test.Unuse();
815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Compile the label expression.
817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(clause->label(), kAccumulator);
818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Perform the comparison as if via '==='.  The comparison stub expects
820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // the smi vs. smi case to be handled before it is called.
821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Label slow_case;
822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(r1, MemOperand(sp, 0));  // Switch value.
8233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ orr(r2, r1, r0);
824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ tst(r2, Operand(kSmiTagMask));
825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(ne, &slow_case);
826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ cmp(r1, r0);
827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(ne, &next_test);
828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(clause->body_target()->entry_label());
830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&slow_case);
8323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    CompareStub stub(eq, true, kBothCouldBeNaN, true, r1, r0);
833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
8343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ cmp(r0, Operand(0));
835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(ne, &next_test);
836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(clause->body_target()->entry_label());
838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Discard the test value and jump to the default if present, otherwise to
841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the end of the statement.
842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&next_test);
843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(1);  // Switch value is no longer needed.
844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (default_clause == NULL) {
845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(nested_statement.break_target());
846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(default_clause->body_target()->entry_label());
848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the case bodies.
851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case body");
853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(clause->body_target()->entry_label());
855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitStatements(clause->statements());
856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(nested_statement.break_target());
859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ ForInStatement");
864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label loop, exit;
867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ForIn loop_statement(this, stmt);
868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  increment_loop_depth();
869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the object to enumerate over. Both SpiderMonkey and JSC
871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ignore null and undefined in contrast to the specification; see
872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ECMA-262 section 12.6.4.
873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(stmt->enumerable(), kAccumulator);
874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, ip);
876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, &exit);
877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(ip, Heap::kNullValueRootIndex);
878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, ip);
879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, &exit);
880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the object to a JS object.
882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label convert, done_convert;
883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, &convert);
884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(hs, &done_convert);
886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&convert);
887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);
888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done_convert);
890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);
891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // TODO(kasperl): Check cache validity in generated code. This is a
893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // fast case for the JSObject::IsSimpleEnum cache validity
894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // checks. If we cannot guarantee cache validity, call the runtime
895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // system to check cache validity or get the property names in a
896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // fixed array.
897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the set of properties to enumerate.
899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);  // Duplicate the enumerable object on the stack.
900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If we got a map from the runtime call, we can do a fast
903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // modification check. Otherwise, we got a fixed array, and we have
904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // to do a slow check.
905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label fixed_array;
906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r2, r0);
907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));
908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(ip, Heap::kMetaMapRootIndex);
909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, ip);
910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &fixed_array);
911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a map in register r0. Get the enumeration cache from it.
913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r0, Map::kInstanceDescriptorsOffset));
914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset));
915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));
916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Setup the four remaining stack slots.
918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);  // Map.
919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r2, FixedArray::kLengthOffset));
920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r0, Operand(Smi::FromInt(0)));
921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Push enumeration cache, enumeration cache length (as smi) and zero.
922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(r2, r1, r0);
923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a fixed array in register r0. Iterate through that.
926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&fixed_array);
927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r1, Operand(Smi::FromInt(0)));  // Map (0) - force slow check.
928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(r1, r0);
929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset));
930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r0, Operand(Smi::FromInt(0)));
931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(r1, r0);  // Fixed array length (as smi) and initial index.
932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for doing the condition check.
934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&loop);
935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the current count to r0, load the length to r1.
936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, r1);  // Compare to the array length.
938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(hs, loop_statement.break_target());
939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the current entry of the array into register r3.
941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(sp, 2 * kPointerSize));
942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the expected map from the stack or a zero map in the
946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // permanent slow case into register r2.
947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(sp, 3 * kPointerSize));
948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the expected map still matches that of the enumerable.
950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If not, we have to filter the key.
951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label update_each;
952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, MemOperand(sp, 4 * kPointerSize));
953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset));
954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r4, Operand(r2));
955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, &update_each);
956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
957756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Convert the entry to a string or (smi) 0 if it isn't a property
958756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // any more. If the property has been removed while iterating, we
959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // just skip it.
960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r1);  // Enumerable.
961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r3);  // Current entry.
962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS);
963756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ mov(r3, Operand(r0), SetCC);
964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, loop_statement.continue_target());
965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the 'each' property or variable from the possibly filtered
967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // entry in register r3.
968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&update_each);
969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(result_register(), r3);
970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Perform the assignment as if via '='.
971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  EmitAssignment(stmt->each());
972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the body of the loop.
974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label stack_limit_hit, stack_check_done;
975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Visit(stmt->body());
976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ StackLimitCheck(&stack_limit_hit);
978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&stack_check_done);
979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the going to the next element by incrementing
981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the index (smi) stored on top of the stack.
982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(loop_statement.continue_target());
983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r0);
984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(r0, r0, Operand(Smi::FromInt(1)));
985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);
986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(&loop);
987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Slow case for the stack limit check.
989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StackCheckStub stack_check_stub;
990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&stack_limit_hit);
991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stack_check_stub);
992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(&stack_check_done);
993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Remove the pointers stored on the stack.
995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(loop_statement.break_target());
996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(5);
997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Exit and decrement the loop depth.
999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
1000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  decrement_loop_depth();
1001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
10023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
1005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Use the fast case closure allocation code that allocates in new
1006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // space for nested functions that don't need literals cloning.
1007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (scope()->is_function_scope() && info->num_literals() == 0) {
1008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    FastNewClosureStub stub;
1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r0, Operand(info));
1010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(r0);
1011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r0, Operand(info));
1014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Push(cp, r0);
1015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kNewClosure, 2);
1016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, r0);
10183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
10193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1021d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
10223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ VariableProxy");
1023e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  EmitVariableLoad(expr->var(), context_);
1024e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1025e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1026e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1027d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableLoad(Variable* var,
1028e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Expression::Context context) {
1029d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Four cases: non-this global variables, lookup slots, all other
1030d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // types of slots, and parameters that rewrite to explicit property
1031d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // accesses on the arguments object.
1032d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Slot* slot = var->slot();
1033d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Property* property = var->AsProperty();
1034d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1035d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (var->is_global() && !var->is_this()) {
10363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Comment cmnt(masm_, "Global variable");
10373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Use inline caching. Variable name is passed in r2 and the global
1038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // object (receiver) in r0.
10396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ ldr(r0, CodeGenerator::GlobalObject());
1040e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ mov(r2, Operand(var->name()));
10413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
10423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Apply(context, r0);
1044d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1045d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
1046d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Lookup slot");
1047d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ mov(r1, Operand(var->name()));
1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Push(cp, r1);  // Context and name.
1049d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
1050d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Apply(context, r0);
1051d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1052d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL) {
1053d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1054d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            ? "Context slot"
1055d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            : "Stack slot");
1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (var->mode() == Variable::CONST) {
1057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke       // Constants may be the hole value if they have not been initialized.
1058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke       // Unhole them.
1059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke       Label done;
1060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke       MemOperand slot_operand = EmitSlotSearch(slot, r0);
1061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke       __ ldr(r0, slot_operand);
1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke       __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke       __ cmp(r0, ip);
1064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke       __ b(ne, &done);
1065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke       __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
1066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke       __ bind(&done);
1067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke       Apply(context, r0);
1068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke     } else {
1069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke       Apply(context, slot);
1070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke     }
1071d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1072d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Rewritten parameter");
1073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(property);
1074d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Rewritten parameter accesses are of the form "slot[literal]".
1075d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1076e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the object is in a slot.
1077d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1078d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(object_var);
1079d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Slot* object_slot = object_var->slot();
1080d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(object_slot);
1081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1082d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the object.
10836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Move(r1, object_slot);
1084d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1085e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the key is a smi.
1086d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key_literal = property->key()->AsLiteral();
1087d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(key_literal);
1088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(key_literal->handle()->IsSmi());
1089d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1090d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the key.
10916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ mov(r0, Operand(key_literal->handle()));
1092d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
109325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    // Call keyed load IC. It has arguments key and receiver in r0 and r1.
1094d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1095d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ Call(ic, RelocInfo::CODE_TARGET);
109625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    Apply(context, r0);
10973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
10983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
10993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1101d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1102d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ RegExpLiteral");
1103bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label materialized;
11043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Registers will be used as follows:
11053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r4 = JS function, literals array
11063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r3 = literal index
11073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r2 = RegExp pattern
11083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r1 = RegExp flags
1109bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // r0 = temp + materialized value (RegExp literal)
11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(r0, MemOperand(fp,  JavaScriptFrameConstants::kFunctionOffset));
11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(r4,  FieldMemOperand(r0, JSFunction::kLiteralsOffset));
11123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int literal_offset =
11133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
11143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(r0, FieldMemOperand(r4, literal_offset));
11153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
11163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ cmp(r0, ip);
1117bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(ne, &materialized);
11183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r3, Operand(Smi::FromInt(expr->literal_index())));
11193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r2, Operand(expr->pattern()));
11203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r1, Operand(expr->flags()));
11216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(r4, r3, r2, r1);
11223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1123bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&materialized);
1124bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1125bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(r0);
1126bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(r0, Operand(Smi::FromInt(size)));
1127bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(r0);
1128bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1129bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // After this, registers are used as follows:
1130bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // r0: Newly allocated regexp.
1131bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // r1: Materialized regexp
1132bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // r2: temp.
1133bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(r1);
1134bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CopyFields(r0, r1, r2.bit(), size / kPointerSize);
1135e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, r0);
1136d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1139d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
11416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r3, MemOperand(fp,  JavaScriptFrameConstants::kFunctionOffset));
11426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
11436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
11446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r1, Operand(expr->constant_properties()));
11456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r0, Operand(Smi::FromInt(expr->fast_elements() ? 1 : 0)));
11466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(r3, r2, r1, r0);
1147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->depth() > 1) {
11486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
11493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
11506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
1151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1152d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1153e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
1154e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in r0.
1155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
1156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1157d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < expr->properties()->length(); i++) {
1158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectLiteral::Property* property = expr->properties()->at(i);
1159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
1160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = property->key();
1162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
1163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
1164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ push(r0);  // Save result on stack
1165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
1166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
1168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::CONSTANT:
1169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        UNREACHABLE();
1170e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value()));
1172e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
1174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (key->handle()->IsSymbol()) {
1175e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          VisitForValue(value, kAccumulator);
1176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ mov(r2, Operand(key->handle()));
1177402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu          __ ldr(r1, MemOperand(sp));
1178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Call(ic, RelocInfo::CODE_TARGET);
1180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Fall through.
1183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::PROTOTYPE:
1184e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Duplicate receiver on stack.
1185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ ldr(r0, MemOperand(sp));
1186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(r0);
1187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(key, kStack);
1188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(value, kStack);
1189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kSetProperty, 3);
1190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::GETTER:
1192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::SETTER:
1193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Duplicate receiver on stack.
1194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ ldr(r0, MemOperand(sp));
1195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(r0);
1196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(key, kStack);
1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ?
1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                           Smi::FromInt(1) :
1199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                           Smi::FromInt(0)));
1200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(r1);
1201e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(value, kStack);
1202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDefineAccessor, 4);
1203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1207e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
1208e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ApplyTOS(context_);
1209e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
1210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Apply(context_, r0);
12113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
12133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1215d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
12163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
1217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<Expression*>* subexprs = expr->values();
1219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int length = subexprs->length();
1220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
12213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
12223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
12233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
1224e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(r1, Operand(expr->constant_elements()));
12256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(r3, r2, r1);
1226756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) {
1227756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    FastCloneShallowArrayStub stub(
1228756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
1229756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
1230756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1, r1, r2);
1231756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (expr->depth() > 1) {
1232e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
1233756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
1234e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
1235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1236756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    FastCloneShallowArrayStub stub(
1237756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        FastCloneShallowArrayStub::CLONE_ELEMENTS, length);
1238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
12393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
12423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
12443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
1245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < length; i++) {
12463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Expression* subexpr = subexprs->at(i);
12473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
12483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
12493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (subexpr->AsLiteral() != NULL ||
12503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        CompileTimeValue::IsCompileTimeValue(subexpr)) {
12513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      continue;
12523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
12533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
12553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(r0);
12563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
12573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(subexpr, kAccumulator);
12593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Store the subexpression value in the array's elements.
12613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ ldr(r1, MemOperand(sp));  // Copy of array literal.
12623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
12633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ str(result_register(), FieldMemOperand(r1, offset));
12653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Update the write barrier for the array store with r0 as the scratch
12673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // register.
12689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ RecordWrite(r1, Operand(offset), r2, result_register());
12693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
1272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ApplyTOS(context_);
1273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
1274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Apply(context_, r0);
12753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
12773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1279402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1280402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Comment cmnt(masm_, "[ Assignment");
1281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // on the left-hand side.
1283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->target()->IsValidLeftHandSide()) {
1284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->target());
1285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1288402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Left-hand side can only be a property, a global or a (parameter or local)
1289402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1290402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1291402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LhsKind assign_type = VARIABLE;
1292402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Property* prop = expr->target()->AsProperty();
1293402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (prop != NULL) {
1294402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    assign_type =
1295402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
1296402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1297402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1298402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate LHS expression.
1299402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1300402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1301402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Nothing to do here.
1302402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1303402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1304402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1305402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // We need the receiver both on the stack and in the accumulator.
1306402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        VisitForValue(prop->obj(), kAccumulator);
1307402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
1309402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        VisitForValue(prop->obj(), kStack);
1310402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1311402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1312402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
131325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      // We need the key and receiver on both the stack and in r0 and r1.
131425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      if (expr->is_compound()) {
131525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        VisitForValue(prop->obj(), kStack);
131625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        VisitForValue(prop->key(), kAccumulator);
131725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        __ ldr(r1, MemOperand(sp, 0));
131825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        __ push(r0);
131925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      } else {
132025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        VisitForValue(prop->obj(), kStack);
132125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        VisitForValue(prop->key(), kStack);
132225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      }
1323402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1324402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1325402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1326402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // If we have a compound assignment: Get value of LHS expression and
1327402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // store in on top of the stack.
1328402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
1329402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Location saved_location = location_;
1330402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = kStack;
1331402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    switch (assign_type) {
1332402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      case VARIABLE:
1333402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        EmitVariableLoad(expr->target()->AsVariableProxy()->var(),
1334402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                         Expression::kValue);
1335402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        break;
1336402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      case NAMED_PROPERTY:
1337402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        EmitNamedPropertyLoad(prop);
1338402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1339402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        break;
1340402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      case KEYED_PROPERTY:
1341402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        EmitKeyedPropertyLoad(prop);
1342402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1343402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        break;
1344402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1345402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = saved_location;
1346402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1347402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1348402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate RHS expression.
1349402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Expression* rhs = expr->value();
1350402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  VisitForValue(rhs, kAccumulator);
1351402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1352402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // If we have a compound assignment: Apply operator.
1353402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
1354402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Location saved_location = location_;
1355402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = kAccumulator;
1356402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    EmitBinaryOp(expr->binary_op(), Expression::kValue);
1357402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = saved_location;
1358402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1359402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Record source position before possible IC call.
1361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  SetSourcePosition(expr->position());
1362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1363402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Store the value.
1364402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1366402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                             expr->op(),
1368402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                             context_);
1369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1370402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitNamedPropertyAssignment(expr);
1372402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1373402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1374402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitKeyedPropertyAssignment(expr);
1375402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1376402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1377402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1378402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1380d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Literal* key = prop->key()->AsLiteral();
1383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(r2, Operand(key->handle()));
1384f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call load IC. It has arguments receiver and property name r0 and r2.
1385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Call(ic, RelocInfo::CODE_TARGET);
1387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1390d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
139225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Call keyed load IC. It has arguments key and receiver in r0 and r1.
1393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Call(ic, RelocInfo::CODE_TARGET);
1395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1398d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitBinaryOp(Token::Value op,
1399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     Expression::Context context) {
1400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(r1);
14016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenericBinaryOpStub stub(op, NO_OVERWRITE, r1, r0);
1402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
1403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context, r0);
1404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitAssignment(Expression* expr) {
1408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw
1409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ReferenceError' on the left-hand side.
1410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->IsValidLeftHandSide()) {
1411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr);
1412f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand side can only be a property, a global or a (parameter or local)
1416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  LhsKind assign_type = VARIABLE;
1419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = expr->AsProperty();
1420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (prop != NULL) {
1421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    assign_type = (prop->key()->IsPropertyName())
1422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ? NAMED_PROPERTY
1423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        : KEYED_PROPERTY;
1424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (assign_type) {
1427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case VARIABLE: {
1428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->AsVariableProxy()->var();
1429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect);
1430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case NAMED_PROPERTY: {
1433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(r0);  // Preserve value.
1434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitForValue(prop->obj(), kAccumulator);
1435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(r1, r0);
1436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r0);  // Restore value.
1437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
1438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ Call(ic, RelocInfo::CODE_TARGET);
1440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case KEYED_PROPERTY: {
1443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(r0);  // Preserve value.
1444f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitForValue(prop->obj(), kStack);
1445f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitForValue(prop->key(), kAccumulator);
1446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(r1, r0);
1447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r2);
1448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r0);  // Restore value.
1449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ Call(ic, RelocInfo::CODE_TARGET);
1451f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1457d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var,
1458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                               Token::Value op,
1459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                               Expression::Context context) {
1460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand sides that rewrite to explicit property accesses do not reach
1461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // here.
14623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(var != NULL);
14633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(var->is_global() || var->slot() != NULL);
1464d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
14653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (var->is_global()) {
1466d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT(!var->is_this());
1467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Assignment to a global variable.  Use inline caching for the
1468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // assignment.  Right-hand-side value is passed in r0, variable name in
1469402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // r2, and the global object in r1.
14703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(r2, Operand(var->name()));
1471402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ ldr(r1, CodeGenerator::GlobalObject());
14723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
14733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Call(ic, RelocInfo::CODE_TARGET);
1474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) {
1476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Perform the assignment for non-const variables and for initialization
1477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // of const variables.  Const assignments are simply skipped.
1478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Label done;
1479d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Slot* slot = var->slot();
1480d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
1481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
1482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      case Slot::LOCAL:
1483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Detect const reinitialization by checking for the hole value.
1485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ ldr(r1, MemOperand(fp, SlotOffset(slot)));
1486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ cmp(r1, ip);
1488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ b(ne, &done);
1489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment.
1491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
1492d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1493d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1494d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT: {
1495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        MemOperand target = EmitSlotSearch(slot, r1);
1496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Detect const reinitialization by checking for the hole value.
1498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ ldr(r2, target);
1499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ cmp(r2, ip);
1501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ b(ne, &done);
1502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment and issue the write barrier.
1504e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ str(result_register(), target);
1505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // RecordWrite may destroy all its register arguments.
1506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ mov(r3, result_register());
1507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
15089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        __ RecordWrite(r1, Operand(offset), r2, r3);
1509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
15103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
1511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP:
1513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Call the runtime for the assignment.  The runtime will ignore
1514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // const reinitialization.
1515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(r0);  // Value.
1516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(r0, Operand(slot->var()->name()));
1517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ Push(cp, r0);  // Context and name.
1518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // The runtime will ignore const redeclaration.
1520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else {
1522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kStoreContextSlot, 3);
1523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
15253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&done);
15273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1529402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Apply(context, result_register());
15303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
15313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1533d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
1535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
1536d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop != NULL);
1537d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop->key()->AsLiteral() != NULL);
15383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1540d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1543e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1544e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ ldr(ip, MemOperand(sp, kPointerSize));  // Receiver is now under value.
1545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(ip);
1546d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1547e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1550e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
1553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load receiver to r1. Leave a copy in the stack if needed for turning the
1554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // receiver into fast case.
1555402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->ends_initialization_block()) {
1556402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ ldr(r1, MemOperand(sp));
1557402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  } else {
1558402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop(r1);
1559402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1560402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1561d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Call(ic, RelocInfo::CODE_TARGET);
1563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1564d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1565d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1566d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(r0);  // Result of assignment, saved even if not needed.
1567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Receiver is under the result value.
1568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(ip, MemOperand(sp, kPointerSize));
1569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(ip);
1570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(r0);
1572402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    DropAndApply(1, context_, r0);
1573402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  } else {
1574402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Apply(context_, r0);
1575d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1576d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1579d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1580d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
1581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Receiver is now under the key and value.
1588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(ip, MemOperand(sp, 2 * kPointerSize));
1589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(ip);
1590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r1);  // Key.
1597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load receiver to r2. Leave a copy in the stack if needed for turning the
1598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // receiver into fast case.
1599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (expr->ends_initialization_block()) {
1600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(r2, MemOperand(sp));
1601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ pop(r2);
1603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Call(ic, RelocInfo::CODE_TARGET);
1607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1608d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(r0);  // Result of assignment, saved even if not needed.
1611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Receiver is under the result value.
1612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(ip, MemOperand(sp, kPointerSize));
1613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(ip);
1614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(r0);
1616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    DropAndApply(1, context_, r0);
1617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Apply(context_, r0);
1619d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1620d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1621d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1623d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) {
1624d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Property");
1625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* key = expr->key();
1626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (key->IsPropertyName()) {
1628f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(expr->obj(), kAccumulator);
1629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitNamedPropertyLoad(expr);
1630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Apply(context_, r0);
1631d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(expr->obj(), kStack);
163325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    VisitForValue(expr->key(), kAccumulator);
163425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ pop(r1);
1635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitKeyedPropertyLoad(expr);
163625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    Apply(context_, r0);
1637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1640d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr,
1641402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                       Handle<Object> name,
1642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       RelocInfo::Mode mode) {
1643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the IC.
1644d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
16453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
16463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
1647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
16483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1649402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(r2, Operand(name));
1650d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
16513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SetSourcePosition(expr->position());
16523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the IC initialization code.
1653402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1654402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
1655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Call(ic, mode);
1656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Restore context register.
1657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1658402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Apply(context_, r0);
1659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1660d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1661d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
16629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
16639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                            Expression* key,
16649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                            RelocInfo::Mode mode) {
16659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Code common for calls using the IC.
16669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ZoneList<Expression*>* args = expr->arguments();
16679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  int arg_count = args->length();
16689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  for (int i = 0; i < arg_count; i++) {
16699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    VisitForValue(args->at(i), kStack);
16709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
16719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  VisitForValue(key, kAccumulator);
16729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ mov(r2, r0);
16739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Record source position for debugger.
16749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  SetSourcePosition(expr->position());
16759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Call the IC initialization code.
16769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
16779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count,
16789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                                              in_loop);
16799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ Call(ic, mode);
16809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Restore context register.
16819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
16829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Apply(context_, r0);
16839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
16849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
16859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1686d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) {
1687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the call stub.
1688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
1690d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
1691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
1692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
1694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
1695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ CallStub(&stub);
16983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore context register.
16993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1700e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  DropAndApply(1, context_, r0);
1701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1704d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) {
1705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Call");
1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* fun = expr->expression();
1707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Variable* var = fun->AsVariableProxy()->AsVariable();
1708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (var != NULL && var->is_possibly_eval()) {
1710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // In a call to eval, we first call %ResolvePossiblyDirectEval to
1711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // resolve the function we need to call and the receiver of the
1712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // call.  Then we call the resolved function using the given
1713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // arguments.
1714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(fun, kStack);
1715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
1716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(r2);  // Reserved receiver slot.
1717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push the arguments.
1719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    ZoneList<Expression*>* args = expr->arguments();
1720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    int arg_count = args->length();
1721f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    for (int i = 0; i < arg_count; i++) {
1722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitForValue(args->at(i), kStack);
1723f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push copy of the function - found below the arguments.
1726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
1727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(r1);
1728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push copy of the first argument or undefined if it doesn't exist.
1730f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (arg_count > 0) {
1731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
1732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(r1);
1733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
1734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(r2);
1735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1736f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push the receiver of the enclosing function and do runtime call.
1738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(r1, MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize));
1739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(r1);
1740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
1741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The runtime call returns a pair of values in r0 (function) and
1743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // r1 (receiver). Touch up the stack with the right values.
1744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
1745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ str(r1, MemOperand(sp, arg_count * kPointerSize));
1746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Record source position for debugger.
1748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    SetSourcePosition(expr->position());
1749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
1752f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Restore context register.
1753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    DropAndApply(1, context_, r0);
1755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (var != NULL && !var->is_this() && var->is_global()) {
1756402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Push global object as receiver for the call IC.
1757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(r0, CodeGenerator::GlobalObject());
1758402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(r0);
1759e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
1760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (var != NULL && var->slot() != NULL &&
1761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block             var->slot()->type() == Slot::LOOKUP) {
1762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Call to a lookup slot (dynamically introduced variable).  Call the
1763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // runtime to find the function to call (returned in eax) and the object
1764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // holding it (returned in edx).
1765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(context_register());
1766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r2, Operand(var->name()));
1767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(r2);
1768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
1769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(r0);  // Function.
1770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(r1);  // Receiver.
1771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitCallWithStub(expr);
1772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (fun->AsProperty() != NULL) {
1773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to an object property.
1774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Property* prop = fun->AsProperty();
1775d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = prop->key()->AsLiteral();
1776d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (key != NULL && key->handle()->IsSymbol()) {
1777d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Call to a named property, use call IC.
1778e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->obj(), kStack);
1779e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
17819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Call to a keyed property.
17829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // For a synthetic property use keyed load IC followed by function call,
17839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // for a regular property use keyed CallIC.
1784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->obj(), kStack);
178525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      if (prop->is_synthetic()) {
17869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        VisitForValue(prop->key(), kAccumulator);
17879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // Record source code position for IC call.
17889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        SetSourcePosition(prop->position());
178925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        __ pop(r1);  // We do not need to keep the receiver.
179025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
17919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
17929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        __ Call(ic, RelocInfo::CODE_TARGET);
179325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        // Push result (function).
179425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        __ push(r0);
179525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        // Push Global receiver.
1796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ ldr(r1, CodeGenerator::GlobalObject());
1797e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
179825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        __ push(r1);
17999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        EmitCallWithStub(expr);
1800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
18019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
1802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
18043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
1805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to some other expression.  If the expression is an anonymous
1806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // function literal not called in a loop, mark it as one that should
1807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // also use the fast code generator.
1808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    FunctionLiteral* lit = fun->AsFunctionLiteral();
1809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (lit != NULL &&
1810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        lit->name()->Equals(Heap::empty_string()) &&
1811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        loop_depth() == 0) {
1812d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      lit->set_try_full_codegen(true);
1813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1814e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(fun, kStack);
1815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load global receiver object.
1816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(r1, CodeGenerator::GlobalObject());
1817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
1818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(r1);
1819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit function call.
1820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    EmitCallWithStub(expr);
18213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
18223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
18233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1825d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
1826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
1827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
1828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
1829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
1830d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push function on the stack.
1831e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  VisitForValue(expr->expression(), kStack);
1832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push global object (receiver).
1834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ ldr(r0, CodeGenerator::GlobalObject());
1835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ push(r0);
1836d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
1837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
1839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
1840e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
1841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
1844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
1845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
1846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Load function, arg_count into r1 and r0.
1848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(r0, Operand(arg_count));
1849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Function is in sp[arg_count + 1].
1850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
1851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
1853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
1854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Replace function on TOS with result in r0, or pop it.
1856e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  DropAndApply(1, context_, r0);
1857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
1861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
1864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
1868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, if_true);
1871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(if_false);
1872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
1874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
1878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
1881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
1885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ tst(r0, Operand(kSmiTagMask | 0x80000000));
1888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, if_true);
1889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(if_false);
1890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
1892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
1896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
1899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
1903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, if_false);
1905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(ip, Heap::kNullValueRootIndex);
1906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, ip);
1907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, if_true);
1908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
1909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Undetectable objects behave like undefined when tested with typeof.
1910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
1911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ tst(r1, Operand(1 << Map::kIsUndetectable));
1912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, if_false);
1913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset));
1914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
1915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(lt, if_false);
1916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));
1917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(le, if_true);
1918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(if_false);
1919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
1921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
19253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(args->length() == 1);
19263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  VisitForValue(args->at(0), kAccumulator);
19283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label materialize_true, materialize_false;
19303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_true = NULL;
19313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_false = NULL;
19323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
19333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ BranchOnSmi(r0, if_false);
19353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
19363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ b(ge, if_true);
19373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ b(if_false);
19383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Apply(context_, if_true, if_false);
19403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
19413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
1944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
1947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
1951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, if_false);
1954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
1955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
1956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ tst(r1, Operand(1 << Map::kIsUndetectable));
1957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, if_true);
1958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(if_false);
1959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
1961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1964756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
1965756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    ZoneList<Expression*>* args) {
1966756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1967756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ASSERT(args->length() == 1);
1968756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1969756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  VisitForValue(args->at(0), kAccumulator);
1970756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1971756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label materialize_true, materialize_false;
1972756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_true = NULL;
1973756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_false = NULL;
1974756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1975756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1976756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only
1977756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // used in a few functions in runtime.js which should not normally be hit by
1978756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // this compiler.
1979756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ jmp(if_false);
1980756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Apply(context_, if_true, if_false);
1981756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
1982756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1983756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
1985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
1988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
1992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, if_false);
1995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, if_true);
1997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(if_false);
1998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
2004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, if_false);
2014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
2015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, if_true);
2016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(if_false);
2017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
2023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, if_false);
2033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
2034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, if_true);
2035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(if_false);
2036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
2043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the frame pointer for the calling frame.
2051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Skip the arguments adaptor frame if it exists.
2054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label check_frame_marker;
2055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset));
2056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &check_frame_marker);
2058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset));
2059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check the marker in the calling frame.
2061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&check_frame_marker);
2062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
2063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
2064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, if_true);
2065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(if_false);
2066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
2072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the two objects into registers and perform the comparison.
2075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kAccumulator);
2077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r1);
2084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, r1);
2085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, if_true);
2086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(if_false);
2087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ArgumentsAccessStub expects the key in edx and the formal
2096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // parameter count in eax.
2097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r1, r0);
2099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
2100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label exit;
2110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the number of formal parameters.
2111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
2112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the calling frame is an arguments adaptor frame.
2114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
2116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2117f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &exit);
2118f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Arguments adaptor case: Read the arguments length from the
2120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // adaptor frame.
2121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
2122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
2124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
2129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, null, function, non_function_constructor;
2131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, we return null.
2135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, &null);
2136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check that the object is a JS object but take special care of JS
2138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // functions to make sure they have 'Function' as their class.
2139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE);  // Map is now in r0.
2140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(lt, &null);
2141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // As long as JS_FUNCTION_TYPE is the last instance type and it is
2143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
2144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // LAST_JS_OBJECT_TYPE.
2145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
2146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
2147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, Operand(JS_FUNCTION_TYPE));
2148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, &function);
2149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the constructor in the map is a function.
2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, Map::kConstructorOffset));
2152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &non_function_constructor);
2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r0 now contains the constructor function. Grab the
2156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // instance class name from there.
2157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
2158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset));
2159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(&done);
2160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Functions have class 'Function'.
2162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&function);
2163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex);
2164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Objects with a non-function constructor have class 'Object'.
2167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&non_function_constructor);
2168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex);
2169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-JS objects have class null.
2172f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&null);
2173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(r0, Heap::kNullValueRootIndex);
2174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // All done.
2176f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
2183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Conditionally generate a log call.
2184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Args:
2185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   0 (literal string): The type of logging (corresponds to the flags).
2186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     This is used to determine whether or not to generate the log call.
2187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   1 (string): Format string.  Access the string at argument index 2
2188f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     with '%2s' (see Logger::LogRuntime for all the formats).
2189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   2 (array): Arguments to the format string.
2190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 3);
2191f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING
2192f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
2193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(args->at(1), kStack);
2194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(args->at(2), kStack);
2195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLog, 2);
2196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif
2198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Finally, we're expected to leave a value on the top of the stack.
2199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
2200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
2205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label slow_allocate_heapnumber;
2208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label heapnumber_allocated;
2209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
22109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
22119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber);
2212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&heapnumber_allocated);
2213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&slow_allocate_heapnumber);
22153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Allocate a heap number.
22163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CallRuntime(Runtime::kNumberAlloc, 0);
2217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r4, Operand(r0));
2218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&heapnumber_allocated);
2220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert 32 random bits in r0 to 0.(32 random bits) in a double
2222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // by computing:
2223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
2224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (CpuFeatures::IsSupported(VFP3)) {
2225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ PrepareCallCFunction(0, r1);
2226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallCFunction(ExternalReference::random_uint32_function(), 0);
2227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CpuFeatures::Scope scope(VFP3);
2229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0x41300000 is the top half of 1.0 x 2^20 as a double.
2230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Create this constant using mov/orr to avoid PC relative load.
2231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r1, Operand(0x41000000));
2232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ orr(r1, r1, Operand(0x300000));
2233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Move 0x41300000xxxxxxxx (x = random bits) to VFP.
2234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ vmov(d7, r0, r1);
2235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Move 0x4130000000000000 to VFP.
2236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r0, Operand(0));
2237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ vmov(d8, r0, r1);
2238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Subtract and store the result in the heap number.
2239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ vsub(d7, d7, d8);
2240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ sub(r0, r4, Operand(kHeapObjectTag));
2241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ vstr(d7, r0, HeapNumber::kValueOffset);
2242f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r0, r4);
2243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
2244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r0, Operand(r4));
2245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ PrepareCallCFunction(1, r1);
2246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallCFunction(
2247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ExternalReference::fill_heap_number_with_random_function(), 1);
2248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
2255f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SubStringStub stub;
2257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
2258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(2), kStack);
2261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
2267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  RegExpExecStub stub;
2269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 4);
2270f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(2), kStack);
2273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(3), kStack);
2274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
2280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);  // Load the object.
2283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
2285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi return the object.
2286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, &done);
2287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the object.
2288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE);
2289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &done);
2290f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
2291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2293f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
2298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the runtime function.
2299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_pow, 2);
2303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
2308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);  // Load the object.
2311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kAccumulator);  // Load the value.
2312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r1);  // r0 = value. r1 = object.
2313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
2315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, return the value.
2316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r1, &done);
2317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the value.
2319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE);
2320f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &done);
2321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Store the value.
2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the write barrier.  Save the value as it will be
2325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // overwritten by the write barrier code and is needed afterward.
23269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ RecordWrite(r1, Operand(JSValue::kValueOffset - kHeapObjectTag), r2, r3);
2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
2334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 1);
2335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
2337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  NumberToStringStub stub;
2340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2343f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
2346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
23517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharFromCodeGenerator generator(r0, r1);
23527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
23537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
2354f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
23567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
2357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
23597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Apply(context_, r1);
2360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
23647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
23657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  VisitForValue(args->at(0), kStack);
23677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  VisitForValue(args->at(1), kAccumulator);
23687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = r1;
23707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = r0;
23717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch = r2;
23727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = r3;
23737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
23757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
23777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
23787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
23797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharCodeAtGenerator generator(object,
23807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      index,
23817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      scratch,
23827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      result,
23837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
23847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
23857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &index_out_of_range,
23867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      STRING_INDEX_IS_NUMBER);
23877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
23887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
23897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
23917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
23927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // NaN.
23937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kNanValueRootIndex);
23947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
23957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
23977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Load the undefined value into the result register, which will
23987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // trigger conversion.
23997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
24007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
24017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
24037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
24047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
24067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Apply(context_, result);
24077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
24087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
24117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
24127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  VisitForValue(args->at(0), kStack);
24147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  VisitForValue(args->at(1), kAccumulator);
24157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = r1;
24177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = r0;
24187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch1 = r2;
24197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch2 = r3;
24207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = r0;
24217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
24237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
24257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
24267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
24277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharAtGenerator generator(object,
24287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  index,
24297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  scratch1,
24307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  scratch2,
24317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  result,
24327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
24337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
24347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &index_out_of_range,
24357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  STRING_INDEX_IS_NUMBER);
24367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
24377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
24387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
24407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
24417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the empty string.
24427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kEmptyStringRootIndex);
24437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
24447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
24467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move smi zero into the result register, which will trigger
24477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // conversion.
24487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(result, Operand(Smi::FromInt(0)));
24497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
24507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
24527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
24537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
24557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Apply(context_, result);
2456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
2460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringAddStub stub(NO_STRING_ADD_FLAGS);
2466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
2472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringCompareStub stub;
2478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
2484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the runtime.
2485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_sin, 1);
2488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
2493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the runtime.
2494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_cos, 1);
2497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
2502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the runtime function.
2503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2505f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_sqrt, 1);
2506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
2511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() >= 2);
2512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int arg_count = args->length() - 2;  // For receiver and function.
2514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);  // Receiver.
2515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < arg_count; i++) {
2516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(args->at(i + 1), kStack);
2517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(arg_count + 1), kAccumulator);  // Function.
2519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // InvokeFunction requires function in r1. Move it in there.
2521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!result_register().is(r1)) __ mov(r1, result_register());
2522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ParameterCount count(arg_count);
2523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeFunction(r1, count, CALL_FUNCTION);
2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
2530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
2531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(2), kStack);
2534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kRegExpConstructResult, 3);
2535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(2), kStack);
2544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kSwapElements, 3);
2545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
2550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_NE(NULL, args->at(0)->AsLiteral());
2553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
2554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<FixedArray> jsfunction_result_caches(
2556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Top::global_context()->jsfunction_result_caches());
2557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (jsfunction_result_caches->length() <= cache_id) {
2558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Abort("Attempt to use undefined cache.");
2559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
2560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Apply(context_, r0);
2561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kAccumulator);
2565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register key = r0;
2567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register cache = r1;
2568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(cache, CodeGenerator::ContextOperand(cp, Context::GLOBAL_INDEX));
2569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(cache, FieldMemOperand(cache, GlobalObject::kGlobalContextOffset));
2570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(cache,
2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         CodeGenerator::ContextOperand(
2572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke             cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
2573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(cache,
2574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, not_found;
2578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // tmp now holds finger offset as a smi.
2579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
2580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset));
2581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r2 now holds finger offset as a smi.
2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
2583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r3 now points to the start of fixed array elements.
2584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2 - kSmiTagSize, PreIndex));
2585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Note side effect of PreIndex: r3 now points to the key of the pair.
2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(key, r2);
2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &not_found);
2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, MemOperand(r3, kPointerSize));
2590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(&done);
2591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&not_found);
2593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call runtime to perform the lookup.
2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(cache, key);
2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetFromCache, 2);
2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, r0);
2599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2602bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
2603bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT_EQ(2, args->length());
2604bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2605bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register right = r0;
2606bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register left = r1;
2607bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register tmp = r2;
2608bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register tmp2 = r3;
2609bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2610bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  VisitForValue(args->at(0), kStack);
2611bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  VisitForValue(args->at(1), kAccumulator);
2612bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(left);
2613bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2614bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label done, fail, ok;
2615bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(left, Operand(right));
2616bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(eq, &ok);
2617bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Fail if either is a non-HeapObject.
2618bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ and_(tmp, left, Operand(right));
2619bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ tst(tmp, Operand(kSmiTagMask));
2620bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(eq, &fail);
2621bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ldr(tmp, FieldMemOperand(left, HeapObject::kMapOffset));
2622bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ldrb(tmp2, FieldMemOperand(tmp, Map::kInstanceTypeOffset));
2623bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(tmp2, Operand(JS_REGEXP_TYPE));
2624bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(ne, &fail);
2625bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
2626bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(tmp, Operand(tmp2));
2627bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(ne, &fail);
2628bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ldr(tmp, FieldMemOperand(left, JSRegExp::kDataOffset));
2629bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ldr(tmp2, FieldMemOperand(right, JSRegExp::kDataOffset));
2630bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(tmp, tmp2);
2631bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(eq, &ok);
2632bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&fail);
2633bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ LoadRoot(r0, Heap::kFalseValueRootIndex);
2634bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ jmp(&done);
2635bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&ok);
2636bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ LoadRoot(r0, Heap::kTrueValueRootIndex);
2637bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&done);
2638bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2639bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Apply(context_, r0);
2640bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
2641bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2642bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2643d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
2644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<String> name = expr->name();
2645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (name->length() > 0 && name->Get(0) == '_') {
2646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ InlineRuntimeCall");
2647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitInlineRuntimeCall(expr);
2648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ CallRuntime");
26523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* args = expr->arguments();
26533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2654d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
2655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Prepare for calling JS runtime function.
2656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(r0, CodeGenerator::GlobalObject());
2657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset));
2658402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(r0);
2659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
26603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
26613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Push the arguments ("left-to-right").
26623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
26633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
2664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
2665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2666d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
2668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call the JS runtime function.
2669402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(r2, Operand(expr->name()));
2670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
2671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                                           NOT_IN_LOOP);
2672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ Call(ic, RelocInfo::CODE_TARGET);
2673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Restore context register.
2674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
2676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call the C runtime function.
2677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(expr->function(), arg_count);
2678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2679402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Apply(context_, r0);
2680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2681d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2683d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
2685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Token::DELETE: {
2686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
2687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Property* prop = expr->expression()->AsProperty();
2688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
2689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (prop == NULL && var == NULL) {
2690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Result of deleting non-property, non-variable reference is true.
2691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The subexpression may have side effects.
2692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForEffect(expr->expression());
2693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        Apply(context_, true);
2694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else if (var != NULL &&
2695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 !var->is_global() &&
2696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 var->slot() != NULL &&
2697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 var->slot()->type() != Slot::LOOKUP) {
2698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Result of deleting non-global, non-dynamic variables is false.
2699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The subexpression does not have side effects.
2700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        Apply(context_, false);
2701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else {
2702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Property or variable reference.  Call the delete builtin with
2703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // object and property name as arguments.
2704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (prop != NULL) {
2705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          VisitForValue(prop->obj(), kStack);
2706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          VisitForValue(prop->key(), kStack);
2707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (var->is_global()) {
2708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ ldr(r1, CodeGenerator::GlobalObject());
2709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ mov(r0, Operand(var->name()));
2710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ Push(r1, r0);
2711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else {
2712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Non-global variable.  Call the runtime to look up the context
2713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // where the variable was introduced.
2714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(context_register());
2715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ mov(r2, Operand(var->name()));
2716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(r2);
2717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kLookupContext, 2);
2718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(r0);
2719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ mov(r2, Operand(var->name()));
2720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(r2);
2721f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
2722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
2723f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        Apply(context_, r0);
2724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
2725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
2729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
2730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
2731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (context_) {
2732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kUninitialized:
2733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
2734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
2735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kEffect:
2736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
2737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kValue:
2738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex);
2739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          switch (location_) {
2740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kAccumulator:
2741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
2742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kStack:
2743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ push(result_register());
2744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
2745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
2746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
2747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kTestValue:
2748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Value is false so it's needed.
2749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex);
2750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          switch (location_) {
2751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kAccumulator:
2752e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
2753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kStack:
2754e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ push(result_register());
2755e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
2756e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
2757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Fall through.
2758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case Expression::kTest:
2759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kValueTest:
2760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ jmp(false_label_);
2761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
2762d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
2767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label materialize_true, materialize_false;
2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label* if_true = NULL;
2770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label* if_false = NULL;
2771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Notice that the labels are swapped.
2773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true);
2774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2775e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForControl(expr->expression(), if_true, if_false);
2776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2777e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Apply(context_, if_false, if_true);  // Labels swapped.
2778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2779d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
2782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
2783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      VariableProxy* proxy = expr->expression()->AsVariableProxy();
2784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (proxy != NULL &&
2785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          !proxy->var()->is_this() &&
2786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          proxy->var()->is_global()) {
2787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        Comment cmnt(masm_, "Global variable");
2788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ ldr(r0, CodeGenerator::GlobalObject());
2789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ mov(r2, Operand(proxy->name()));
2790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
2791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Use a regular load, not a contextual load, to avoid a reference
2792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // error.
2793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Call(ic, RelocInfo::CODE_TARGET);
2794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(r0);
2795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else if (proxy != NULL &&
2796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                 proxy->var()->slot() != NULL &&
2797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                 proxy->var()->slot()->type() == Slot::LOOKUP) {
2798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ mov(r0, Operand(proxy->name()));
2799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ Push(cp, r0);
2800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(r0);
2802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
2803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // This expression cannot throw a reference error at the top level.
2804e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(expr->expression(), kStack);
2805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallRuntime(Runtime::kTypeof, 1);
2808e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Apply(context_, r0);
2809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
28103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
2811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2812d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Token::ADD: {
2813d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Comment cmt(masm_, "[ UnaryOperation (ADD)");
2814d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      VisitForValue(expr->expression(), kAccumulator);
2815d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Label no_conversion;
2816d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ tst(result_register(), Operand(kSmiTagMask));
2817d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ b(eq, &no_conversion);
2818d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ push(r0);
2819d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
2820d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ bind(&no_conversion);
2821d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Apply(context_, result_register());
2822d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      break;
2823d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
2824d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
28254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::SUB: {
28264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (SUB)");
2827ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke      bool can_overwrite =
28284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          (expr->expression()->AsBinaryOperation() != NULL &&
28294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
2830ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke      UnaryOverwriteMode overwrite =
2831ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke          can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
28324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      GenericUnaryOpStub stub(Token::SUB, overwrite);
28334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // GenericUnaryOpStub expects the argument to be in the
28344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // accumulator register r0.
28354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      VisitForValue(expr->expression(), kAccumulator);
28364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
28374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Apply(context_, r0);
28384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
28394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
28404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
28414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::BIT_NOT: {
28424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
2843ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke      bool can_overwrite =
28444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          (expr->expression()->AsBinaryOperation() != NULL &&
28454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
2846ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke      UnaryOverwriteMode overwrite =
2847ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke          can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
28484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
28494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // GenericUnaryOpStub expects the argument to be in the
28504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // accumulator register r0.
28514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      VisitForValue(expr->expression(), kAccumulator);
28524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Avoid calling the stub for Smis.
28534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Label smi, done;
2854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ BranchOnSmi(result_register(), &smi);
28554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Non-smi: call stub leaving result in accumulator register.
28564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
28574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ b(&done);
28584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Perform operation directly on Smis.
28594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ bind(&smi);
28604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ mvn(result_register(), Operand(result_register()));
28614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Bit-clear inverted smi-tag.
28624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ bic(result_register(), result_register(), Operand(kSmiTagMask));
28634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ bind(&done);
28644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Apply(context_, result_register());
28654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
28664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
28674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
2868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
2869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
28703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2874d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
2875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CountOperation");
2876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
2877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // as the left-hand side.
2878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->expression()->IsValidLeftHandSide()) {
2879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->expression());
2880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2883e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Expression can only be a property, a global or a (parameter or local)
2884e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
2885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
2886e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LhsKind assign_type = VARIABLE;
2887e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
2888e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In case of a property we use the uninitialized expression context
2889e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // of the key to detect a named property.
2890e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (prop != NULL) {
2891e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    assign_type =
2892e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
2893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2894e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2895e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
2896e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
2897e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
2898e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Location saved_location = location_;
2899d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    location_ = kAccumulator;
2900e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
2901e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     Expression::kValue);
2902e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    location_ = saved_location;
29033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2904e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
2905e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (expr->is_postfix() && context_ != Expression::kEffect) {
2906e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(ip, Operand(Smi::FromInt(0)));
2907e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ push(ip);
2908e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2909e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (assign_type == NAMED_PROPERTY) {
2910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Put the object both on the stack and in the accumulator.
2911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitForValue(prop->obj(), kAccumulator);
2912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(r0);
2913e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitNamedPropertyLoad(prop);
2914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
2915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitForValue(prop->obj(), kStack);
291625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      VisitForValue(prop->key(), kAccumulator);
291725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      __ ldr(r1, MemOperand(sp, 0));
291825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      __ push(r0);
2919e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitKeyedPropertyLoad(prop);
2920e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2923d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Call ToNumber only if operand is not a smi.
2924d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label no_conversion;
2925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, &no_conversion);
2926d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ push(r0);
2927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
2928d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&no_conversion);
2929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2930e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
2931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
2932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    switch (context_) {
2933e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kUninitialized:
2934e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        UNREACHABLE();
2935e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kEffect:
2936e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Do not save result.
2937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        break;
2938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kValue:
2939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kTest:
2940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kValueTest:
2941e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kTestValue:
2942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Save the result on the stack. If we have a named or keyed property
2943e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // we store the result under the receiver that is currently on top
2944e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // of the stack.
2945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        switch (assign_type) {
2946e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          case VARIABLE:
2947e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            __ push(r0);
2948e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            break;
2949e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          case NAMED_PROPERTY:
2950e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            __ str(r0, MemOperand(sp, kPointerSize));
2951e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            break;
2952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          case KEYED_PROPERTY:
2953e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            __ str(r0, MemOperand(sp, 2 * kPointerSize));
2954e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            break;
2955e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
2956e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        break;
2957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2960d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2961d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Inline smi case if we are in a loop.
2962d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label stub_call, done;
296310e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu  int count_value = expr->op() == Token::INC ? 1 : -1;
2964d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (loop_depth() > 0) {
296510e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu    __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC);
2966d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ b(vs, &stub_call);
2967d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // We could eliminate this smi check if we split the code at
2968d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // the first smi check before calling ToNumber.
2969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ BranchOnSmi(r0, &done);
2970d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ bind(&stub_call);
2971d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Call stub. Undo operation first.
297210e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu    __ sub(r0, r0, Operand(Smi::FromInt(count_value)));
2973d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
297410e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu  __ mov(r1, Operand(Smi::FromInt(count_value)));
29756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0);
2976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
2977d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
2978e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2979e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in r0.
2980e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
2981e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case VARIABLE:
2982e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
2983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
2984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               Token::ASSIGN,
2985e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               Expression::kEffect);
2986e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // For all contexts except kEffect: We have the result on
2987e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
2988e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (context_ != Expression::kEffect) {
2989e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          ApplyTOS(context_);
2990e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
2991e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
2992e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
2993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               Token::ASSIGN,
2994e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               context_);
2995e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
2996d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2997e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
2998e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
2999402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ pop(r1);
3000e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
3001e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Call(ic, RelocInfo::CODE_TARGET);
3002e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
3003e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (context_ != Expression::kEffect) {
3004e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          ApplyTOS(context_);
3005e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3006e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
3007402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        Apply(context_, r0);
3008e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3009d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3010d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3011e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
3012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r1);  // Key.
3013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r2);  // Receiver.
3014e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
3015e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Call(ic, RelocInfo::CODE_TARGET);
3016e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
3017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (context_ != Expression::kEffect) {
3018e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          ApplyTOS(context_);
3019e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3020e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
3021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        Apply(context_, r0);
3022e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3023d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3024d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
30253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
30263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
30273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
30283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3029d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
3030d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ BinaryOperation");
3031d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
3032d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::COMMA:
3033e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->left());
3034d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Visit(expr->right());
3035d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3036d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3037d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::OR:
3038d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::AND:
3039d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      EmitLogicalOperation(expr);
3040d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3041d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3042d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::ADD:
3043d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::SUB:
3044d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::DIV:
3045d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::MOD:
3046d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::MUL:
3047d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::BIT_OR:
3048d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::BIT_AND:
3049d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::BIT_XOR:
3050d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::SHL:
3051d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::SHR:
3052e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::SAR:
3053e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->left(), kStack);
3054e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kAccumulator);
3055e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitBinaryOp(expr->op(), context_);
3056d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3058d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
3059d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
3060d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3061d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3062d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
30633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNullCompare(bool strict,
3065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Register obj,
3066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Register null_const,
3067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Label* if_true,
3068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Label* if_false,
3069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Register scratch) {
3070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(obj, null_const);
3071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (strict) {
3072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(eq, if_true);
3073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
3074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(eq, if_true);
3075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
3076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ cmp(obj, ip);
3077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(eq, if_true);
3078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ BranchOnSmi(obj, if_false);
3079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // It can be an undetectable object.
3080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
3081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
3082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ tst(scratch, Operand(1 << Map::kIsUndetectable));
3083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(ne, if_true);
3084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
3086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3089d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
3090d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
3091e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3092e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
3093e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
3094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
3098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
3099d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  VisitForValue(expr->left(), kStack);
3101d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
3102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
3103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kStack);
3104d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ InvokeBuiltin(Builtins::IN, CALL_JS);
3105d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ LoadRoot(ip, Heap::kTrueValueRootIndex);
3106d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ cmp(r0, ip);
3107e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ b(eq, if_true);
3108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
3109d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3110d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3111d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
3112e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kStack);
3113d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      InstanceofStub stub;
3114d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
3115d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ tst(r0, r0);
3116e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ b(eq, if_true);  // The stub returns 0 for true.
3117e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
3118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3119d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3120d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
3122e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kAccumulator);
3123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Condition cc = eq;
3124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      bool strict = false;
3125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (expr->op()) {
3126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::EQ_STRICT:
3127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          strict = true;
3128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Fall through
3129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case Token::EQ: {
3130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = eq;
3131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(r1);
3132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // If either operand is constant null we do a fast compare
3133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // against null.
3134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          Literal* right_literal = expr->right()->AsLiteral();
3135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          Literal* left_literal = expr->left()->AsLiteral();
3136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (right_literal != NULL && right_literal->handle()->IsNull()) {
3137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            EmitNullCompare(strict, r1, r0, if_true, if_false, r2);
3138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Apply(context_, if_true, if_false);
3139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            return;
3140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          } else if (left_literal != NULL && left_literal->handle()->IsNull()) {
3141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            EmitNullCompare(strict, r0, r1, if_true, if_false, r2);
3142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Apply(context_, if_true, if_false);
3143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            return;
3144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          }
3145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
3147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LT:
3148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = lt;
3149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(r1);
3150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GT:
3152e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Reverse left and right sides to obtain ECMA-262 conversion order.
3153d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = lt;
3154e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(r1, result_register());
3155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(r0);
3156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block         break;
3157d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LTE:
3158e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Reverse left and right sides to obtain ECMA-262 conversion order.
3159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = ge;
3160e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(r1, result_register());
3161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(r0);
3162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GTE:
3164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = ge;
3165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(r1);
3166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::IN:
3168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::INSTANCEOF:
3169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default:
3170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
3171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
3172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // The comparison stub expects the smi vs. smi case to be handled
3174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // before it is called.
3175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Label slow_case;
3176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ orr(r2, r0, Operand(r1));
3177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ BranchOnNotSmi(r2, &slow_case);
3178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ cmp(r1, r0);
3179e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ b(cc, if_true);
3180e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
3181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ bind(&slow_case);
31833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      CompareStub stub(cc, strict, kBothCouldBeNaN, true, r1, r0);
3184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
3185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ cmp(r0, Operand(0));
3186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ b(cc, if_true);
3187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
31883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
31893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
31903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
3192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
3193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, if_true, if_false);
3194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
31953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3197d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
3198e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
3199e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, r0);
3200e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3203d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::result_register() { return r0; }
3204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3205e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3206d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::context_register() { return cp; }
3207e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3208e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3209d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
3210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
3211e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ str(value, MemOperand(fp, frame_offset));
3212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
32133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3214e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3215d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
3216e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ldr(dst, CodeGenerator::ContextOperand(cp, context_index));
32173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
32183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3220e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ----------------------------------------------------------------------------
3221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support.
3222e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3223d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() {
3224e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(r1));
3225e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store result register while executing finally block.
3226e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
3227e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Cook return address in link register to stack (smi encoded Code* delta)
3228e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ sub(r1, lr, Operand(masm_->CodeObject()));
3229e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
3230e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, kSmiTag);
3231e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(r1, r1, Operand(r1));  // Convert to smi.
3232e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(r1);
3233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3234e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3236d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() {
3237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(r1));
3238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Restore result register from stack.
3239e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(r1);
3240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Uncook return address and return.
3241e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(result_register());
3242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
3243e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(r1, Operand(r1, ASR, 1));  // Un-smi-tag value.
3244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(pc, r1, Operand(masm_->CodeObject()));
3245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef __
3249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
32503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} }  // namespace v8::internal
3251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
3253