full-codegen-arm.cc revision 8a31eba00023874d4a1dcdc5f411cc4336776874
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
3280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "code-stubs.h"
333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "codegen-inl.h"
34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h"
35d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "debug.h"
36d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "full-codegen.h"
373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "parser.h"
386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "scopes.h"
398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#include "stub-cache.h"
403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 {
423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal {
433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_)
453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function.  On entry to the function the receiver
473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right.  The actual
483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// argument count matches the formal parameter count expected by the
493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// function.
503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are:
523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o r1: the JS function object being called (ie, ourselves)
533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o cp: our context
543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o fp: our caller's frame pointer
553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o sp: stack pointer
563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o lr: return address
573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame.  Please see JavaScriptFrameConstants in
593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-arm.h for its layout.
60756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::Generate(CompilationInfo* info) {
613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ASSERT(info_ == NULL);
623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  info_ = info;
633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  SetFunctionPosition(function());
646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comment cmnt(masm_, "[ function compiled by full code generator");
653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
66f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG
67f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (strlen(FLAG_stop_at) > 0 &&
68f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
69f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ stop("stop-at");
70f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
71f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif
72f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
73756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int locals_count = scope()->num_stack_slots();
743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
75756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ Push(lr, fp, cp, r1);
76756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (locals_count > 0) {
77756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Load undefined value here, so the value is ready for the loop
78756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // below.
79756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
80756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
81756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Adjust fp to point to caller's fp.
82756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ add(fp, sp, Operand(2 * kPointerSize));
833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
84756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  { Comment cmnt(masm_, "[ Allocate locals");
85756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (int i = 0; i < locals_count; i++) {
86756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ push(ip);
874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
88756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
89d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
90756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  bool function_in_register = true;
914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
92756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate a local context.
93756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
94756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (heap_slots > 0) {
95756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate local context");
96756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Argument to NewContext is the function, which is in r1.
97756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ push(r1);
98756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
99756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      FastNewContextStub stub(heap_slots);
100756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ CallStub(&stub);
101756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
102756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ CallRuntime(Runtime::kNewContext, 1);
103756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
104756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    function_in_register = false;
105756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Context is returned in both r0 and cp.  It replaces the context
106756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // passed to us.  It's saved in the stack and kept live in cp.
107756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
108756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Copy any necessary parameters into the context.
109756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    int num_parameters = scope()->num_parameters();
110756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (int i = 0; i < num_parameters; i++) {
1110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      Slot* slot = scope()->parameter(i)->AsSlot();
112756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      if (slot != NULL && slot->type() == Slot::CONTEXT) {
113756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
114756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick            (num_parameters - 1 - i) * kPointerSize;
115756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Load parameter from stack.
116756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ ldr(r0, MemOperand(fp, parameter_offset));
117756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Store it in the context.
118756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ mov(r1, Operand(Context::SlotOffset(slot->index())));
119756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ str(r0, MemOperand(cp, r1));
120756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Update the write barrier. This clobbers all involved
121756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // registers, so we have to use two more registers to avoid
122756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // clobbering cp.
123756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ mov(r2, Operand(cp));
124756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ RecordWrite(r2, Operand(r1), r3, r0);
125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
127756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Variable* arguments = scope()->arguments();
130756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (arguments != NULL) {
131756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Function uses arguments object.
132756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate arguments object");
133756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (!function_in_register) {
134756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      // Load this again, if it's used by the local context below.
135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
136756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
137756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ mov(r3, r1);
138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
139756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Receiver is just before the parameters on the caller's stack.
140756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    int offset = scope()->num_parameters() * kPointerSize;
141756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ add(r2, fp,
142756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           Operand(StandardFrameConstants::kCallerSPOffset + offset));
143756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ mov(r1, Operand(Smi::FromInt(scope()->num_parameters())));
144756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ Push(r3, r2, r1);
145756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
146756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Arguments to ArgumentsAccessStub:
147756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    //   function, receiver address, parameter count.
148756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The stub will rewrite receiever and parameter count if the previous
149756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // stack frame was an arguments adapter frame.
150756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
151756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
152756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Duplicate the value; move-to-slot operation might clobber registers.
153756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ mov(r3, r0);
1540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Move(arguments->AsSlot(), r0, r1, r2);
1550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot();
156756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Move(dot_arguments_slot, r3, r1, r2);
157d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  { Comment cmnt(masm_, "[ Declarations");
160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // For named function expressions, declare the function name as a
161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // constant.
162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (scope()->is_function_scope() && scope()->function() != NULL) {
163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      EmitDeclaration(scope()->function(), Variable::CONST, NULL);
164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Visit all the explicit declarations unless there is an illegal
166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // redeclaration.
167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (scope()->HasIllegalRedeclaration()) {
168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      scope()->VisitIllegalRedeclaration(this);
169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitDeclarations(scope()->declarations());
171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
172f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Check the stack for overflow or break request.
175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { Comment cmnt(masm_, "[ Stack check");
1764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ LoadRoot(r2, Heap::kStackLimitRootIndex);
1774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ cmp(sp, Operand(r2));
1784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    StackCheckStub stub;
1798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ mov(ip,
1804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           Operand(reinterpret_cast<intptr_t>(stub.GetCode().location()),
1814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                   RelocInfo::CODE_TARGET),
1824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           LeaveCC,
1834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           lo);
1848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Call(ip, lo);
1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (FLAG_trace) {
1883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CallRuntime(Runtime::kTraceEnter, 0);
1893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ Body");
192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    VisitStatements(function()->body());
194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
1983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Emit a 'return undefined' in case control fell off the end of the
1993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // body.
2003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  EmitReturnSequence();
203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() {
207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ b(&return_label_);
210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
2123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
2133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // Push the return value on the stack as the parameter.
2143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // Runtime::TraceExit returns its parameter in r0.
2153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(r0);
2163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ CallRuntime(Runtime::kTraceExit, 1);
2173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
2183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG
220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Add a label for checking the size of the code used for returning.
221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Label check_exit_codesize;
222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    masm_->bind(&check_exit_codesize);
2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Make sure that the constant pool is not emitted inside of the return
2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // sequence.
2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    { Assembler::BlockConstPoolScope block_const_pool(masm_);
2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Here we use masm_-> instead of the __ macro to avoid the code coverage
2286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // tool from instrumenting as we rely on the code size here.
2296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize;
230bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
2316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ RecordJSReturn();
2326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      masm_->mov(sp, fp);
2336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      masm_->ldm(ia_w, sp, fp.bit() | lr.bit());
2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      masm_->add(sp, sp, Operand(sp_delta));
2356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      masm_->Jump(lr);
236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG
239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Check that the size of the code used for returning matches what is
2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // expected by the debugger. If the sp_delts above cannot be encoded in the
2416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // add instruction the add will generate two instructions.
2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int return_sequence_length =
2436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        masm_->InstructionsGeneratedSince(&check_exit_codesize);
2447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    CHECK(return_sequence_length ==
2457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          Assembler::kJSReturnSequenceInstructions ||
2467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          return_sequence_length ==
2477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          Assembler::kJSReturnSequenceInstructions + 1);
2486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
25380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenFullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand(
25480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Token::Value op, Expression* left, Expression* right) {
25580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(ShouldInlineSmiCase(op));
25680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return kNoConstants;
25780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
25880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
25980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2600d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
2610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2640d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const {
2650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->Move(result_register(), slot);
2660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2690d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
2700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->Move(result_register(), slot);
2710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(result_register());
272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2750d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Slot* slot) const {
2760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
2770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->Move(result_register(), slot);
2780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->DoTest(true_label_, false_label_, fall_through_);
279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2820d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
2830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
2840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2860d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
2870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
2880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), index);
2890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
2900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2920d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
2930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
2940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), index);
2950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(result_register());
2960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
2970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2990d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
3000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (index == Heap::kUndefinedValueRootIndex ||
3010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kNullValueRootIndex ||
3020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kFalseValueRootIndex) {
3030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ b(false_label_);
3040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (index == Heap::kTrueValueRootIndex) {
3050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ b(true_label_);
3060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
3070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ LoadRoot(result_register(), index);
3080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    codegen()->DoTest(true_label_, false_label_, fall_through_);
309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3130d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
3140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3170d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
3180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Handle<Object> lit) const {
3190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), Operand(lit));
3200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3230d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
3240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Immediates can be pushed directly.
3250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), Operand(lit));
3260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(result_register());
3270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
3280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3300d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
3310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!lit->IsUndetectableObject());  // There are no undetectable literals.
3320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
3330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ b(false_label_);
3340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsTrue() || lit->IsJSObject()) {
3350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ b(true_label_);
3360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsString()) {
3370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (String::cast(*lit)->length() == 0) {
3380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ b(false_label_);
3390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
3400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ b(true_label_);
3410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
3420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsSmi()) {
3430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (Smi::cast(*lit)->value() == 0) {
3440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ b(false_label_);
3450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
3460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ b(true_label_);
3470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
3480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
3490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // For simplicity we always test the accumulator register.
3500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ mov(result_register(), Operand(lit));
3510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    codegen()->DoTest(true_label_, false_label_, fall_through_);
352d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
353d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3560d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count,
3570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                   Register reg) const {
358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(count > 0);
3590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
3600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3630d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
3640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    int count,
3650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Register reg) const {
3660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
3670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
3680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
3690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3720d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count,
3730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                       Register reg) const {
3740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
3750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (count > 1) __ Drop(count - 1);
3760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ str(reg, MemOperand(sp, 0));
377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3800d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count,
3810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                 Register reg) const {
3820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
3830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
3840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
3850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
3860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->DoTest(true_label_, false_label_, fall_through_);
3870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3900d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
3910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            Label* materialize_false) const {
3920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT_EQ(materialize_true, materialize_false);
3930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
3940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3970d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
3980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
3990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
4000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label done;
4010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
4020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
4030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ jmp(&done);
4040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
4050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
4060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4100d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
4110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
4120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
4130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label done;
4140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
4150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(ip, Heap::kTrueValueRootIndex);
4160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(ip);
4170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ jmp(&done);
4180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
4190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(ip, Heap::kFalseValueRootIndex);
4200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(ip);
4210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
4220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4250d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true,
4260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                          Label* materialize_false) const {
4270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(materialize_false == false_label_);
4280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(materialize_true == true_label_);
4290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4320d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const {
4330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4360d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
4370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
4380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
4390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), value_root_index);
4400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4430d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const {
4440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
4450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
4460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(ip, value_root_index);
4470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(ip);
4480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4510d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const {
4520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (flag) {
4530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (true_label_ != fall_through_) __ b(true_label_);
4540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
4550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (false_label_ != fall_through_) __ b(false_label_);
456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
46080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::DoTest(Label* if_true,
46180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* if_false,
46280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* fall_through) {
463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call the runtime to find the boolean value of the source and then
464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // translate it into control flow to the pair of labels.
46580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ push(result_register());
466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallRuntime(Runtime::kToBool, 1);
467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ LoadRoot(ip, Heap::kTrueValueRootIndex);
468e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(r0, ip);
46980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
47080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
47380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::Split(Condition cc,
47480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_true,
47580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_false,
47680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* fall_through) {
47780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (if_false == fall_through) {
47880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(cc, if_true);
47980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (if_true == fall_through) {
48080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(NegateCondition(cc), if_false);
48180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
48280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(cc, if_true);
48380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(if_false);
484d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
485d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
486d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
487d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
488d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (slot->type()) {
490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::PARAMETER:
491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOCAL:
492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return MemOperand(fp, SlotOffset(slot));
493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::CONTEXT: {
494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      int context_chain_length =
4953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          scope()->ContextChainLength(slot->var()->scope());
496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ LoadContext(scratch, context_chain_length);
49759151504615d929945dc59db37bf1166937748c6Steve Block      return ContextOperand(scratch, slot->index());
498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOOKUP:
500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  UNREACHABLE();
503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return MemOperand(r0, 0);
504e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
507d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) {
508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Use destination as scratch.
509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand slot_operand = EmitSlotSearch(source, destination);
510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ldr(destination, slot_operand);
511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
514d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst,
515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register src,
516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch1,
517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch2) {
518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(dst->type() != Slot::LOOKUP);  // Not yet implemented.
519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!scratch1.is(src) && !scratch2.is(src));
520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(dst, scratch1);
521e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ str(src, location);
522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
523e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (dst->type() == Slot::CONTEXT) {
5249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ RecordWrite(scratch1,
5259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                   Operand(Context::SlotOffset(dst->index())),
5269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                   scratch2,
5279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                   src);
528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitDeclaration(Variable* variable,
533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Variable::Mode mode,
534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        FunctionLiteral* function) {
535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Declaration");
536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(variable != NULL);  // Must have been resolved.
5370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Slot* slot = variable->AsSlot();
538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = variable->AsProperty();
539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
540d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (slot != NULL) {
541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
542e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOCAL:
544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ str(ip, MemOperand(fp, SlotOffset(slot)));
547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
5480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForAccumulatorValue(function);
549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
551d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT:
554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // We bypass the general EmitSlotSearch because we know more about
555e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // this specific context.
556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
557d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // The variable in the decl always resides in the current context.
558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
559d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (FLAG_debug_code) {
560d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Check if we have the correct context pointer.
56159151504615d929945dc59db37bf1166937748c6Steve Block          __ ldr(r1, ContextOperand(cp, Context::FCONTEXT_INDEX));
562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ cmp(r1, cp);
563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Check(eq, "Unexpected declaration in current context.");
564d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
566d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
56759151504615d929945dc59db37bf1166937748c6Steve Block          __ str(ip, ContextOperand(cp, slot->index()));
568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // No write barrier since the_hole_value is in old space.
569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
5700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForAccumulatorValue(function);
57159151504615d929945dc59db37bf1166937748c6Steve Block          __ str(result_register(), ContextOperand(cp, slot->index()));
572d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          int offset = Context::SlotOffset(slot->index());
573d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // We know that we have written a function, which is not a smi.
5744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ mov(r1, Operand(cp));
5759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          __ RecordWrite(r1, Operand(offset), r2, result_register());
576d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP: {
580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(r2, Operand(variable->name()));
581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Declaration nodes are always introduced in one of two modes.
582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ASSERT(mode == Variable::VAR ||
583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke               mode == Variable::CONST);
584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        PropertyAttributes attr =
585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            (mode == Variable::VAR) ? NONE : READ_ONLY;
586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ mov(r1, Operand(Smi::FromInt(attr)));
587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Push initial value, if any.
588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Note: For variables we must not push an initial value (such as
589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // 'undefined') because we may have a (legal) redeclaration and we
590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // must not destroy the current value.
591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ Push(cp, r2, r1, r0);
594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ Push(cp, r2, r1);
596e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Push initial value for function declaration.
5970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForStackValue(function);
598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else {
599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ mov(r0, Operand(Smi::FromInt(0)));  // No initial value!
600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ Push(cp, r2, r1, r0);
601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDeclareContextSlot, 4);
603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (prop != NULL) {
608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (function != NULL || mode == Variable::CONST) {
609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // We are declaring a function or constant that rewrites to a
610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // property.  Use (keyed) IC to set the initial value.
6110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(prop->obj());
612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (function != NULL) {
6130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(prop->key());
6140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(function);
615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ pop(r1);  // Key.
616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
6170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(prop->key());
618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(r1, result_register());  // Key.
619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex);
620d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r2);  // Receiver.
622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
6240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Value in r0 is ignored (declarations are statements).
626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
6273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
6283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
6293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) {
632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
636d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
6373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
6383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // The context is the first argument.
6393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r1, Operand(pairs));
6403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(cp, r1, r0);
6423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kDeclareGlobals, 3);
6433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
6443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
6453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ SwitchStatement");
649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Breakable nested_statement(this, stmt);
650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Keep the switch value on the stack until a case matches.
6520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(stmt->tag());
653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<CaseClause*>* clauses = stmt->cases();
655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label next_test;  // Recycled for each test.
658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the tests with branches to their bodies.
659f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The default is not a test, but remember it as final fall through.
662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (clause->is_default()) {
663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      default_clause = clause;
664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      continue;
665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case comparison");
668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&next_test);
669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    next_test.Unuse();
670f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Compile the label expression.
6720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(clause->label());
673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
67480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Perform the comparison as if via '==='.
675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(r1, MemOperand(sp, 0));  // Switch value.
6760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
6770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (inline_smi_code) {
67880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label slow_case;
67980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ orr(r2, r1, r0);
68080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ tst(r2, Operand(kSmiTagMask));
68180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ b(ne, &slow_case);
68280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ cmp(r1, r0);
68380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ b(ne, &next_test);
68480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ Drop(1);  // Switch value is no longer needed.
68580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ b(clause->body_target()->entry_label());
686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&slow_case);
68780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
68880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
6890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    CompareFlags flags = inline_smi_code
6900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        ? NO_SMI_COMPARE_IN_STUB
6910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        : NO_COMPARE_FLAGS;
6920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    CompareStub stub(eq, true, flags, r1, r0);
693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
6949ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    __ cmp(r0, Operand(0, RelocInfo::NONE));
695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(ne, &next_test);
696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(clause->body_target()->entry_label());
698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Discard the test value and jump to the default if present, otherwise to
701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the end of the statement.
702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&next_test);
703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(1);  // Switch value is no longer needed.
704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (default_clause == NULL) {
705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(nested_statement.break_target());
706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(default_clause->body_target()->entry_label());
708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the case bodies.
711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case body");
713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(clause->body_target()->entry_label());
715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitStatements(clause->statements());
716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(nested_statement.break_target());
719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
721f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
723f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ ForInStatement");
724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label loop, exit;
727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ForIn loop_statement(this, stmt);
728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  increment_loop_depth();
729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
730f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the object to enumerate over. Both SpiderMonkey and JSC
731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ignore null and undefined in contrast to the specification; see
732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ECMA-262 section 12.6.4.
7330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(stmt->enumerable());
734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, ip);
736f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, &exit);
737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(ip, Heap::kNullValueRootIndex);
738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, ip);
739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, &exit);
740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the object to a JS object.
742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label convert, done_convert;
743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, &convert);
744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(hs, &done_convert);
746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&convert);
747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);
748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done_convert);
750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);
751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
75259151504615d929945dc59db37bf1166937748c6Steve Block  // BUG(867): Check cache validity in generated code. This is a fast
75359151504615d929945dc59db37bf1166937748c6Steve Block  // case for the JSObject::IsSimpleEnum cache validity checks. If we
75459151504615d929945dc59db37bf1166937748c6Steve Block  // cannot guarantee cache validity, call the runtime system to check
75559151504615d929945dc59db37bf1166937748c6Steve Block  // cache validity or get the property names in a fixed array.
756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the set of properties to enumerate.
758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);  // Duplicate the enumerable object on the stack.
759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If we got a map from the runtime call, we can do a fast
762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // modification check. Otherwise, we got a fixed array, and we have
763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // to do a slow check.
764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label fixed_array;
765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r2, r0);
766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));
767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(ip, Heap::kMetaMapRootIndex);
768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, ip);
769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &fixed_array);
770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a map in register r0. Get the enumeration cache from it.
772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r0, Map::kInstanceDescriptorsOffset));
773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset));
774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));
775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Setup the four remaining stack slots.
777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);  // Map.
778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r2, FixedArray::kLengthOffset));
779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r0, Operand(Smi::FromInt(0)));
780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Push enumeration cache, enumeration cache length (as smi) and zero.
781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(r2, r1, r0);
782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a fixed array in register r0. Iterate through that.
785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&fixed_array);
786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r1, Operand(Smi::FromInt(0)));  // Map (0) - force slow check.
787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(r1, r0);
788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset));
789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r0, Operand(Smi::FromInt(0)));
790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(r1, r0);  // Fixed array length (as smi) and initial index.
791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for doing the condition check.
793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&loop);
794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the current count to r0, load the length to r1.
795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, r1);  // Compare to the array length.
797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(hs, loop_statement.break_target());
798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the current entry of the array into register r3.
800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(sp, 2 * kPointerSize));
801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the expected map from the stack or a zero map in the
805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // permanent slow case into register r2.
806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(sp, 3 * kPointerSize));
807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the expected map still matches that of the enumerable.
809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If not, we have to filter the key.
810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label update_each;
811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, MemOperand(sp, 4 * kPointerSize));
812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset));
813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r4, Operand(r2));
814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, &update_each);
815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
816756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Convert the entry to a string or (smi) 0 if it isn't a property
817756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // any more. If the property has been removed while iterating, we
818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // just skip it.
819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r1);  // Enumerable.
820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r3);  // Current entry.
821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS);
822756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ mov(r3, Operand(r0), SetCC);
823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, loop_statement.continue_target());
824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the 'each' property or variable from the possibly filtered
826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // entry in register r3.
827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&update_each);
828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(result_register(), r3);
829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Perform the assignment as if via '='.
830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  EmitAssignment(stmt->each());
831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the body of the loop.
833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label stack_limit_hit, stack_check_done;
834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Visit(stmt->body());
835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ StackLimitCheck(&stack_limit_hit);
837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&stack_check_done);
838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the going to the next element by incrementing
840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the index (smi) stored on top of the stack.
841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(loop_statement.continue_target());
842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r0);
843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(r0, r0, Operand(Smi::FromInt(1)));
844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r0);
845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(&loop);
846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Slow case for the stack limit check.
848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StackCheckStub stack_check_stub;
849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&stack_limit_hit);
850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stack_check_stub);
851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(&stack_check_done);
852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Remove the pointers stored on the stack.
854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(loop_statement.break_target());
855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(5);
856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Exit and decrement the loop depth.
858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  decrement_loop_depth();
860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
8613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
8648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                       bool pretenure) {
865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Use the fast case closure allocation code that allocates in new
866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // space for nested functions that don't need literals cloning.
8678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (scope()->is_function_scope() &&
8688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      info->num_literals() == 0 &&
8698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      !pretenure) {
870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    FastNewClosureStub stub;
871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r0, Operand(info));
872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(r0);
873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r0, Operand(info));
8768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ LoadRoot(r1, pretenure ? Heap::kTrueValueRootIndex
8778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                              : Heap::kFalseValueRootIndex);
8788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Push(cp, r0, r1);
8798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ CallRuntime(Runtime::kNewClosure, 3);
880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
8810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
885d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ VariableProxy");
8870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitVariableLoad(expr->var());
888e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
889e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
890e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
89159151504615d929945dc59db37bf1166937748c6Steve BlockMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
89259151504615d929945dc59db37bf1166937748c6Steve Block    Slot* slot,
89359151504615d929945dc59db37bf1166937748c6Steve Block    Label* slow) {
89459151504615d929945dc59db37bf1166937748c6Steve Block  ASSERT(slot->type() == Slot::CONTEXT);
89559151504615d929945dc59db37bf1166937748c6Steve Block  Register current = cp;
89659151504615d929945dc59db37bf1166937748c6Steve Block  Register next = r3;
89759151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = r4;
89859151504615d929945dc59db37bf1166937748c6Steve Block
89959151504615d929945dc59db37bf1166937748c6Steve Block  for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
90059151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
90159151504615d929945dc59db37bf1166937748c6Steve Block      if (s->calls_eval()) {
90259151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
90359151504615d929945dc59db37bf1166937748c6Steve Block        __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX));
90459151504615d929945dc59db37bf1166937748c6Steve Block        __ tst(temp, temp);
90559151504615d929945dc59db37bf1166937748c6Steve Block        __ b(ne, slow);
90659151504615d929945dc59db37bf1166937748c6Steve Block      }
90759151504615d929945dc59db37bf1166937748c6Steve Block      __ ldr(next, ContextOperand(current, Context::CLOSURE_INDEX));
90859151504615d929945dc59db37bf1166937748c6Steve Block      __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset));
90959151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering cp.
91059151504615d929945dc59db37bf1166937748c6Steve Block      current = next;
91159151504615d929945dc59db37bf1166937748c6Steve Block    }
91259151504615d929945dc59db37bf1166937748c6Steve Block  }
91359151504615d929945dc59db37bf1166937748c6Steve Block  // Check that last extension is NULL.
91459151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX));
91559151504615d929945dc59db37bf1166937748c6Steve Block  __ tst(temp, temp);
91659151504615d929945dc59db37bf1166937748c6Steve Block  __ b(ne, slow);
91759151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(temp, ContextOperand(current, Context::FCONTEXT_INDEX));
91859151504615d929945dc59db37bf1166937748c6Steve Block  return ContextOperand(temp, slot->index());
91959151504615d929945dc59db37bf1166937748c6Steve Block}
92059151504615d929945dc59db37bf1166937748c6Steve Block
92159151504615d929945dc59db37bf1166937748c6Steve Block
92259151504615d929945dc59db37bf1166937748c6Steve Blockvoid FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
92359151504615d929945dc59db37bf1166937748c6Steve Block    Slot* slot,
92459151504615d929945dc59db37bf1166937748c6Steve Block    TypeofState typeof_state,
92559151504615d929945dc59db37bf1166937748c6Steve Block    Label* slow,
92659151504615d929945dc59db37bf1166937748c6Steve Block    Label* done) {
92759151504615d929945dc59db37bf1166937748c6Steve Block  // Generate fast-case code for variables that might be shadowed by
92859151504615d929945dc59db37bf1166937748c6Steve Block  // eval-introduced variables.  Eval is used a lot without
92959151504615d929945dc59db37bf1166937748c6Steve Block  // introducing variables.  In those cases, we do not want to
93059151504615d929945dc59db37bf1166937748c6Steve Block  // perform a runtime call for all variables in the scope
93159151504615d929945dc59db37bf1166937748c6Steve Block  // containing the eval.
93259151504615d929945dc59db37bf1166937748c6Steve Block  if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
93359151504615d929945dc59db37bf1166937748c6Steve Block    EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow);
93459151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(done);
93559151504615d929945dc59db37bf1166937748c6Steve Block  } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
9360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot();
93759151504615d929945dc59db37bf1166937748c6Steve Block    Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
93859151504615d929945dc59db37bf1166937748c6Steve Block    if (potential_slot != NULL) {
93959151504615d929945dc59db37bf1166937748c6Steve Block      // Generate fast case for locals that rewrite to slots.
94059151504615d929945dc59db37bf1166937748c6Steve Block      __ ldr(r0, ContextSlotOperandCheckExtensions(potential_slot, slow));
94159151504615d929945dc59db37bf1166937748c6Steve Block      if (potential_slot->var()->mode() == Variable::CONST) {
94259151504615d929945dc59db37bf1166937748c6Steve Block        __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
94359151504615d929945dc59db37bf1166937748c6Steve Block        __ cmp(r0, ip);
94459151504615d929945dc59db37bf1166937748c6Steve Block        __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
94559151504615d929945dc59db37bf1166937748c6Steve Block      }
94659151504615d929945dc59db37bf1166937748c6Steve Block      __ jmp(done);
94759151504615d929945dc59db37bf1166937748c6Steve Block    } else if (rewrite != NULL) {
94859151504615d929945dc59db37bf1166937748c6Steve Block      // Generate fast case for calls of an argument function.
94959151504615d929945dc59db37bf1166937748c6Steve Block      Property* property = rewrite->AsProperty();
95059151504615d929945dc59db37bf1166937748c6Steve Block      if (property != NULL) {
95159151504615d929945dc59db37bf1166937748c6Steve Block        VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
95259151504615d929945dc59db37bf1166937748c6Steve Block        Literal* key_literal = property->key()->AsLiteral();
95359151504615d929945dc59db37bf1166937748c6Steve Block        if (obj_proxy != NULL &&
95459151504615d929945dc59db37bf1166937748c6Steve Block            key_literal != NULL &&
95559151504615d929945dc59db37bf1166937748c6Steve Block            obj_proxy->IsArguments() &&
95659151504615d929945dc59db37bf1166937748c6Steve Block            key_literal->handle()->IsSmi()) {
95759151504615d929945dc59db37bf1166937748c6Steve Block          // Load arguments object if there are no eval-introduced
95859151504615d929945dc59db37bf1166937748c6Steve Block          // variables. Then load the argument from the arguments
95959151504615d929945dc59db37bf1166937748c6Steve Block          // object using keyed load.
96059151504615d929945dc59db37bf1166937748c6Steve Block          __ ldr(r1,
9610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
96259151504615d929945dc59db37bf1166937748c6Steve Block                                                   slow));
96359151504615d929945dc59db37bf1166937748c6Steve Block          __ mov(r0, Operand(key_literal->handle()));
96459151504615d929945dc59db37bf1166937748c6Steve Block          Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
9650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitCallIC(ic, RelocInfo::CODE_TARGET);
96659151504615d929945dc59db37bf1166937748c6Steve Block          __ jmp(done);
96759151504615d929945dc59db37bf1166937748c6Steve Block        }
96859151504615d929945dc59db37bf1166937748c6Steve Block      }
96959151504615d929945dc59db37bf1166937748c6Steve Block    }
97059151504615d929945dc59db37bf1166937748c6Steve Block  }
97159151504615d929945dc59db37bf1166937748c6Steve Block}
97259151504615d929945dc59db37bf1166937748c6Steve Block
97359151504615d929945dc59db37bf1166937748c6Steve Block
97459151504615d929945dc59db37bf1166937748c6Steve Blockvoid FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
97559151504615d929945dc59db37bf1166937748c6Steve Block    Slot* slot,
97659151504615d929945dc59db37bf1166937748c6Steve Block    TypeofState typeof_state,
97759151504615d929945dc59db37bf1166937748c6Steve Block    Label* slow) {
97859151504615d929945dc59db37bf1166937748c6Steve Block  Register current = cp;
97959151504615d929945dc59db37bf1166937748c6Steve Block  Register next = r1;
98059151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = r2;
98159151504615d929945dc59db37bf1166937748c6Steve Block
98259151504615d929945dc59db37bf1166937748c6Steve Block  Scope* s = scope();
98359151504615d929945dc59db37bf1166937748c6Steve Block  while (s != NULL) {
98459151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
98559151504615d929945dc59db37bf1166937748c6Steve Block      if (s->calls_eval()) {
98659151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
98759151504615d929945dc59db37bf1166937748c6Steve Block        __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX));
98859151504615d929945dc59db37bf1166937748c6Steve Block        __ tst(temp, temp);
98959151504615d929945dc59db37bf1166937748c6Steve Block        __ b(ne, slow);
99059151504615d929945dc59db37bf1166937748c6Steve Block      }
99159151504615d929945dc59db37bf1166937748c6Steve Block      // Load next context in chain.
99259151504615d929945dc59db37bf1166937748c6Steve Block      __ ldr(next, ContextOperand(current, Context::CLOSURE_INDEX));
99359151504615d929945dc59db37bf1166937748c6Steve Block      __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset));
99459151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering cp.
99559151504615d929945dc59db37bf1166937748c6Steve Block      current = next;
99659151504615d929945dc59db37bf1166937748c6Steve Block    }
99759151504615d929945dc59db37bf1166937748c6Steve Block    // If no outer scope calls eval, we do not need to check more
99859151504615d929945dc59db37bf1166937748c6Steve Block    // context extensions.
99959151504615d929945dc59db37bf1166937748c6Steve Block    if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break;
100059151504615d929945dc59db37bf1166937748c6Steve Block    s = s->outer_scope();
100159151504615d929945dc59db37bf1166937748c6Steve Block  }
100259151504615d929945dc59db37bf1166937748c6Steve Block
100359151504615d929945dc59db37bf1166937748c6Steve Block  if (s->is_eval_scope()) {
100459151504615d929945dc59db37bf1166937748c6Steve Block    Label loop, fast;
100559151504615d929945dc59db37bf1166937748c6Steve Block    if (!current.is(next)) {
100659151504615d929945dc59db37bf1166937748c6Steve Block      __ Move(next, current);
100759151504615d929945dc59db37bf1166937748c6Steve Block    }
100859151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&loop);
100959151504615d929945dc59db37bf1166937748c6Steve Block    // Terminate at global context.
101059151504615d929945dc59db37bf1166937748c6Steve Block    __ ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset));
101159151504615d929945dc59db37bf1166937748c6Steve Block    __ LoadRoot(ip, Heap::kGlobalContextMapRootIndex);
101259151504615d929945dc59db37bf1166937748c6Steve Block    __ cmp(temp, ip);
101359151504615d929945dc59db37bf1166937748c6Steve Block    __ b(eq, &fast);
101459151504615d929945dc59db37bf1166937748c6Steve Block    // Check that extension is NULL.
101559151504615d929945dc59db37bf1166937748c6Steve Block    __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX));
101659151504615d929945dc59db37bf1166937748c6Steve Block    __ tst(temp, temp);
101759151504615d929945dc59db37bf1166937748c6Steve Block    __ b(ne, slow);
101859151504615d929945dc59db37bf1166937748c6Steve Block    // Load next context in chain.
101959151504615d929945dc59db37bf1166937748c6Steve Block    __ ldr(next, ContextOperand(next, Context::CLOSURE_INDEX));
102059151504615d929945dc59db37bf1166937748c6Steve Block    __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset));
102159151504615d929945dc59db37bf1166937748c6Steve Block    __ b(&loop);
102259151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&fast);
102359151504615d929945dc59db37bf1166937748c6Steve Block  }
102459151504615d929945dc59db37bf1166937748c6Steve Block
10258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r0, GlobalObjectOperand());
102659151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(r2, Operand(slot->var()->name()));
102759151504615d929945dc59db37bf1166937748c6Steve Block  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
102859151504615d929945dc59db37bf1166937748c6Steve Block      ? RelocInfo::CODE_TARGET
102959151504615d929945dc59db37bf1166937748c6Steve Block      : RelocInfo::CODE_TARGET_CONTEXT;
103059151504615d929945dc59db37bf1166937748c6Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
10310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, mode);
103259151504615d929945dc59db37bf1166937748c6Steve Block}
103359151504615d929945dc59db37bf1166937748c6Steve Block
103459151504615d929945dc59db37bf1166937748c6Steve Block
10350d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EmitVariableLoad(Variable* var) {
1036d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Four cases: non-this global variables, lookup slots, all other
1037d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // types of slots, and parameters that rewrite to explicit property
1038d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // accesses on the arguments object.
10390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Slot* slot = var->AsSlot();
1040d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Property* property = var->AsProperty();
1041d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1042d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (var->is_global() && !var->is_this()) {
10433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Comment cmnt(masm_, "Global variable");
10443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Use inline caching. Variable name is passed in r2 and the global
1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // object (receiver) in r0.
10468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r0, GlobalObjectOperand());
1047e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ mov(r2, Operand(var->name()));
10483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
10490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
10500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
1051d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1052d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
105359151504615d929945dc59db37bf1166937748c6Steve Block    Label done, slow;
105459151504615d929945dc59db37bf1166937748c6Steve Block
105559151504615d929945dc59db37bf1166937748c6Steve Block    // Generate code for loading from variables potentially shadowed
105659151504615d929945dc59db37bf1166937748c6Steve Block    // by eval-introduced variables.
105759151504615d929945dc59db37bf1166937748c6Steve Block    EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
105859151504615d929945dc59db37bf1166937748c6Steve Block
105959151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
1060d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Lookup slot");
1061d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ mov(r1, Operand(var->name()));
1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Push(cp, r1);  // Context and name.
1063d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
106459151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&done);
106559151504615d929945dc59db37bf1166937748c6Steve Block
10660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
1067d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1068d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL) {
1069d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1070d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            ? "Context slot"
1071d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            : "Stack slot");
1072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (var->mode() == Variable::CONST) {
10730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Constants may be the hole value if they have not been initialized.
10740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Unhole them.
10750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      MemOperand slot_operand = EmitSlotSearch(slot, r0);
10760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ ldr(r0, slot_operand);
10770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
10780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ cmp(r0, ip);
10790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
10800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(r0);
10810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
10820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(slot);
10830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
1084d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1085d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Rewritten parameter");
1086d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(property);
1087d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Rewritten parameter accesses are of the form "slot[literal]".
1088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1089e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the object is in a slot.
1090d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1091d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(object_var);
10920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* object_slot = object_var->AsSlot();
1093d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(object_slot);
1094d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1095d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the object.
10966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Move(r1, object_slot);
1097d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1098e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the key is a smi.
1099d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key_literal = property->key()->AsLiteral();
1100d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(key_literal);
1101d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(key_literal->handle()->IsSmi());
1102d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1103d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the key.
11046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ mov(r0, Operand(key_literal->handle()));
1105d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
110625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    // Call keyed load IC. It has arguments key and receiver in r0 and r1.
1107d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
11080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET);
11090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1114d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1115d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ RegExpLiteral");
1116bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label materialized;
11173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Registers will be used as follows:
11183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r4 = JS function, literals array
11193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r3 = literal index
11203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r2 = RegExp pattern
11213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // r1 = RegExp flags
1122bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // r0 = temp + materialized value (RegExp literal)
112380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
112480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
11253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int literal_offset =
112680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
11273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(r0, FieldMemOperand(r4, literal_offset));
11283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
11293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ cmp(r0, ip);
1130bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(ne, &materialized);
113180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
113280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Create regexp literal using runtime function.
113380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Result will be in r0.
11343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r3, Operand(Smi::FromInt(expr->literal_index())));
11353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r2, Operand(expr->pattern()));
11363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r1, Operand(expr->flags()));
11376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(r4, r3, r2, r1);
11383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
113980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1140bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&materialized);
1141bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1142bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(r0);
1143bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(r0, Operand(Smi::FromInt(size)));
1144bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(r0);
1145bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
114680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1147bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // After this, registers are used as follows:
1148bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // r0: Newly allocated regexp.
114980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // r1: Materialized regexp.
1150bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // r2: temp.
1151bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(r1);
1152bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CopyFields(r0, r1, r2.bit(), size / kPointerSize);
11530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
1154d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1157d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
11596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r3, MemOperand(fp,  JavaScriptFrameConstants::kFunctionOffset));
11606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
11616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
11626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r1, Operand(expr->constant_properties()));
11636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r0, Operand(Smi::FromInt(expr->fast_elements() ? 1 : 0)));
11646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(r3, r2, r1, r0);
1165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->depth() > 1) {
11666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
11673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
11686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
1169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
1172e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in r0.
1173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
1174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
11753e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Mark all computed expressions that are bound to a key that
11763e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // is shadowed by a later occurrence of the same key. For the
11773e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // marked expressions, no store code is emitted.
11783e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  expr->CalculateEmitStore();
11793e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
1180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < expr->properties()->length(); i++) {
1181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectLiteral::Property* property = expr->properties()->at(i);
1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
1183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = property->key();
1185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
1186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
1187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ push(r0);  // Save result on stack
1188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
1189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
1191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::CONSTANT:
1192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        UNREACHABLE();
1193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value()));
1195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (key->handle()->IsSymbol()) {
11980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForAccumulatorValue(value);
1199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ mov(r2, Operand(key->handle()));
1200402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu          __ ldr(r1, MemOperand(sp));
12013e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          if (property->emit_store()) {
12023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu            Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
12033e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu            EmitCallIC(ic, RelocInfo::CODE_TARGET);
12043e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          }
1205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Fall through.
1208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::PROTOTYPE:
1209e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Duplicate receiver on stack.
1210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ ldr(r0, MemOperand(sp));
1211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(r0);
12120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(key);
12130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(value);
12143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        if (property->emit_store()) {
12153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          __ CallRuntime(Runtime::kSetProperty, 3);
12163e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        } else {
12173e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          __ Drop(3);
12183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        }
1219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1220e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::GETTER:
1221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::SETTER:
1222e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Duplicate receiver on stack.
1223e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ ldr(r0, MemOperand(sp));
1224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(r0);
12250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(key);
1226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ?
1227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                           Smi::FromInt(1) :
1228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                           Smi::FromInt(0)));
1229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(r1);
12300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(value);
1231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDefineAccessor, 4);
1232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1236e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
12370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
12390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
12403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
12423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1244d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
12453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
1246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<Expression*>* subexprs = expr->values();
1248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int length = subexprs->length();
1249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
12503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
12513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
12523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
1253e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(r1, Operand(expr->constant_elements()));
12546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(r3, r2, r1);
1255756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) {
1256756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    FastCloneShallowArrayStub stub(
1257756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
1258756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
1259756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1, r1, r2);
1260756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (expr->depth() > 1) {
1261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
1262756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
1263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
1264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1265756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    FastCloneShallowArrayStub stub(
1266756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        FastCloneShallowArrayStub::CLONE_ELEMENTS, length);
1267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
12683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
12713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
12733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
1274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < length; i++) {
12753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Expression* subexpr = subexprs->at(i);
12763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
12773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
12783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (subexpr->AsLiteral() != NULL ||
12793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        CompileTimeValue::IsCompileTimeValue(subexpr)) {
12803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      continue;
12813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
12823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
12843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(r0);
12853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
12863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
12870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(subexpr);
12883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Store the subexpression value in the array's elements.
12903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ ldr(r1, MemOperand(sp));  // Copy of array literal.
12913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
12923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ str(result_register(), FieldMemOperand(r1, offset));
12943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Update the write barrier for the array store with r0 as the scratch
12963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // register.
12979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ RecordWrite(r1, Operand(offset), r2, result_register());
12983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
13010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
13030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
13043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
13063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1309402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Comment cmnt(masm_, "[ Assignment");
1310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // on the left-hand side.
1312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->target()->IsValidLeftHandSide()) {
1313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->target());
1314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1317402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Left-hand side can only be a property, a global or a (parameter or local)
1318402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1319402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1320402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LhsKind assign_type = VARIABLE;
132180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Property* property = expr->target()->AsProperty();
132280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (property != NULL) {
132380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    assign_type = (property->key()->IsPropertyName())
132480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? NAMED_PROPERTY
132580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : KEYED_PROPERTY;
1326402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1327402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1328402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate LHS expression.
1329402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1330402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1331402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Nothing to do here.
1332402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1333402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1334402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1335402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // We need the receiver both on the stack and in the accumulator.
13360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(property->obj());
1337402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1338402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
13390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
1340402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1341402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1342402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
134325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      if (expr->is_compound()) {
13440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
13450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(property->key());
134625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        __ ldr(r1, MemOperand(sp, 0));
134725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        __ push(r0);
134825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      } else {
13490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
13500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->key());
135125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      }
1352402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1353402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1354402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1355402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
13560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    { AccumulatorValueContext context(this);
13570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
13580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
13590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitVariableLoad(expr->target()->AsVariableProxy()->var());
13600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
13610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
13620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitNamedPropertyLoad(property);
13630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
13640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
13650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitKeyedPropertyLoad(property);
13660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
13670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
1368402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
137080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Token::Value op = expr->binary_op();
137180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ConstantOperand constant = ShouldInlineSmiCase(op)
137280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? GetConstantOperand(op, expr->target(), expr->value())
137380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : kNoConstants;
137480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ASSERT(constant == kRightConstant || constant == kNoConstants);
137580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (constant == kNoConstants) {
137680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ push(r0);  // Left operand goes on the stack.
13770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->value());
137880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
1379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
138080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
138180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? OVERWRITE_RIGHT
138280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : NO_OVERWRITE;
138380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    SetSourcePosition(expr->position() + 1);
13840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
138580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (ShouldInlineSmiCase(op)) {
138680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      EmitInlineSmiBinaryOp(expr,
138780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            op,
138880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            mode,
138980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            expr->target(),
139080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            expr->value(),
139180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            constant);
139280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    } else {
13930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitBinaryOp(op, mode);
139480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
139580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
13960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->value());
1397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Record source position before possible IC call.
1400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  SetSourcePosition(expr->position());
1401402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Store the value.
1403402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1404402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1405402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
14060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             expr->op());
1407402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1408402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitNamedPropertyAssignment(expr);
1410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1412402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitKeyedPropertyAssignment(expr);
1413402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1414402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1415402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1416402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1417402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1418d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Literal* key = prop->key()->AsLiteral();
1421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(r2, Operand(key->handle()));
1422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call load IC. It has arguments receiver and property name r0 and r2.
1423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
14240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1428d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
143025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Call keyed load IC. It has arguments key and receiver in r0 and r1.
1431e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
14320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
143680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
143780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Token::Value op,
143880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              OverwriteMode mode,
143980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Expression* left,
144080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Expression* right,
144180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              ConstantOperand constant) {
144280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(constant == kNoConstants);  // Only handled case.
14430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitBinaryOp(op, mode);
144480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
144580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
144680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1447d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitBinaryOp(Token::Value op,
144880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                     OverwriteMode mode) {
1449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(r1);
145080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenericBinaryOpStub stub(op, mode, r1, r0);
1451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
14520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
1453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitAssignment(Expression* expr) {
1457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw
1458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ReferenceError' on the left-hand side.
1459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->IsValidLeftHandSide()) {
1460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr);
1461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand side can only be a property, a global or a (parameter or local)
1465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  LhsKind assign_type = VARIABLE;
1468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = expr->AsProperty();
1469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (prop != NULL) {
1470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    assign_type = (prop->key()->IsPropertyName())
1471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ? NAMED_PROPERTY
1472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        : KEYED_PROPERTY;
1473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (assign_type) {
1476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case VARIABLE: {
1477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->AsVariableProxy()->var();
14780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EffectContext context(this);
14790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitVariableAssignment(var, Token::ASSIGN);
1480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case NAMED_PROPERTY: {
1483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(r0);  // Preserve value.
14840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
1485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(r1, r0);
1486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r0);  // Restore value.
1487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
1488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
14890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
1490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case KEYED_PROPERTY: {
1493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(r0);  // Preserve value.
14940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(prop->obj());
14950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->key());
1496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(r1, r0);
1497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r2);
1498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r0);  // Restore value.
1499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
15000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
1501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1505f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1507d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var,
15080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                               Token::Value op) {
1509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand sides that rewrite to explicit property accesses do not reach
1510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // here.
15113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(var != NULL);
15120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(var->is_global() || var->AsSlot() != NULL);
1513d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
15143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (var->is_global()) {
1515d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT(!var->is_this());
1516d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Assignment to a global variable.  Use inline caching for the
1517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // assignment.  Right-hand-side value is passed in r0, variable name in
1518402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // r2, and the global object in r1.
15193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(r2, Operand(var->name()));
15208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r1, GlobalObjectOperand());
15213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
15220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET);
1523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) {
1525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Perform the assignment for non-const variables and for initialization
1526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // of const variables.  Const assignments are simply skipped.
1527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Label done;
15280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* slot = var->AsSlot();
1529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
1530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
1531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      case Slot::LOCAL:
1532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Detect const reinitialization by checking for the hole value.
1534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ ldr(r1, MemOperand(fp, SlotOffset(slot)));
1535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ cmp(r1, ip);
1537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ b(ne, &done);
1538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment.
1540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
1541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT: {
1544e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        MemOperand target = EmitSlotSearch(slot, r1);
1545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Detect const reinitialization by checking for the hole value.
1547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ ldr(r2, target);
1548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ cmp(r2, ip);
1550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ b(ne, &done);
1551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment and issue the write barrier.
1553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ str(result_register(), target);
1554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // RecordWrite may destroy all its register arguments.
1555e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ mov(r3, result_register());
1556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
15579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        __ RecordWrite(r1, Operand(offset), r2, r3);
1558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
15593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
1560d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1561d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP:
1562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Call the runtime for the assignment.  The runtime will ignore
1563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // const reinitialization.
1564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(r0);  // Value.
1565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(r0, Operand(slot->var()->name()));
1566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ Push(cp, r0);  // Context and name.
1567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // The runtime will ignore const redeclaration.
1569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else {
1571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kStoreContextSlot, 3);
1572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1573d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
15743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&done);
15763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
15780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result_register());
15793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
15803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1582d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
1584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
1585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop != NULL);
1586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop->key()->AsLiteral() != NULL);
15873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1591d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ ldr(ip, MemOperand(sp, kPointerSize));  // Receiver is now under value.
1594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(ip);
1595d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1596e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1600e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
1602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load receiver to r1. Leave a copy in the stack if needed for turning the
1603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // receiver into fast case.
1604402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->ends_initialization_block()) {
1605402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ ldr(r1, MemOperand(sp));
1606402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  } else {
1607402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop(r1);
1608402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1609402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
16110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(r0);  // Result of assignment, saved even if not needed.
1616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Receiver is under the result value.
1617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(ip, MemOperand(sp, kPointerSize));
1618d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(ip);
1619d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1620d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(r0);
16210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->DropAndPlug(1, r0);
1622402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  } else {
16230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
1624d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
1630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1631d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1632d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1633d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1634d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Receiver is now under the key and value.
1637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(ip, MemOperand(sp, 2 * kPointerSize));
1638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(ip);
1639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1642d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r1);  // Key.
1646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load receiver to r2. Leave a copy in the stack if needed for turning the
1647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // receiver into fast case.
1648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (expr->ends_initialization_block()) {
1649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(r2, MemOperand(sp));
1650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ pop(r2);
1652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1654d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
16550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(r0);  // Result of assignment, saved even if not needed.
1660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Receiver is under the result value.
1661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(ip, MemOperand(sp, kPointerSize));
1662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(ip);
1663d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1664d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(r0);
16650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->DropAndPlug(1, r0);
1666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
16670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
1668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1672d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) {
1673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Property");
1674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* key = expr->key();
1675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (key->IsPropertyName()) {
16770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->obj());
1678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitNamedPropertyLoad(expr);
1679d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
16800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(expr->obj());
16810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->key());
168225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ pop(r1);
1683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitKeyedPropertyLoad(expr);
1684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
16850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
1686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1688d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr,
1689402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                       Handle<Object> name,
1690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       RelocInfo::Mode mode) {
1691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the IC.
1692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
16933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
16943e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  { PreserveStatementPositionScope scope(masm()->positions_recorder());
16953e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
16963e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
16973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
16983e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    __ mov(r2, Operand(name));
16993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
17013e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  SetSourcePosition(expr->position(), FORCED_POSITION);
17023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the IC initialization code.
1703402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
17048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
17050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, mode);
1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Restore context register.
1707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
17080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
1709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
17129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
17139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                            Expression* key,
17149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                            RelocInfo::Mode mode) {
17158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the key.
17168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForAccumulatorValue(key);
17178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Swap the name of the function and the receiver on the stack to follow
17198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // the calling convention for call ICs.
17208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ pop(r1);
17218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(r0);
17228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(r1);
17238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Code common for calls using the IC.
17259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ZoneList<Expression*>* args = expr->arguments();
17269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  int arg_count = args->length();
17273e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  { PreserveStatementPositionScope scope(masm()->positions_recorder());
17283e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
17293e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
17303e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
17319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
17329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Record source position for debugger.
17333e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  SetSourcePosition(expr->position(), FORCED_POSITION);
17349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Call the IC initialization code.
17359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
17368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
17378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize));  // Key.
17380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, mode);
17399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Restore context register.
17409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
17418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  context()->DropAndPlug(1, r0);  // Drop the key still on the stack.
17429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
17439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
17449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1745d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) {
1746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the call stub.
1747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
17493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  { PreserveStatementPositionScope scope(masm()->positions_recorder());
17503e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
17513e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
17523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
1753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
17553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  SetSourcePosition(expr->position(), FORCED_POSITION);
1756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ CallStub(&stub);
17593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore context register.
17603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
17610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->DropAndPlug(1, r0);
1762d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1765d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) {
1766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Call");
1767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* fun = expr->expression();
1768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Variable* var = fun->AsVariableProxy()->AsVariable();
1769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (var != NULL && var->is_possibly_eval()) {
1771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // In a call to eval, we first call %ResolvePossiblyDirectEval to
1772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // resolve the function we need to call and the receiver of the
1773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // call.  Then we call the resolved function using the given
1774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // arguments.
1775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    ZoneList<Expression*>* args = expr->arguments();
1776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    int arg_count = args->length();
1777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
17783e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    { PreserveStatementPositionScope pos_scope(masm()->positions_recorder());
17793e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(fun);
17803e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
17813e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ push(r2);  // Reserved receiver slot.
1782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
17833e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Push the arguments.
17843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      for (int i = 0; i < arg_count; i++) {
17853e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        VisitForStackValue(args->at(i));
17863e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      }
17873e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
17883e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Push copy of the function - found below the arguments.
17893e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
1790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(r1);
1791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
17923e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Push copy of the first argument or undefined if it doesn't exist.
17933e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      if (arg_count > 0) {
17943e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
17953e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        __ push(r1);
17963e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      } else {
17973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        __ push(r2);
17983e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      }
1799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
18003e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Push the receiver of the enclosing function and do runtime call.
18013e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ ldr(r1,
18023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu             MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize));
18033e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ push(r1);
18043e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
18053e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
18063e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // The runtime call returns a pair of values in r0 (function) and
18073e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // r1 (receiver). Touch up the stack with the right values.
18083e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
18093e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ str(r1, MemOperand(sp, arg_count * kPointerSize));
18103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
1811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Record source position for debugger.
18133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    SetSourcePosition(expr->position(), FORCED_POSITION);
1814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
1817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Restore context register.
1818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
18190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->DropAndPlug(1, r0);
1820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (var != NULL && !var->is_this() && var->is_global()) {
1821402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Push global object as receiver for the call IC.
18228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r0, GlobalObjectOperand());
1823402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(r0);
1824e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
18250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (var != NULL && var->AsSlot() != NULL &&
18260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen             var->AsSlot()->type() == Slot::LOOKUP) {
182759151504615d929945dc59db37bf1166937748c6Steve Block    // Call to a lookup slot (dynamically introduced variable).
182859151504615d929945dc59db37bf1166937748c6Steve Block    Label slow, done;
182959151504615d929945dc59db37bf1166937748c6Steve Block
18303e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    { PreserveStatementPositionScope scope(masm()->positions_recorder());
18313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Generate code for loading from variables potentially shadowed
18323e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // by eval-introduced variables.
18333e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      EmitDynamicLoadFromSlotFastCase(var->AsSlot(),
18343e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                                      NOT_INSIDE_TYPEOF,
18353e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                                      &slow,
18363e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                                      &done);
18373e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
183859151504615d929945dc59db37bf1166937748c6Steve Block
183959151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
18400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Call the runtime to find the function to call (returned in r0)
184159151504615d929945dc59db37bf1166937748c6Steve Block    // and the object holding it (returned in edx).
1842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(context_register());
1843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r2, Operand(var->name()));
1844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(r2);
1845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
184659151504615d929945dc59db37bf1166937748c6Steve Block    __ Push(r0, r1);  // Function, receiver.
184759151504615d929945dc59db37bf1166937748c6Steve Block
184859151504615d929945dc59db37bf1166937748c6Steve Block    // If fast case code has been generated, emit code to push the
184959151504615d929945dc59db37bf1166937748c6Steve Block    // function and receiver and have the slow path jump around this
185059151504615d929945dc59db37bf1166937748c6Steve Block    // code.
185159151504615d929945dc59db37bf1166937748c6Steve Block    if (done.is_linked()) {
185259151504615d929945dc59db37bf1166937748c6Steve Block      Label call;
185359151504615d929945dc59db37bf1166937748c6Steve Block      __ b(&call);
185459151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&done);
185559151504615d929945dc59db37bf1166937748c6Steve Block      // Push function.
185659151504615d929945dc59db37bf1166937748c6Steve Block      __ push(r0);
185759151504615d929945dc59db37bf1166937748c6Steve Block      // Push global receiver.
18588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ ldr(r1, GlobalObjectOperand());
185959151504615d929945dc59db37bf1166937748c6Steve Block      __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
186059151504615d929945dc59db37bf1166937748c6Steve Block      __ push(r1);
186159151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&call);
186259151504615d929945dc59db37bf1166937748c6Steve Block    }
186359151504615d929945dc59db37bf1166937748c6Steve Block
1864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitCallWithStub(expr);
1865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (fun->AsProperty() != NULL) {
1866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to an object property.
1867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Property* prop = fun->AsProperty();
1868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = prop->key()->AsLiteral();
1869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (key != NULL && key->handle()->IsSymbol()) {
1870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Call to a named property, use call IC.
18713e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      { PreserveStatementPositionScope scope(masm()->positions_recorder());
18723e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        VisitForStackValue(prop->obj());
18733e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      }
1874e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
18769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Call to a keyed property.
18779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // For a synthetic property use keyed load IC followed by function call,
18789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // for a regular property use keyed CallIC.
18793e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      { PreserveStatementPositionScope scope(masm()->positions_recorder());
18803e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        VisitForStackValue(prop->obj());
18813e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      }
188225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      if (prop->is_synthetic()) {
18833e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        { PreserveStatementPositionScope scope(masm()->positions_recorder());
18843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          VisitForAccumulatorValue(prop->key());
18853e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        }
18869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // Record source code position for IC call.
18873e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        SetSourcePosition(prop->position(), FORCED_POSITION);
188825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        __ pop(r1);  // We do not need to keep the receiver.
188925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
18909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
18910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        EmitCallIC(ic, RelocInfo::CODE_TARGET);
18928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ ldr(r1, GlobalObjectOperand());
1893e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
189459151504615d929945dc59db37bf1166937748c6Steve Block        __ Push(r0, r1);  // Function, receiver.
18959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        EmitCallWithStub(expr);
1896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
18979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
1898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
19003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
1901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to some other expression.  If the expression is an anonymous
1902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // function literal not called in a loop, mark it as one that should
1903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // also use the fast code generator.
1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    FunctionLiteral* lit = fun->AsFunctionLiteral();
1905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (lit != NULL &&
1906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        lit->name()->Equals(Heap::empty_string()) &&
1907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        loop_depth() == 0) {
1908d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      lit->set_try_full_codegen(true);
1909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
19103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
19113e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    { PreserveStatementPositionScope scope(masm()->positions_recorder());
19123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(fun);
19133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
1914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load global receiver object.
19158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r1, GlobalObjectOperand());
1916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
1917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(r1);
1918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit function call.
1919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    EmitCallWithStub(expr);
19203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
19213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
19223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1924d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
1925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
1926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
1927d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
1928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
192980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
193080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Push constructor on the stack.  If it's not a function it's used as
193180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
193280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ignored.
19330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->expression());
1934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
1936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
1938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
19390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
1940d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1942d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
1943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
1944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
1945d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
194680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load function and argument count into r1 and r0.
1947d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(r0, Operand(arg_count));
194880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
1949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
1951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
19520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
1953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
1957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
1960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
196480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
19650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
19660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
1967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, if_true);
1969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(if_false);
1970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
1972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
1976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
1979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
198380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
19840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
19850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
1986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ tst(r0, Operand(kSmiTagMask | 0x80000000));
198880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
1989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
1991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
1995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
1998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
200280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
20030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
20040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
200580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, if_false);
2007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(ip, Heap::kNullValueRootIndex);
2008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, ip);
2009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, if_true);
2010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
2011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Undetectable objects behave like undefined when tested with typeof.
2012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
2013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ tst(r1, Operand(1 << Map::kIsUndetectable));
2014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, if_false);
2015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset));
2016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
2017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(lt, if_false);
2018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));
201980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(le, if_true, if_false, fall_through);
2020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
20263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(args->length() == 1);
20273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
20293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label materialize_true, materialize_false;
20313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_true = NULL;
20323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_false = NULL;
203380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
20340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
20350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
20363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ BranchOnSmi(r0, if_false);
20383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
203980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(ge, if_true, if_false, fall_through);
20403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
20423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
20433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
2045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
2046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
205380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
20540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
20550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, if_false);
2058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
2060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ tst(r1, Operand(1 << Map::kIsUndetectable));
206180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(ne, if_true, if_false, fall_through);
2062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2067756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2068756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    ZoneList<Expression*>* args) {
2069756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2070756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ASSERT(args->length() == 1);
2071756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
20720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2073756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2074756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label materialize_true, materialize_false;
2075756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_true = NULL;
2076756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_false = NULL;
207780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
20780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
20790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2080756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2081756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only
2082756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // used in a few functions in runtime.js which should not normally be hit by
2083756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // this compiler.
2084756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ jmp(if_false);
20850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2086756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2087756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2088756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
2090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
209780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
20980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
20990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, if_false);
2102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
210380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
2104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
2110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
211780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
21180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
21190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, if_false);
2122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
212380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
2124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
2130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
213780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
21380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
21390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, if_false);
2142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
214380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
2144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
215680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
21570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
21580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the frame pointer for the calling frame.
2161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Skip the arguments adaptor frame if it exists.
2164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label check_frame_marker;
2165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset));
2166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &check_frame_marker);
2168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset));
2169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check the marker in the calling frame.
2171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&check_frame_marker);
2172f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
2173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
217480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
2175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
2181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the two objects into registers and perform the comparison.
21840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
21850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
2186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2188f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
219080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
21910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
21920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r1);
2195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r0, r1);
219680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(eq, if_true, if_false, fall_through);
2197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ArgumentsAccessStub expects the key in edx and the formal
22060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // parameter count in r0.
22070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r1, r0);
2209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
2210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
22120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label exit;
2220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the number of formal parameters.
2221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
2222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the calling frame is an arguments adaptor frame.
2224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
2226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &exit);
2228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Arguments adaptor case: Read the arguments length from the
2230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // adaptor frame.
2231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
2232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
22340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
2239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, null, function, non_function_constructor;
2241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
22420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, we return null.
2245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, &null);
2246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check that the object is a JS object but take special care of JS
2248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // functions to make sure they have 'Function' as their class.
2249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE);  // Map is now in r0.
2250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(lt, &null);
2251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // As long as JS_FUNCTION_TYPE is the last instance type and it is
2253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
2254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // LAST_JS_OBJECT_TYPE.
2255f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
2256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
2257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, Operand(JS_FUNCTION_TYPE));
2258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(eq, &function);
2259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the constructor in the map is a function.
2261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, Map::kConstructorOffset));
2262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
2263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &non_function_constructor);
2264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r0 now contains the constructor function. Grab the
2266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // instance class name from there.
2267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
2268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset));
2269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(&done);
2270f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Functions have class 'Function'.
2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&function);
2273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex);
2274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Objects with a non-function constructor have class 'Object'.
2277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&non_function_constructor);
2278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex);
2279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-JS objects have class null.
2282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&null);
2283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(r0, Heap::kNullValueRootIndex);
2284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // All done.
2286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
22880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2290f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
2293f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Conditionally generate a log call.
2294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Args:
2295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   0 (literal string): The type of logging (corresponds to the flags).
2296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     This is used to determine whether or not to generate the log call.
2297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   1 (string): Format string.  Access the string at argument index 2
2298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     with '%2s' (see Logger::LogRuntime for all the formats).
2299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   2 (array): Arguments to the format string.
2300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 3);
2301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING
2302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
23030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(1));
23040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(2));
2305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLog, 2);
2306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif
2308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Finally, we're expected to leave a value on the top of the stack.
2309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
23100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
2315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label slow_allocate_heapnumber;
2318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label heapnumber_allocated;
2319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
23219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber);
2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&heapnumber_allocated);
2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&slow_allocate_heapnumber);
23253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Allocate a heap number.
23263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CallRuntime(Runtime::kNumberAlloc, 0);
2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(r4, Operand(r0));
2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&heapnumber_allocated);
2330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert 32 random bits in r0 to 0.(32 random bits) in a double
2332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // by computing:
2333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
2334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (CpuFeatures::IsSupported(VFP3)) {
2335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ PrepareCallCFunction(0, r1);
2336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallCFunction(ExternalReference::random_uint32_function(), 0);
2337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CpuFeatures::Scope scope(VFP3);
2339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0x41300000 is the top half of 1.0 x 2^20 as a double.
2340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Create this constant using mov/orr to avoid PC relative load.
2341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r1, Operand(0x41000000));
2342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ orr(r1, r1, Operand(0x300000));
2343f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Move 0x41300000xxxxxxxx (x = random bits) to VFP.
2344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ vmov(d7, r0, r1);
2345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Move 0x4130000000000000 to VFP.
23469ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    __ mov(r0, Operand(0, RelocInfo::NONE));
2347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ vmov(d8, r0, r1);
2348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Subtract and store the result in the heap number.
2349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ vsub(d7, d7, d8);
2350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ sub(r0, r4, Operand(kHeapObjectTag));
2351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ vstr(d7, r0, HeapNumber::kValueOffset);
2352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r0, r4);
2353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
2354f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(r0, Operand(r4));
2355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ PrepareCallCFunction(1, r1);
2356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallCFunction(
2357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ExternalReference::fill_heap_number_with_random_function(), 1);
2358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
2365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SubStringStub stub;
2367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
23680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
23690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
23700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
2371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
23720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2376f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
2377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  RegExpExecStub stub;
2379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 4);
23800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
23810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
23820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
23830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(3));
2384f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
23850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2386f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2387f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
2390f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2391f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));  // Load the object.
2393f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
2395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi return the object.
2396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, &done);
2397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the object.
2398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE);
2399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &done);
2400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
2401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
24030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2404f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
2408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the runtime function.
2409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
24100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
24110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
2412f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_pow, 2);
24130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
2418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));  // Load the object.
24210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));  // Load the value.
2422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r1);  // r0 = value. r1 = object.
2423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
2425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, return the value.
2426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r1, &done);
2427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the value.
2429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE);
2430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &done);
2431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Store the value.
2433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
2434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the write barrier.  Save the value as it will be
2435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // overwritten by the write barrier code and is needed afterward.
24369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ RecordWrite(r1, Operand(JSValue::kValueOffset - kHeapObjectTag), r2, r3);
2437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
24390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
2444f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 1);
2445f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
24470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  NumberToStringStub stub;
2450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
24510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
2456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
24617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharFromCodeGenerator generator(r0, r1);
24627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
24637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
2464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
24667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
2467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
24690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r1);
2470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
24747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
24757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
24770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
24787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = r1;
24807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = r0;
24817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch = r2;
24827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = r3;
24837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
24857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
24877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
24887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
24897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharCodeAtGenerator generator(object,
24907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      index,
24917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      scratch,
24927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      result,
24937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
24947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
24957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &index_out_of_range,
24967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      STRING_INDEX_IS_NUMBER);
24977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
24987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
24997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
25017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
25027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // NaN.
25037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kNanValueRootIndex);
25047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
25057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
25077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Load the undefined value into the result register, which will
25087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // trigger conversion.
25097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
25107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
25117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
25137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
25147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
25160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
25177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
25187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
25217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
25227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
25240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
25257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = r1;
25277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = r0;
25287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch1 = r2;
25297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch2 = r3;
25307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = r0;
25317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
25337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
25357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
25367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
25377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharAtGenerator generator(object,
25387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  index,
25397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  scratch1,
25407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  scratch2,
25417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  result,
25427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
25437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
25447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &index_out_of_range,
25457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  STRING_INDEX_IS_NUMBER);
25467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
25477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
25487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
25507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
25517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the empty string.
25527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kEmptyStringRootIndex);
25537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
25547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
25567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move smi zero into the result register, which will trigger
25577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // conversion.
25587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(result, Operand(Smi::FromInt(0)));
25597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
25607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
25627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
25637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
25650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
2566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
2570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
25730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
2574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringAddStub stub(NO_STRING_ADD_FLAGS);
2576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
25770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
25850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringCompareStub stub;
2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
25890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the runtime.
2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
25960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_sin, 1);
25980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the runtime.
2604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
26050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_cos, 1);
26070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
2612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the runtime function.
2613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
26140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_sqrt, 1);
26160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
2621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() >= 2);
2622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int arg_count = args->length() - 2;  // For receiver and function.
26240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));  // Receiver.
2625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < arg_count; i++) {
26260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i + 1));
2627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
26280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(arg_count + 1));  // Function.
2629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // InvokeFunction requires function in r1. Move it in there.
2631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!result_register().is(r1)) __ mov(r1, result_register());
2632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ParameterCount count(arg_count);
2633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeFunction(r1, count, CALL_FUNCTION);
2634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
26350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
26410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
26420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
26430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
2644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kRegExpConstructResult, 3);
26450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
2650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
26510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
26520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
26530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
2654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kSwapElements, 3);
26550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2659f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
2660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_NE(NULL, args->at(0)->AsLiteral());
2663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
2664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<FixedArray> jsfunction_result_caches(
2666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Top::global_context()->jsfunction_result_caches());
2667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (jsfunction_result_caches->length() <= cache_id) {
2668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Abort("Attempt to use undefined cache.");
2669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
26700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
2671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
2675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register key = r0;
2677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register cache = r1;
267859151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(cache, ContextOperand(cp, Context::GLOBAL_INDEX));
2679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(cache, FieldMemOperand(cache, GlobalObject::kGlobalContextOffset));
268059151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
2681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(cache,
2682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
2683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, not_found;
2686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // tmp now holds finger offset as a smi.
2687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
2688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset));
2689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r2 now holds finger offset as a smi.
2690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
2691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r3 now points to the start of fixed array elements.
2692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2 - kSmiTagSize, PreIndex));
2693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Note side effect of PreIndex: r3 now points to the key of the pair.
2694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(key, r2);
2695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(ne, &not_found);
2696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ldr(r0, MemOperand(r3, kPointerSize));
2698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ b(&done);
2699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&not_found);
2701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call runtime to perform the lookup.
2702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(cache, key);
2703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetFromCache, 2);
2704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
27060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2710bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
2711bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT_EQ(2, args->length());
2712bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2713bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register right = r0;
2714bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register left = r1;
2715bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register tmp = r2;
2716bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register tmp2 = r3;
2717bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
27180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
27190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
2720bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(left);
2721bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2722bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label done, fail, ok;
2723bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(left, Operand(right));
2724bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(eq, &ok);
2725bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Fail if either is a non-HeapObject.
2726bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ and_(tmp, left, Operand(right));
2727bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ tst(tmp, Operand(kSmiTagMask));
2728bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(eq, &fail);
2729bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ldr(tmp, FieldMemOperand(left, HeapObject::kMapOffset));
2730bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ldrb(tmp2, FieldMemOperand(tmp, Map::kInstanceTypeOffset));
2731bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(tmp2, Operand(JS_REGEXP_TYPE));
2732bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(ne, &fail);
2733bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
2734bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(tmp, Operand(tmp2));
2735bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(ne, &fail);
2736bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ldr(tmp, FieldMemOperand(left, JSRegExp::kDataOffset));
2737bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ldr(tmp2, FieldMemOperand(right, JSRegExp::kDataOffset));
2738bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(tmp, tmp2);
2739bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ b(eq, &ok);
2740bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&fail);
2741bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ LoadRoot(r0, Heap::kFalseValueRootIndex);
2742bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ jmp(&done);
2743bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&ok);
2744bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ LoadRoot(r0, Heap::kTrueValueRootIndex);
2745bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&done);
2746bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
27470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2748bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
2749bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2750bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
275180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
27520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
275380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
275480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
275580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
275680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
275780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
27580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
27590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
276080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
276180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
276280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ tst(r0, Operand(String::kContainsCachedArrayIndexMask));
276380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
276480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ b(eq, if_true);
276580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ b(if_false);
276680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
27670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
276880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
276980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
277080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
277180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
277280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(args->length() == 1);
27730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
277480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
277580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ IndexFromHash(r0, r0);
27760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
277780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
277880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
277980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
27808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
27818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
27828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  context()->Plug(r0);
27838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return;
27848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
27858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
27868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2787d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
2788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<String> name = expr->name();
2789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (name->length() > 0 && name->Get(0) == '_') {
2790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ InlineRuntimeCall");
2791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitInlineRuntimeCall(expr);
2792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ CallRuntime");
27963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* args = expr->arguments();
27973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
2799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Prepare for calling JS runtime function.
28008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r0, GlobalObjectOperand());
2801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset));
2802402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(r0);
2803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
28043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
28053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Push the arguments ("left-to-right").
28063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
28073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
28080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
2809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
2812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call the JS runtime function.
2813402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(r2, Operand(expr->name()));
28148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, NOT_IN_LOOP);
28150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET);
2816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Restore context register.
2817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
2819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call the C runtime function.
2820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(expr->function(), arg_count);
2821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
28220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
2823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2826d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
2828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Token::DELETE: {
2829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
2830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Property* prop = expr->expression()->AsProperty();
2831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
2832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (prop == NULL && var == NULL) {
2833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Result of deleting non-property, non-variable reference is true.
2834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The subexpression may have side effects.
2835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForEffect(expr->expression());
28360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(true);
2837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else if (var != NULL &&
2838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 !var->is_global() &&
28390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 var->AsSlot() != NULL &&
28400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 var->AsSlot()->type() != Slot::LOOKUP) {
2841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Result of deleting non-global, non-dynamic variables is false.
2842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The subexpression does not have side effects.
28430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(false);
2844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else {
2845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Property or variable reference.  Call the delete builtin with
2846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // object and property name as arguments.
2847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (prop != NULL) {
28480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForStackValue(prop->obj());
28490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForStackValue(prop->key());
2850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (var->is_global()) {
28518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang          __ ldr(r1, GlobalObjectOperand());
2852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ mov(r0, Operand(var->name()));
2853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ Push(r1, r0);
2854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else {
2855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Non-global variable.  Call the runtime to look up the context
2856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // where the variable was introduced.
2857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(context_register());
2858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ mov(r2, Operand(var->name()));
2859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(r2);
2860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kLookupContext, 2);
2861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(r0);
2862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ mov(r2, Operand(var->name()));
2863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(r2);
2864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
2865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
28660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(r0);
2867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
2868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
2872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
2873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
28740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(Heap::kUndefinedValueRootIndex);
2875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2877d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2878d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
2879d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label materialize_true, materialize_false;
2881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label* if_true = NULL;
2882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label* if_false = NULL;
288380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label* fall_through = NULL;
2884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Notice that the labels are swapped.
28860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->PrepareTest(&materialize_true, &materialize_false,
28870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             &if_false, &if_true, &fall_through);
288880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      VisitForControl(expr->expression(), if_true, if_false, fall_through);
28890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(if_false, if_true);  // Labels swapped.
2890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
2894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
28950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      { StackValueContext context(this);
28960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForTypeofValue(expr->expression());
28970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
2898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallRuntime(Runtime::kTypeof, 1);
28990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(r0);
2900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
29013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
2902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2903d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Token::ADD: {
2904d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Comment cmt(masm_, "[ UnaryOperation (ADD)");
29050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->expression());
2906d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Label no_conversion;
2907d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ tst(result_register(), Operand(kSmiTagMask));
2908d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ b(eq, &no_conversion);
2909d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ push(r0);
2910d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
2911d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ bind(&no_conversion);
29120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(result_register());
2913d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      break;
2914d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
2915d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
29164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::SUB: {
29174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (SUB)");
291880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
2919ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke      UnaryOverwriteMode overwrite =
2920ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke          can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
29210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      GenericUnaryOpStub stub(Token::SUB,
29220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                              overwrite,
29230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                              NO_UNARY_FLAGS);
29244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // GenericUnaryOpStub expects the argument to be in the
29254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // accumulator register r0.
29260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->expression());
29274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
29280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(r0);
29294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
29304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
29314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
29324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::BIT_NOT: {
29334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
293480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // The generic unary operation stub expects the argument to be
293580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // in the accumulator register r0.
29360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->expression());
293780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label done;
29380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      bool inline_smi_code = ShouldInlineSmiCase(expr->op());
29390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (inline_smi_code) {
294080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Label call_stub;
294180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ BranchOnNotSmi(r0, &call_stub);
294280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ mvn(r0, Operand(r0));
294380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        // Bit-clear inverted smi-tag.
294480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bic(r0, r0, Operand(kSmiTagMask));
294580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ b(&done);
294680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&call_stub);
294780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
294880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      bool overwrite = expr->expression()->ResultOverwriteAllowed();
29490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      UnaryOpFlags flags = inline_smi_code
29500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          ? NO_UNARY_SMI_CODE_IN_STUB
29510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          : NO_UNARY_FLAGS;
295280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      UnaryOverwriteMode mode =
295380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
29540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      GenericUnaryOpStub stub(Token::BIT_NOT, mode, flags);
29554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
29564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ bind(&done);
29570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(r0);
29584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
29594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
29604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
2961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
2962d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
29633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2964d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2965d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2966d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2967d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
2968d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CountOperation");
296980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
297080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
2972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // as the left-hand side.
2973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->expression()->IsValidLeftHandSide()) {
2974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->expression());
2975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2977d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2978e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Expression can only be a property, a global or a (parameter or local)
2979e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
2980e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
2981e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LhsKind assign_type = VARIABLE;
2982e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
2983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In case of a property we use the uninitialized expression context
2984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // of the key to detect a named property.
2985e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (prop != NULL) {
2986e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    assign_type =
2987e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
2988d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2989e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2990e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
2991e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
2992e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
29930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
29940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitVariableLoad(expr->expression()->AsVariableProxy()->var());
29953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2996e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
29970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (expr->is_postfix() && !context()->IsEffect()) {
2998e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(ip, Operand(Smi::FromInt(0)));
2999e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ push(ip);
3000e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3001e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (assign_type == NAMED_PROPERTY) {
3002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Put the object both on the stack and in the accumulator.
30030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
3004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(r0);
3005e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitNamedPropertyLoad(prop);
3006e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
30070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(prop->obj());
30080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->key());
300925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      __ ldr(r1, MemOperand(sp, 0));
301025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      __ push(r0);
3011e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitKeyedPropertyLoad(prop);
3012e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3013d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3014d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3015d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Call ToNumber only if operand is not a smi.
3016d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label no_conversion;
3017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ BranchOnSmi(r0, &no_conversion);
3018d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ push(r0);
3019e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
3020d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&no_conversion);
3021e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3022e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
3023e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
30240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (!context()->IsEffect()) {
30250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Save the result on the stack. If we have a named or keyed property
30260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // we store the result under the receiver that is currently on top
30270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // of the stack.
30280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
30290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
30300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ push(r0);
30310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
30320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
30330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ str(r0, MemOperand(sp, kPointerSize));
30340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
30350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
30360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ str(r0, MemOperand(sp, 2 * kPointerSize));
30370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
30380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
3039e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3040e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3041e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3042d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3043d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Inline smi case if we are in a loop.
3044d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label stub_call, done;
304510e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu  int count_value = expr->op() == Token::INC ? 1 : -1;
304680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (ShouldInlineSmiCase(expr->op())) {
304710e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu    __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC);
3048d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ b(vs, &stub_call);
3049d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // We could eliminate this smi check if we split the code at
3050d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // the first smi check before calling ToNumber.
3051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ BranchOnSmi(r0, &done);
3052d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ bind(&stub_call);
3053d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Call stub. Undo operation first.
305410e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu    __ sub(r0, r0, Operand(Smi::FromInt(count_value)));
3055d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
305610e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu  __ mov(r1, Operand(Smi::FromInt(count_value)));
30576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0);
3058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
3059d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
3060e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3061e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in r0.
3062e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
3063e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case VARIABLE:
3064e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
30650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        { EffectContext context(this);
30660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
30670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                 Token::ASSIGN);
30680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        }
30690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        // For all contexts except EffectConstant We have the result on
3070e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
30710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
30720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
3075e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
30760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                               Token::ASSIGN);
3077e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3078d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3079e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
3080e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
3081402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ pop(r1);
3082e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
30830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
3084e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
30850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
30860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3087e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3088e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
30890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(r0);
3090e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3091d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3092d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3093e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
3094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r1);  // Key.
3095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(r2);  // Receiver.
3096e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
30970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
3098e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
30990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
31000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3101e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
31030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(r0);
3104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3105d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3106d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
31073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
31083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
31093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
31103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
31110d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
31120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!context()->IsEffect());
31130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!context()->IsTest());
311480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  VariableProxy* proxy = expr->AsVariableProxy();
311580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
311680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Comment cmnt(masm_, "Global variable");
31178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r0, GlobalObjectOperand());
311880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(r2, Operand(proxy->name()));
311980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
312080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Use a regular load, not a contextual load, to avoid a reference
312180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // error.
31220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET);
31230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
312480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (proxy != NULL &&
31250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen             proxy->var()->AsSlot() != NULL &&
31260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen             proxy->var()->AsSlot()->type() == Slot::LOOKUP) {
312759151504615d929945dc59db37bf1166937748c6Steve Block    Label done, slow;
312859151504615d929945dc59db37bf1166937748c6Steve Block
312959151504615d929945dc59db37bf1166937748c6Steve Block    // Generate code for loading from variables potentially shadowed
313059151504615d929945dc59db37bf1166937748c6Steve Block    // by eval-introduced variables.
31310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* slot = proxy->var()->AsSlot();
313259151504615d929945dc59db37bf1166937748c6Steve Block    EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
313359151504615d929945dc59db37bf1166937748c6Steve Block
313459151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
313580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(r0, Operand(proxy->name()));
313680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ Push(cp, r0);
313780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
313859151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&done);
313959151504615d929945dc59db37bf1166937748c6Steve Block
31400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(r0);
314180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
314280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // This expression cannot throw a reference error at the top level.
31430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Visit(expr);
3144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
31473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
314880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenbool FullCodeGenerator::TryLiteralCompare(Token::Value op,
314980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Expression* left,
315080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Expression* right,
315180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Label* if_true,
315280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Label* if_false,
315380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Label* fall_through) {
315480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (op != Token::EQ && op != Token::EQ_STRICT) return false;
315580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
315680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check for the pattern: typeof <expression> == <string literal>.
315780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Literal* right_literal = right->AsLiteral();
315880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (right_literal == NULL) return false;
315980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Handle<Object> right_literal_value = right_literal->handle();
316080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (!right_literal_value->IsString()) return false;
316180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  UnaryOperation* left_unary = left->AsUnaryOperation();
316280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
316380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Handle<String> check = Handle<String>::cast(right_literal_value);
316480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
31650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  { AccumulatorValueContext context(this);
31660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForTypeofValue(left_unary->expression());
31670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
316880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (check->Equals(Heap::number_symbol())) {
316980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ tst(r0, Operand(kSmiTagMask));
3170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(eq, if_true);
317180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
317280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
317380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r0, ip);
317480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
317580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::string_symbol())) {
317680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ tst(r0, Operand(kSmiTagMask));
317780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(eq, if_false);
317880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
317980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
318080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
318180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
318280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r1, Operand(1 << Map::kIsUndetectable));
318380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(eq, if_false);
318480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldrb(r1, FieldMemOperand(r0, Map::kInstanceTypeOffset));
318580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r1, Operand(FIRST_NONSTRING_TYPE));
318680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(lt, if_true, if_false, fall_through);
318780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::boolean_symbol())) {
318880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(ip, Heap::kTrueValueRootIndex);
318980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r0, ip);
3190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(eq, if_true);
319180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(ip, Heap::kFalseValueRootIndex);
319280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r0, ip);
319380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
319480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::undefined_symbol())) {
3195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
319680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r0, ip);
3197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ b(eq, if_true);
319880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ tst(r0, Operand(kSmiTagMask));
319980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(eq, if_false);
320080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => true.
320180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
320280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
320380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
320480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r1, Operand(1 << Map::kIsUndetectable));
320580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
320680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::function_symbol())) {
320780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ tst(r0, Operand(kSmiTagMask));
320880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(eq, if_false);
320980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareObjectType(r0, r1, r0, JS_FUNCTION_TYPE);
321080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(eq, if_true);
321180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Regular expressions => 'function' (they are callable).
321280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareInstanceType(r1, r0, JS_REGEXP_TYPE);
321380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
321480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::object_symbol())) {
321580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ tst(r0, Operand(kSmiTagMask));
321680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(eq, if_false);
321780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(ip, Heap::kNullValueRootIndex);
321880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r0, ip);
321980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(eq, if_true);
322080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Regular expressions => 'function', not 'object'.
322180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareObjectType(r0, r1, r0, JS_REGEXP_TYPE);
322280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(eq, if_false);
322380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
322480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldrb(r0, FieldMemOperand(r1, Map::kBitFieldOffset));
322580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ and_(r0, r0, Operand(1 << Map::kIsUndetectable));
322680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r0, Operand(1 << Map::kIsUndetectable));
322780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(eq, if_false);
322880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for JS objects => true.
322980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldrb(r0, FieldMemOperand(r1, Map::kInstanceTypeOffset));
323080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r0, Operand(FIRST_JS_OBJECT_TYPE));
323180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(lt, if_false);
323280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r0, Operand(LAST_JS_OBJECT_TYPE));
323380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(le, if_true, if_false, fall_through);
323480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
323580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (if_false != fall_through) __ jmp(if_false);
3236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
323780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
323880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return true;
3239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3242d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
3243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
324480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
3245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
3247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
3248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
325280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
32530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
32540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
325580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
325680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // First we try a fast inlined version of the compare when one of
325780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the operands is a literal.
325880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Token::Value op = expr->op();
325980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Expression* left = expr->left();
326080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Expression* right = expr->right();
326180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) {
32620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(if_true, if_false);
326380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return;
326480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
3265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
32660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->left());
326780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
3268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
32690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
3270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ InvokeBuiltin(Builtins::IN, CALL_JS);
3271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ LoadRoot(ip, Heap::kTrueValueRootIndex);
3272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ cmp(r0, ip);
327380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(eq, if_true, if_false, fall_through);
3274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
32770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
3278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      InstanceofStub stub;
3279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
328080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // The stub returns 0 for true.
3281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ tst(r0, r0);
328280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(eq, if_true, if_false, fall_through);
3283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
32870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->right());
3288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Condition cc = eq;
3289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      bool strict = false;
329080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      switch (op) {
3291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::EQ_STRICT:
3292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          strict = true;
3293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Fall through
329480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        case Token::EQ:
3295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = eq;
3296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(r1);
3297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LT:
3299d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = lt;
3300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(r1);
3301d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GT:
3303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Reverse left and right sides to obtain ECMA-262 conversion order.
3304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = lt;
3305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(r1, result_register());
3306d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(r0);
3307d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block         break;
3308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LTE:
3309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Reverse left and right sides to obtain ECMA-262 conversion order.
3310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = ge;
3311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(r1, result_register());
3312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(r0);
3313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GTE:
3315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = ge;
3316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(r1);
3317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::IN:
3319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::INSTANCEOF:
3320d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default:
3321d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
3322d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
3323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
33240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      bool inline_smi_code = ShouldInlineSmiCase(op);
33250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (inline_smi_code) {
332680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Label slow_case;
332780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ orr(r2, r0, Operand(r1));
332880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ BranchOnNotSmi(r2, &slow_case);
332980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ cmp(r1, r0);
333080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Split(cc, if_true, if_false, NULL);
333180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&slow_case);
333280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
33330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      CompareFlags flags = inline_smi_code
33340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          ? NO_SMI_COMPARE_IN_STUB
33350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          : NO_COMPARE_FLAGS;
33360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      CompareStub stub(cc, strict, flags, r1, r0);
3337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
33389ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick      __ cmp(r0, Operand(0, RelocInfo::NONE));
333980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(cc, if_true, if_false, fall_through);
33403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
33413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
33423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
3344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
33450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
33473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3348d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
334980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) {
335080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Comment cmnt(masm_, "[ CompareToNull");
335180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
335280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
335380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
335480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
33550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
33560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
335780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
33580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(expr->expression());
335980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ LoadRoot(r1, Heap::kNullValueRootIndex);
336080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ cmp(r0, r1);
336180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (expr->is_strict()) {
336280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
336380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
336480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(eq, if_true);
336580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
336680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r0, r1);
336780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(eq, if_true);
336880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ tst(r0, Operand(kSmiTagMask));
336980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ b(eq, if_false);
337080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // It can be an undetectable object.
337180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
337280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
337380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
337480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(r1, Operand(1 << Map::kIsUndetectable));
337580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(eq, if_true, if_false, fall_through);
337680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
33770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
337880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
337980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
338080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3381d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
3382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
33830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(r0);
3384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
33870d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() {
33880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return r0;
33890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
3390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
33920d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() {
33930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return cp;
33940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
33950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
33960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
33970d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) {
33980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(mode == RelocInfo::CODE_TARGET ||
33990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen         mode == RelocInfo::CODE_TARGET_CONTEXT);
34000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Call(ic, mode);
34010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
3402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3404d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
3405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
3406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ str(value, MemOperand(fp, frame_offset));
3407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
34083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3410d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
341159151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(dst, ContextOperand(cp, context_index));
34123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
34133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3414d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ----------------------------------------------------------------------------
3416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support.
3417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3418d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() {
3419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(r1));
3420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store result register while executing finally block.
3421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
3422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Cook return address in link register to stack (smi encoded Code* delta)
3423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ sub(r1, lr, Operand(masm_->CodeObject()));
3424e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
3425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, kSmiTag);
3426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(r1, r1, Operand(r1));  // Convert to smi.
3427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(r1);
3428e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3431d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() {
3432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(r1));
3433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Restore result register from stack.
3434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(r1);
3435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Uncook return address and return.
3436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(result_register());
3437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
3438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(r1, Operand(r1, ASR, 1));  // Un-smi-tag value.
3439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(pc, r1, Operand(masm_->CodeObject()));
3440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef __
3444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
34453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} }  // namespace v8::internal
3446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
3448