full-codegen-ia32.cc revision db5a90a88cfcddb042912799e872037c6548b8a3
1f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// Copyright 2010 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_IA32)
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "code-stubs.h"
333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "codegen-inl.h"
34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h"
35e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#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, with the
483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them.  The actual argument count matches the
493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function.
503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are:
523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o edi: the JS function object being called (ie, ourselves)
533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o esi: our context
543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o ebp: our caller's frame pointer
553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o esp: stack pointer (pointing to return address)
563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame.  Please see JavaScriptFrameConstants in
583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-ia32.h for its layout.
59756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::Generate(CompilationInfo* info) {
603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ASSERT(info_ == NULL);
613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  info_ = info;
623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  SetFunctionPosition(function());
636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comment cmnt(masm_, "[ function compiled by full code generator");
643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
65f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG
66f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (strlen(FLAG_stop_at) > 0 &&
67f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
68f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ int3();
69f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
70f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif
71f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
72756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(ebp);  // Caller's frame pointer.
73756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ mov(ebp, esp);
74756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(esi);  // Callee's context.
75756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(edi);  // Callee's JS Function.
76756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
77756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  { Comment cmnt(masm_, "[ Allocate locals");
78756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    int locals_count = scope()->num_stack_slots();
79756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (locals_count == 1) {
80756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ push(Immediate(Factory::undefined_value()));
81756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else if (locals_count > 1) {
82756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ mov(eax, Immediate(Factory::undefined_value()));
83756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      for (int i = 0; i < locals_count; i++) {
84756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ push(eax);
85d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
86d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
87756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
88d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
89756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  bool function_in_register = true;
904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
91756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate a local context.
92756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
93756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (heap_slots > 0) {
94756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate local context");
95756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Argument to NewContext is the function, which is still in edi.
96756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ push(edi);
97756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
98756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      FastNewContextStub stub(heap_slots);
99756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ CallStub(&stub);
100756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
101756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ CallRuntime(Runtime::kNewContext, 1);
102756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
103756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    function_in_register = false;
104756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Context is returned in both eax and esi.  It replaces the context
105756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // passed to us.  It's saved in the stack and kept live in esi.
106756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
107756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
108756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Copy parameters into context if necessary.
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        __ mov(eax, Operand(ebp, parameter_offset));
117756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Store it in the context.
118756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        int context_offset = Context::SlotOffset(slot->index());
119756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ mov(Operand(esi, context_offset), eax);
120756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Update the write barrier. This clobbers all involved
121756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // registers, so we have use a third register to avoid
122756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // clobbering esi.
123756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ mov(ecx, esi);
124756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ RecordWrite(ecx, context_offset, eax, ebx);
125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
127756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
1283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve 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      __ push(edi);
135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
136756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
138756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Receiver is just before the parameters on the caller's stack.
139756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    int offset = scope()->num_parameters() * kPointerSize;
140756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ lea(edx,
141756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
142756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ push(edx);
143756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ push(Immediate(Smi::FromInt(scope()->num_parameters())));
144756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Arguments to ArgumentsAccessStub:
145756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    //   function, receiver address, parameter count.
146756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The stub will rewrite receiver and parameter count if the previous
147756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // stack frame was an arguments adapter frame.
148756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
149756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
150756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ mov(ecx, eax);  // Duplicate result.
1510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Move(arguments->AsSlot(), eax, ebx, edx);
1520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot();
153756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Move(dot_arguments_slot, ecx, ebx, edx);
154d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { Comment cmnt(masm_, "[ Declarations");
157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // For named function expressions, declare the function name as a
158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // constant.
159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (scope()->is_function_scope() && scope()->function() != NULL) {
160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      EmitDeclaration(scope()->function(), Variable::CONST, NULL);
161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Visit all the explicit declarations unless there is an illegal
163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // redeclaration.
164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (scope()->HasIllegalRedeclaration()) {
165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      scope()->VisitIllegalRedeclaration(this);
166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitDeclarations(scope()->declarations());
168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ Stack check");
1720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    NearLabel ok;
173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ExternalReference stack_limit =
174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ExternalReference::address_of_stack_limit();
175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ cmp(esp, Operand::StaticVariable(stack_limit));
1763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(above_equal, &ok, taken);
1773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    StackCheckStub stub;
1783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CallStub(&stub);
1793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&ok);
1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (FLAG_trace) {
1833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CallRuntime(Runtime::kTraceEnter, 0);
1843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ Body");
187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    VisitStatements(function()->body());
189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit a 'return undefined' in case control fell off the end of the body.
1943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(eax, Factory::undefined_value());
1957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    EmitReturnSequence();
196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
200db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdochvoid FullCodeGenerator::ClearAccumulator() {
201db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  __ Set(eax, Immediate(Smi::FromInt(0)));
202db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch}
203db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
204db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
2057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() {
206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ jmp(&return_label_);
209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Common return label
211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
2123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
2133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(eax);
2143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ CallRuntime(Runtime::kTraceExit, 1);
2153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG
217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Add a label for checking the size of the code used for returning.
218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Label check_exit_codesize;
219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    masm_->bind(&check_exit_codesize);
220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
221bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
2223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ RecordJSReturn();
2233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Do not use the leave instruction here because it is too short to
2243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // patch with the code required by the debugger.
2253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(esp, ebp);
2263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ pop(ebp);
2273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    __ ret((scope()->num_parameters() + 1) * kPointerSize);
228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT
229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Check that the size of the code used for returning matches what is
230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // expected by the debugger.
231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_EQ(Assembler::kJSReturnSequenceLength,
23280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen              masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
23880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenFullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand(
23980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Token::Value op, Expression* left, Expression* right) {
24080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(ShouldInlineSmiCase(op));
24180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (op == Token::DIV || op == Token::MOD || op == Token::MUL) {
24280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // We never generate inlined constant smi operations for these.
24380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return kNoConstants;
24480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (right->IsSmiLiteral()) {
24580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return kRightConstant;
24680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (left->IsSmiLiteral() && !Token::IsShiftOp(op)) {
24780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return kLeftConstant;
24880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
24980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return kNoConstants;
25080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
25180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
25280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
25380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2540d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
2550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2580d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const {
2590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
2600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), slot_operand);
2610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2640d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
2650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
2660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Memory operands can be pushed directly.
2670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(slot_operand);
268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2710d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Slot* slot) const {
2720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
2730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->Move(result_register(), slot);
2740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->DoTest(true_label_, false_label_, fall_through_);
2750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2780d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
2790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  UNREACHABLE();  // Not used on IA32.
280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2830d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
2840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
2850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  UNREACHABLE();  // Not used on IA32.
2860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2890d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
2900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
2910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  UNREACHABLE();  // Not used on IA32.
292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2950d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
2960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  UNREACHABLE();  // Not used on IA32.
2970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3000d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
3010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3040d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
3050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Handle<Object> lit) const {
3060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), lit);
3070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
3080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3100d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
3110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Immediates can be pushed directly.
3120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(Immediate(lit));
3130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
3140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3160d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
3170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!lit->IsUndetectableObject());  // There are no undetectable literals.
3180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
3190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ jmp(false_label_);
3200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsTrue() || lit->IsJSObject()) {
3210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ jmp(true_label_);
3220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsString()) {
3230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (String::cast(*lit)->length() == 0) {
3240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ jmp(false_label_);
3250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
3260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ jmp(true_label_);
3270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
3280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsSmi()) {
3290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (Smi::cast(*lit)->value() == 0) {
3300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ jmp(false_label_);
3310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
3320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ jmp(true_label_);
3330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
3340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
3350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // For simplicity we always test the accumulator register.
3360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ mov(result_register(), lit);
3370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    codegen()->DoTest(true_label_, false_label_, fall_through_);
338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3420d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count,
3430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                   Register reg) const {
344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(count > 0);
3450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
3460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3490d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
3500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    int count,
3510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Register reg) const {
3520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
3530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
3540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
3550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3580d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count,
3590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                       Register reg) const {
3600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
3610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (count > 1) __ Drop(count - 1);
3620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(Operand(esp, 0), reg);
363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3660d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count,
3670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                 Register reg) const {
3680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
3690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
3700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
3710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
3720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->DoTest(true_label_, false_label_, fall_through_);
3730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3760d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
3770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            Label* materialize_false) const {
3780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT_EQ(materialize_true, materialize_false);
3790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
3800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3830d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
3840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
3850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
3860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel done;
3870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
3880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), Factory::true_value());
3890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ jmp(&done);
3900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
3910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), Factory::false_value());
3920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3960d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
3970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
3980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
3990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel done;
4000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
4010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(Immediate(Factory::true_value()));
4020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ jmp(&done);
4030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
4040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(Immediate(Factory::false_value()));
4050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
4060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4090d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true,
4100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                          Label* materialize_false) const {
4110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(materialize_false == false_label_);
4120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(materialize_true == true_label_);
4130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4160d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const {
4170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4200d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
4210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Handle<Object> value =
4220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Factory::true_value() : Factory::false_value();
4230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), value);
4240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4270d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const {
4280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Handle<Object> value =
4290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Factory::true_value() : Factory::false_value();
4300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(Immediate(value));
4310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4340d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const {
4350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (flag) {
4360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (true_label_ != fall_through_) __ jmp(true_label_);
4370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
4380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (false_label_ != fall_through_) __ jmp(false_label_);
439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
44380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::DoTest(Label* if_true,
44480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* if_false,
44580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* fall_through) {
446e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the inlined tests assumed by the stub.
447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(result_register(), Factory::undefined_value());
448e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(result_register(), Factory::true_value());
450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_true);
451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(result_register(), Factory::false_value());
452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, kSmiTag);
454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ test(result_register(), Operand(result_register()));
455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(zero, if_false);
456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ test(result_register(), Immediate(kSmiTagMask));
457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(zero, if_true);
458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call the ToBoolean stub for all other cases.
460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ToBooleanStub stub;
461e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ test(eax, Operand(eax));
464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
46580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The stub returns nonzero for true.
46680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(not_zero, if_true, if_false, fall_through);
46780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
468e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
47080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::Split(Condition cc,
47180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_true,
47280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_false,
47380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* fall_through) {
47480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (if_false == fall_through) {
47580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(cc, if_true);
47680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (if_true == fall_through) {
47780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(NegateCondition(cc), if_false);
47880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
47980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(cc, if_true);
48080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ jmp(if_false);
481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
485d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (slot->type()) {
487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::PARAMETER:
488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOCAL:
489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return Operand(ebp, SlotOffset(slot));
490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::CONTEXT: {
491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      int context_chain_length =
4923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          scope()->ContextChainLength(slot->var()->scope());
493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ LoadContext(scratch, context_chain_length);
49459151504615d929945dc59db37bf1166937748c6Steve Block      return ContextOperand(scratch, slot->index());
495d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOOKUP:
497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  UNREACHABLE();
500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return Operand(eax, 0);
501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
504d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) {
505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(source, destination);
506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(destination, location);
507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
510d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst,
511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register src,
512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch1,
513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch2) {
514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(dst->type() != Slot::LOOKUP);  // Not yet implemented.
515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!scratch1.is(src) && !scratch2.is(src));
516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(dst, scratch1);
517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(location, src);
518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (dst->type() == Slot::CONTEXT) {
520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
521e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ RecordWrite(scratch1, offset, src, scratch2);
522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitDeclaration(Variable* variable,
527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Variable::Mode mode,
528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        FunctionLiteral* function) {
529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Declaration");
530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(variable != NULL);  // Must have been resolved.
5310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Slot* slot = variable->AsSlot();
532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = variable->AsProperty();
533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (slot != NULL) {
534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
536d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOCAL:
537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(Operand(ebp, SlotOffset(slot)),
539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                 Immediate(Factory::the_hole_value()));
540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
5410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForAccumulatorValue(function);
542e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(Operand(ebp, SlotOffset(slot)), result_register());
543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
546d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT:
547e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // We bypass the general EmitSlotSearch because we know more about
548e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // this specific context.
549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // The variable in the decl always resides in the current context.
551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (FLAG_debug_code) {
553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Check if we have the correct context pointer.
55459151504615d929945dc59db37bf1166937748c6Steve Block          __ mov(ebx, ContextOperand(esi, Context::FCONTEXT_INDEX));
555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ cmp(ebx, Operand(esi));
556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Check(equal, "Unexpected declaration in current context.");
557d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
55959151504615d929945dc59db37bf1166937748c6Steve Block          __ mov(ContextOperand(esi, slot->index()),
560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 Immediate(Factory::the_hole_value()));
561d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // No write barrier since the hole value is in old space.
562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
5630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForAccumulatorValue(function);
56459151504615d929945dc59db37bf1166937748c6Steve Block          __ mov(ContextOperand(esi, slot->index()), result_register());
565d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          int offset = Context::SlotOffset(slot->index());
5664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ mov(ebx, esi);
5674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ RecordWrite(ebx, offset, result_register(), ecx);
568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP: {
572d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(esi);
573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(Immediate(variable->name()));
574d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Declaration nodes are always introduced in one of two modes.
575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ASSERT(mode == Variable::VAR || mode == Variable::CONST);
576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY;
577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(Immediate(Smi::FromInt(attr)));
578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Push initial value, if any.
579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Note: For variables we must not push an initial value (such as
580d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // 'undefined') because we may have a (legal) redeclaration and we
581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // must not destroy the current value.
582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ push(Immediate(Factory::the_hole_value()));
584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
5850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForStackValue(function);
586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else {
587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ push(Immediate(Smi::FromInt(0)));  // No initial value!
588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDeclareContextSlot, 4);
590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
591d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (prop != NULL) {
595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (function != NULL || mode == Variable::CONST) {
596d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // We are declaring a function or constant that rewrites to a
597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // property.  Use (keyed) IC to set the initial value.
5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(prop->obj());
599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (function != NULL) {
6000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(prop->key());
6010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(function);
6026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ pop(ecx);
603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
6040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(prop->key());
6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ mov(ecx, result_register());
606e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ mov(result_register(), Factory::the_hole_value());
607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
6086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ pop(edx);
609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
6110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
6133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
6143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
6153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) {
618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
622d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
6233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
6243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(esi);  // The context is the first argument.
6253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(pairs));
6263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
6273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kDeclareGlobals, 3);
6283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
6293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
6303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ SwitchStatement");
634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Breakable nested_statement(this, stmt);
635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Keep the switch value on the stack until a case matches.
6370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(stmt->tag());
638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<CaseClause*>* clauses = stmt->cases();
640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label next_test;  // Recycled for each test.
643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the tests with branches to their bodies.
644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The default is not a test, but remember it as final fall through.
647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (clause->is_default()) {
648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      default_clause = clause;
649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      continue;
650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case comparison");
653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&next_test);
654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    next_test.Unuse();
655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Compile the label expression.
6570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(clause->label());
658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
65980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Perform the comparison as if via '==='.
660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(edx, Operand(esp, 0));  // Switch value.
6610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
6620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (inline_smi_code) {
6630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      NearLabel slow_case;
66480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ mov(ecx, edx);
66580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ or_(ecx, Operand(eax));
66680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ test(ecx, Immediate(kSmiTagMask));
66780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(not_zero, &slow_case, not_taken);
66880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ cmp(edx, Operand(eax));
66980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(not_equal, &next_test);
67080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ Drop(1);  // Switch value is no longer needed.
67180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ jmp(clause->body_target()->entry_label());
67280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&slow_case);
67380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
6750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    CompareFlags flags = inline_smi_code
6760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        ? NO_SMI_COMPARE_IN_STUB
6770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        : NO_COMPARE_FLAGS;
6780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    CompareStub stub(equal, true, flags);
679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ test(eax, Operand(eax));
681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(not_equal, &next_test);
682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(clause->body_target()->entry_label());
684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
6853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Discard the test value and jump to the default if present, otherwise to
687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the end of the statement.
688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&next_test);
689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(1);  // Switch value is no longer needed.
690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (default_clause == NULL) {
691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(nested_statement.break_target());
692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(default_clause->body_target()->entry_label());
694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the case bodies.
697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case body");
699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(clause->body_target()->entry_label());
701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitStatements(clause->statements());
702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(nested_statement.break_target());
705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ ForInStatement");
710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label loop, exit;
713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ForIn loop_statement(this, stmt);
714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  increment_loop_depth();
715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the object to enumerate over. Both SpiderMonkey and JSC
717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ignore null and undefined in contrast to the specification; see
718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ECMA-262 section 12.6.4.
7190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(stmt->enumerable());
720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Factory::undefined_value());
721f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Factory::null_value());
723f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the object to a JS object.
7260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel convert, done_convert;
727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, &convert);
729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
730f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(above_equal, &done_convert);
731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&convert);
732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);
733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done_convert);
735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);
7363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
73759151504615d929945dc59db37bf1166937748c6Steve Block  // Check cache validity in generated code. This is a fast case for
73859151504615d929945dc59db37bf1166937748c6Steve Block  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
73959151504615d929945dc59db37bf1166937748c6Steve Block  // guarantee cache validity, call the runtime system to check cache
74059151504615d929945dc59db37bf1166937748c6Steve Block  // validity or get the property names in a fixed array.
74159151504615d929945dc59db37bf1166937748c6Steve Block  Label next, call_runtime;
74259151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(ecx, eax);
74359151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&next);
74459151504615d929945dc59db37bf1166937748c6Steve Block
74559151504615d929945dc59db37bf1166937748c6Steve Block  // Check that there are no elements.  Register ecx contains the
74659151504615d929945dc59db37bf1166937748c6Steve Block  // current JS object we've reached through the prototype chain.
74759151504615d929945dc59db37bf1166937748c6Steve Block  __ cmp(FieldOperand(ecx, JSObject::kElementsOffset),
74859151504615d929945dc59db37bf1166937748c6Steve Block         Factory::empty_fixed_array());
74959151504615d929945dc59db37bf1166937748c6Steve Block  __ j(not_equal, &call_runtime);
75059151504615d929945dc59db37bf1166937748c6Steve Block
75159151504615d929945dc59db37bf1166937748c6Steve Block  // Check that instance descriptors are not empty so that we can
75259151504615d929945dc59db37bf1166937748c6Steve Block  // check for an enum cache.  Leave the map in ebx for the subsequent
75359151504615d929945dc59db37bf1166937748c6Steve Block  // prototype load.
75459151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
75559151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOffset));
75659151504615d929945dc59db37bf1166937748c6Steve Block  __ cmp(edx, Factory::empty_descriptor_array());
75759151504615d929945dc59db37bf1166937748c6Steve Block  __ j(equal, &call_runtime);
75859151504615d929945dc59db37bf1166937748c6Steve Block
75959151504615d929945dc59db37bf1166937748c6Steve Block  // Check that there in an enum cache in the non-empty instance
76059151504615d929945dc59db37bf1166937748c6Steve Block  // descriptors (edx).  This is the case if the next enumeration
76159151504615d929945dc59db37bf1166937748c6Steve Block  // index field does not contain a smi.
76259151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset));
76359151504615d929945dc59db37bf1166937748c6Steve Block  __ test(edx, Immediate(kSmiTagMask));
76459151504615d929945dc59db37bf1166937748c6Steve Block  __ j(zero, &call_runtime);
76559151504615d929945dc59db37bf1166937748c6Steve Block
76659151504615d929945dc59db37bf1166937748c6Steve Block  // For all objects but the receiver, check that the cache is empty.
7670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel check_prototype;
76859151504615d929945dc59db37bf1166937748c6Steve Block  __ cmp(ecx, Operand(eax));
76959151504615d929945dc59db37bf1166937748c6Steve Block  __ j(equal, &check_prototype);
77059151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset));
77159151504615d929945dc59db37bf1166937748c6Steve Block  __ cmp(edx, Factory::empty_fixed_array());
77259151504615d929945dc59db37bf1166937748c6Steve Block  __ j(not_equal, &call_runtime);
77359151504615d929945dc59db37bf1166937748c6Steve Block
77459151504615d929945dc59db37bf1166937748c6Steve Block  // Load the prototype from the map and loop if non-null.
77559151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&check_prototype);
77659151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
77759151504615d929945dc59db37bf1166937748c6Steve Block  __ cmp(ecx, Factory::null_value());
77859151504615d929945dc59db37bf1166937748c6Steve Block  __ j(not_equal, &next);
77959151504615d929945dc59db37bf1166937748c6Steve Block
78059151504615d929945dc59db37bf1166937748c6Steve Block  // The enum cache is valid.  Load the map of the object being
78159151504615d929945dc59db37bf1166937748c6Steve Block  // iterated over and use the cache for the iteration.
7820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel use_cache;
78359151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
78459151504615d929945dc59db37bf1166937748c6Steve Block  __ jmp(&use_cache);
785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the set of properties to enumerate.
78759151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&call_runtime);
788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);  // Duplicate the enumerable object on the stack.
789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If we got a map from the runtime call, we can do a fast
792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // modification check. Otherwise, we got a fixed array, and we have
793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // to do a slow check.
7940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel fixed_array;
795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::meta_map());
796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &fixed_array);
797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a map in register eax. Get the enumeration cache from it.
79959151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&use_cache);
800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset));
801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset));
802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Setup the four remaining stack slots.
805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);  // Map.
806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(edx);  // Enumeration cache.
807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset));
808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);  // Enumeration cache length (as smi).
809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(Smi::FromInt(0)));  // Initial index.
810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a fixed array in register eax. Iterate through that.
813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&fixed_array);
814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(Smi::FromInt(0)));  // Map (0) - force slow check.
815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);
816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);  // Fixed array length (as smi).
818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(Smi::FromInt(0)));  // Initial index.
819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for doing the condition check.
821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&loop);
822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(esp, 0 * kPointerSize));  // Get the current index.
823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Operand(esp, 1 * kPointerSize));  // Compare to the array length.
824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(above_equal, loop_statement.break_target());
825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the current entry of the array into register ebx.
827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, Operand(esp, 2 * kPointerSize));
828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize));
829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the expected map from the stack or a zero map in the
831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // permanent slow case into register edx.
832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, Operand(esp, 3 * kPointerSize));
833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the expected map still matches that of the enumerable.
835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If not, we have to filter the key.
8360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel update_each;
837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ecx, Operand(esp, 4 * kPointerSize));
838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset));
839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &update_each);
840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the entry to a string or null if it isn't a property
842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // anymore. If the property has been removed while iterating, we
843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // just skip it.
844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(ecx);  // Enumerable.
845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(ebx);  // Current entry.
846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
847756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ test(eax, Operand(eax));
848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, loop_statement.continue_target());
849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, Operand(eax));
850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the 'each' property or variable from the possibly filtered
852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // entry in register ebx.
853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&update_each);
854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(result_register(), ebx);
855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Perform the assignment as if via '='.
856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  EmitAssignment(stmt->each());
857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the body of the loop.
8590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label stack_limit_hit;
8600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel stack_check_done;
861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Visit(stmt->body());
862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ StackLimitCheck(&stack_limit_hit);
864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&stack_check_done);
865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for going to the next element by incrementing the
867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // index (smi) stored on top of the stack.
868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(loop_statement.continue_target());
869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Slow case for the stack limit check.
873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StackCheckStub stack_check_stub;
874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&stack_limit_hit);
875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stack_check_stub);
876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&stack_check_done);
877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Remove the pointers stored on the stack.
879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(loop_statement.break_target());
880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(Operand(esp), Immediate(5 * kPointerSize));
881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Exit and decrement the loop depth.
883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  decrement_loop_depth();
885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
8888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
8898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                       bool pretenure) {
890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Use the fast case closure allocation code that allocates in new
891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // space for nested functions that don't need literals cloning.
8928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (scope()->is_function_scope() &&
8938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      info->num_literals() == 0 &&
8948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      !pretenure) {
895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    FastNewClosureStub stub;
896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Immediate(info));
897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(esi);
900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Immediate(info));
9018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ push(Immediate(pretenure
9028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                      ? Factory::true_value()
9038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                      : Factory::false_value()));
9048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ CallRuntime(Runtime::kNewClosure, 3);
905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
9060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
9073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
9083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
910d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
9113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ VariableProxy");
9120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitVariableLoad(expr->var());
913e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
91659151504615d929945dc59db37bf1166937748c6Steve Blockvoid FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
91759151504615d929945dc59db37bf1166937748c6Steve Block    Slot* slot,
91859151504615d929945dc59db37bf1166937748c6Steve Block    TypeofState typeof_state,
91959151504615d929945dc59db37bf1166937748c6Steve Block    Label* slow) {
92059151504615d929945dc59db37bf1166937748c6Steve Block  Register context = esi;
92159151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = edx;
92259151504615d929945dc59db37bf1166937748c6Steve Block
92359151504615d929945dc59db37bf1166937748c6Steve Block  Scope* s = scope();
92459151504615d929945dc59db37bf1166937748c6Steve Block  while (s != NULL) {
92559151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
92659151504615d929945dc59db37bf1166937748c6Steve Block      if (s->calls_eval()) {
92759151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
92859151504615d929945dc59db37bf1166937748c6Steve Block        __ cmp(ContextOperand(context, Context::EXTENSION_INDEX),
92959151504615d929945dc59db37bf1166937748c6Steve Block               Immediate(0));
93059151504615d929945dc59db37bf1166937748c6Steve Block        __ j(not_equal, slow);
93159151504615d929945dc59db37bf1166937748c6Steve Block      }
93259151504615d929945dc59db37bf1166937748c6Steve Block      // Load next context in chain.
93359151504615d929945dc59db37bf1166937748c6Steve Block      __ mov(temp, ContextOperand(context, Context::CLOSURE_INDEX));
93459151504615d929945dc59db37bf1166937748c6Steve Block      __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset));
93559151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering esi.
93659151504615d929945dc59db37bf1166937748c6Steve Block      context = temp;
93759151504615d929945dc59db37bf1166937748c6Steve Block    }
93859151504615d929945dc59db37bf1166937748c6Steve Block    // If no outer scope calls eval, we do not need to check more
93959151504615d929945dc59db37bf1166937748c6Steve Block    // context extensions.  If we have reached an eval scope, we check
94059151504615d929945dc59db37bf1166937748c6Steve Block    // all extensions from this point.
94159151504615d929945dc59db37bf1166937748c6Steve Block    if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break;
94259151504615d929945dc59db37bf1166937748c6Steve Block    s = s->outer_scope();
94359151504615d929945dc59db37bf1166937748c6Steve Block  }
94459151504615d929945dc59db37bf1166937748c6Steve Block
94559151504615d929945dc59db37bf1166937748c6Steve Block  if (s != NULL && s->is_eval_scope()) {
94659151504615d929945dc59db37bf1166937748c6Steve Block    // Loop up the context chain.  There is no frame effect so it is
94759151504615d929945dc59db37bf1166937748c6Steve Block    // safe to use raw labels here.
9480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    NearLabel next, fast;
94959151504615d929945dc59db37bf1166937748c6Steve Block    if (!context.is(temp)) {
95059151504615d929945dc59db37bf1166937748c6Steve Block      __ mov(temp, context);
95159151504615d929945dc59db37bf1166937748c6Steve Block    }
95259151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&next);
95359151504615d929945dc59db37bf1166937748c6Steve Block    // Terminate at global context.
95459151504615d929945dc59db37bf1166937748c6Steve Block    __ cmp(FieldOperand(temp, HeapObject::kMapOffset),
95559151504615d929945dc59db37bf1166937748c6Steve Block           Immediate(Factory::global_context_map()));
95659151504615d929945dc59db37bf1166937748c6Steve Block    __ j(equal, &fast);
95759151504615d929945dc59db37bf1166937748c6Steve Block    // Check that extension is NULL.
95859151504615d929945dc59db37bf1166937748c6Steve Block    __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
95959151504615d929945dc59db37bf1166937748c6Steve Block    __ j(not_equal, slow);
96059151504615d929945dc59db37bf1166937748c6Steve Block    // Load next context in chain.
96159151504615d929945dc59db37bf1166937748c6Steve Block    __ mov(temp, ContextOperand(temp, Context::CLOSURE_INDEX));
96259151504615d929945dc59db37bf1166937748c6Steve Block    __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset));
96359151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(&next);
96459151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&fast);
96559151504615d929945dc59db37bf1166937748c6Steve Block  }
96659151504615d929945dc59db37bf1166937748c6Steve Block
96759151504615d929945dc59db37bf1166937748c6Steve Block  // All extension objects were empty and it is safe to use a global
96859151504615d929945dc59db37bf1166937748c6Steve Block  // load IC call.
9698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(eax, GlobalObjectOperand());
97059151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(ecx, slot->var()->name());
97159151504615d929945dc59db37bf1166937748c6Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
97259151504615d929945dc59db37bf1166937748c6Steve Block  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
97359151504615d929945dc59db37bf1166937748c6Steve Block      ? RelocInfo::CODE_TARGET
97459151504615d929945dc59db37bf1166937748c6Steve Block      : RelocInfo::CODE_TARGET_CONTEXT;
9750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, mode);
97659151504615d929945dc59db37bf1166937748c6Steve Block}
97759151504615d929945dc59db37bf1166937748c6Steve Block
97859151504615d929945dc59db37bf1166937748c6Steve Block
97959151504615d929945dc59db37bf1166937748c6Steve BlockMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
98059151504615d929945dc59db37bf1166937748c6Steve Block    Slot* slot,
98159151504615d929945dc59db37bf1166937748c6Steve Block    Label* slow) {
98259151504615d929945dc59db37bf1166937748c6Steve Block  ASSERT(slot->type() == Slot::CONTEXT);
98359151504615d929945dc59db37bf1166937748c6Steve Block  Register context = esi;
98459151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = ebx;
98559151504615d929945dc59db37bf1166937748c6Steve Block
98659151504615d929945dc59db37bf1166937748c6Steve Block  for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
98759151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
98859151504615d929945dc59db37bf1166937748c6Steve Block      if (s->calls_eval()) {
98959151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
99059151504615d929945dc59db37bf1166937748c6Steve Block        __ cmp(ContextOperand(context, Context::EXTENSION_INDEX),
99159151504615d929945dc59db37bf1166937748c6Steve Block               Immediate(0));
99259151504615d929945dc59db37bf1166937748c6Steve Block        __ j(not_equal, slow);
99359151504615d929945dc59db37bf1166937748c6Steve Block      }
99459151504615d929945dc59db37bf1166937748c6Steve Block      __ mov(temp, ContextOperand(context, Context::CLOSURE_INDEX));
99559151504615d929945dc59db37bf1166937748c6Steve Block      __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset));
99659151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering esi.
99759151504615d929945dc59db37bf1166937748c6Steve Block      context = temp;
99859151504615d929945dc59db37bf1166937748c6Steve Block    }
99959151504615d929945dc59db37bf1166937748c6Steve Block  }
100059151504615d929945dc59db37bf1166937748c6Steve Block  // Check that last extension is NULL.
100159151504615d929945dc59db37bf1166937748c6Steve Block  __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
100259151504615d929945dc59db37bf1166937748c6Steve Block  __ j(not_equal, slow);
100359151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(temp, ContextOperand(context, Context::FCONTEXT_INDEX));
100459151504615d929945dc59db37bf1166937748c6Steve Block  return ContextOperand(temp, slot->index());
100559151504615d929945dc59db37bf1166937748c6Steve Block}
100659151504615d929945dc59db37bf1166937748c6Steve Block
100759151504615d929945dc59db37bf1166937748c6Steve Block
100859151504615d929945dc59db37bf1166937748c6Steve Blockvoid FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
100959151504615d929945dc59db37bf1166937748c6Steve Block    Slot* slot,
101059151504615d929945dc59db37bf1166937748c6Steve Block    TypeofState typeof_state,
101159151504615d929945dc59db37bf1166937748c6Steve Block    Label* slow,
101259151504615d929945dc59db37bf1166937748c6Steve Block    Label* done) {
101359151504615d929945dc59db37bf1166937748c6Steve Block  // Generate fast-case code for variables that might be shadowed by
101459151504615d929945dc59db37bf1166937748c6Steve Block  // eval-introduced variables.  Eval is used a lot without
101559151504615d929945dc59db37bf1166937748c6Steve Block  // introducing variables.  In those cases, we do not want to
101659151504615d929945dc59db37bf1166937748c6Steve Block  // perform a runtime call for all variables in the scope
101759151504615d929945dc59db37bf1166937748c6Steve Block  // containing the eval.
101859151504615d929945dc59db37bf1166937748c6Steve Block  if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
101959151504615d929945dc59db37bf1166937748c6Steve Block    EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow);
102059151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(done);
102159151504615d929945dc59db37bf1166937748c6Steve Block  } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
10220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot();
102359151504615d929945dc59db37bf1166937748c6Steve Block    Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
102459151504615d929945dc59db37bf1166937748c6Steve Block    if (potential_slot != NULL) {
102559151504615d929945dc59db37bf1166937748c6Steve Block      // Generate fast case for locals that rewrite to slots.
102659151504615d929945dc59db37bf1166937748c6Steve Block      __ mov(eax,
102759151504615d929945dc59db37bf1166937748c6Steve Block             ContextSlotOperandCheckExtensions(potential_slot, slow));
102859151504615d929945dc59db37bf1166937748c6Steve Block      if (potential_slot->var()->mode() == Variable::CONST) {
102959151504615d929945dc59db37bf1166937748c6Steve Block        __ cmp(eax, Factory::the_hole_value());
103059151504615d929945dc59db37bf1166937748c6Steve Block        __ j(not_equal, done);
103159151504615d929945dc59db37bf1166937748c6Steve Block        __ mov(eax, Factory::undefined_value());
103259151504615d929945dc59db37bf1166937748c6Steve Block      }
103359151504615d929945dc59db37bf1166937748c6Steve Block      __ jmp(done);
103459151504615d929945dc59db37bf1166937748c6Steve Block    } else if (rewrite != NULL) {
103559151504615d929945dc59db37bf1166937748c6Steve Block      // Generate fast case for calls of an argument function.
103659151504615d929945dc59db37bf1166937748c6Steve Block      Property* property = rewrite->AsProperty();
103759151504615d929945dc59db37bf1166937748c6Steve Block      if (property != NULL) {
103859151504615d929945dc59db37bf1166937748c6Steve Block        VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
103959151504615d929945dc59db37bf1166937748c6Steve Block        Literal* key_literal = property->key()->AsLiteral();
104059151504615d929945dc59db37bf1166937748c6Steve Block        if (obj_proxy != NULL &&
104159151504615d929945dc59db37bf1166937748c6Steve Block            key_literal != NULL &&
104259151504615d929945dc59db37bf1166937748c6Steve Block            obj_proxy->IsArguments() &&
104359151504615d929945dc59db37bf1166937748c6Steve Block            key_literal->handle()->IsSmi()) {
104459151504615d929945dc59db37bf1166937748c6Steve Block          // Load arguments object if there are no eval-introduced
104559151504615d929945dc59db37bf1166937748c6Steve Block          // variables. Then load the argument from the arguments
104659151504615d929945dc59db37bf1166937748c6Steve Block          // object using keyed load.
104759151504615d929945dc59db37bf1166937748c6Steve Block          __ mov(edx,
10480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
104959151504615d929945dc59db37bf1166937748c6Steve Block                                                   slow));
105059151504615d929945dc59db37bf1166937748c6Steve Block          __ mov(eax, Immediate(key_literal->handle()));
105159151504615d929945dc59db37bf1166937748c6Steve Block          Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
10520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitCallIC(ic, RelocInfo::CODE_TARGET);
105359151504615d929945dc59db37bf1166937748c6Steve Block          __ jmp(done);
105459151504615d929945dc59db37bf1166937748c6Steve Block        }
105559151504615d929945dc59db37bf1166937748c6Steve Block      }
105659151504615d929945dc59db37bf1166937748c6Steve Block    }
105759151504615d929945dc59db37bf1166937748c6Steve Block  }
105859151504615d929945dc59db37bf1166937748c6Steve Block}
105959151504615d929945dc59db37bf1166937748c6Steve Block
106059151504615d929945dc59db37bf1166937748c6Steve Block
10610d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EmitVariableLoad(Variable* var) {
1062d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Four cases: non-this global variables, lookup slots, all other
1063d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // types of slots, and parameters that rewrite to explicit property
1064d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // accesses on the arguments object.
10650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Slot* slot = var->AsSlot();
1066d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Property* property = var->AsProperty();
1067d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1068d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (var->is_global() && !var->is_this()) {
10693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Comment cmnt(masm_, "Global variable");
10703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Use inline caching. Variable name is passed in ecx and the global
10713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // object on the stack.
10728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ mov(eax, GlobalObjectOperand());
1073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ mov(ecx, var->name());
10743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
10750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
10760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
1077d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1078d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
107959151504615d929945dc59db37bf1166937748c6Steve Block    Label done, slow;
108059151504615d929945dc59db37bf1166937748c6Steve Block
108159151504615d929945dc59db37bf1166937748c6Steve Block    // Generate code for loading from variables potentially shadowed
108259151504615d929945dc59db37bf1166937748c6Steve Block    // by eval-introduced variables.
108359151504615d929945dc59db37bf1166937748c6Steve Block    EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
108459151504615d929945dc59db37bf1166937748c6Steve Block
108559151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
1086d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Lookup slot");
1087d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ push(esi);  // Context.
1088d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ push(Immediate(var->name()));
1089d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
109059151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&done);
109159151504615d929945dc59db37bf1166937748c6Steve Block
10920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
1093d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1094d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL) {
1095d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1096d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            ? "Context slot"
1097d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            : "Stack slot");
1098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (var->mode() == Variable::CONST) {
1099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Constants may be the hole value if they have not been initialized.
1100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Unhole them.
11010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      NearLabel done;
1102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      MemOperand slot_operand = EmitSlotSearch(slot, eax);
1103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(eax, slot_operand);
1104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ cmp(eax, Factory::the_hole_value());
1105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ j(not_equal, &done);
1106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(eax, Factory::undefined_value());
1107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ bind(&done);
11080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(eax);
1109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
11100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(slot);
1111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1112d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1113d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1114d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Rewritten parameter");
1115d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(property);
1116d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Rewritten parameter accesses are of the form "slot[literal]".
1117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1118e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the object is in a slot.
1119d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1120d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(object_var);
11210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* object_slot = object_var->AsSlot();
1122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(object_slot);
1123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the object.
1125e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    MemOperand object_loc = EmitSlotSearch(object_slot, eax);
1126402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(edx, object_loc);
1127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1128e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the key is a smi.
1129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key_literal = property->key()->AsLiteral();
1130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(key_literal);
1131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(key_literal->handle()->IsSmi());
1132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the key.
1134402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(eax, Immediate(key_literal->handle()));
1135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1136e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Do a keyed property load.
1137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
11380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET);
11390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
1140e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Drop key and object left on the stack by IC.
11410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
11423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1146d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ RegExpLiteral");
11480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel materialized;
11493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Registers will be used as follows:
11503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // edi = JS function.
1151bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // ecx = literals array.
1152bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // ebx = regexp literal.
1153bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // eax = regexp literal clone.
11543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1155bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset));
11563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int literal_offset =
115780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1158bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(ebx, FieldOperand(ecx, literal_offset));
1159bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(ebx, Factory::undefined_value());
1160bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(not_equal, &materialized);
1161bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
11623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Create regexp literal using runtime function
11633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Result will be in eax.
1164bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(ecx);
11653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(Smi::FromInt(expr->literal_index())));
11663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(expr->pattern()));
11673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(expr->flags()));
11683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1169bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(ebx, eax);
1170bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1171bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&materialized);
1172bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1173bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label allocated, runtime_allocate;
1174bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
1175bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ jmp(&allocated);
1176bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1177bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&runtime_allocate);
1178bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(ebx);
1179bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(Immediate(Smi::FromInt(size)));
1180bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1181bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(ebx);
1182bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1183bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&allocated);
1184bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Copy the content into the newly allocated memory.
1185bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // (Unroll copy loop once for better throughput).
1186bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
1187bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(edx, FieldOperand(ebx, i));
1188bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(ecx, FieldOperand(ebx, i + kPointerSize));
1189bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(FieldOperand(eax, i), edx);
1190bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(FieldOperand(eax, i + kPointerSize), ecx);
1191bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1192bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if ((size % (2 * kPointerSize)) != 0) {
1193bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(edx, FieldOperand(ebx, size - kPointerSize));
1194bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(FieldOperand(eax, size - kPointerSize), edx);
1195bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
11960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1200d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
1202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(edi, JSFunction::kLiteralsOffset));
1204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ push(Immediate(Smi::FromInt(expr->literal_index())));
1205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ push(Immediate(expr->constant_properties()));
12066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(Immediate(Smi::FromInt(expr->fast_elements() ? 1 : 0)));
1207e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->depth() > 1) {
12086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
12093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
12106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
1211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1213e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
1214e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in eax.
1215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
1216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
12173e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Mark all computed expressions that are bound to a key that
12183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // is shadowed by a later occurrence of the same key. For the
12193e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // marked expressions, no store code is emitted.
12203e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  expr->CalculateEmitStore();
12213e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
1222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < expr->properties()->length(); i++) {
1223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectLiteral::Property* property = expr->properties()->at(i);
1224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
1225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = property->key();
1227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
1228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
1229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ push(eax);  // Save result on the stack
1230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
1231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
1233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
1237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (key->handle()->IsSymbol()) {
12380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForAccumulatorValue(value);
1239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ mov(ecx, Immediate(key->handle()));
12404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ mov(edx, Operand(esp, 0));
12413e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          if (property->emit_store()) {
12423e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu            Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
12433e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu            EmitCallIC(ic, RelocInfo::CODE_TARGET);
12443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          }
1245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::PROTOTYPE:
1249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(esp, 0));  // Duplicate receiver.
12500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(key);
12510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(value);
12523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        if (property->emit_store()) {
12533e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          __ CallRuntime(Runtime::kSetProperty, 3);
12543e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        } else {
12553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          __ Drop(3);
12563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        }
1257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::SETTER:
1259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::GETTER:
1260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(esp, 0));  // Duplicate receiver.
12610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(key);
1262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ?
1263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                          Smi::FromInt(1) :
1264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                          Smi::FromInt(0)));
12650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(value);
1266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDefineAccessor, 4);
1267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      default: UNREACHABLE();
1269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
12730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
12750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
12763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
12783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1280d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
12813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
1282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<Expression*>* subexprs = expr->values();
1284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int length = subexprs->length();
1285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
12863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
12883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(Smi::FromInt(expr->literal_index())));
1289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(Immediate(expr->constant_elements()));
1290756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) {
1291756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    FastCloneShallowArrayStub stub(
1292756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
1293756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
1294756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1);
1295756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (expr->depth() > 1) {
1296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
1297756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
1298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
1299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1300756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    FastCloneShallowArrayStub stub(
1301756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        FastCloneShallowArrayStub::CLONE_ELEMENTS, length);
1302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
13033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
13063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
13083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
1309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < length; i++) {
13103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Expression* subexpr = subexprs->at(i);
13113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
13123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
13133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (subexpr->AsLiteral() != NULL ||
13143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        CompileTimeValue::IsCompileTimeValue(subexpr)) {
13153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      continue;
13163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
13173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
13193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(eax);
13203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
13213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
13220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(subexpr);
13233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Store the subexpression value in the array's elements.
13253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(ebx, Operand(esp, 0));  // Copy of array literal.
13263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
13273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ mov(FieldOperand(ebx, offset), result_register());
13293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Update the write barrier for the array store.
1331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ RecordWrite(ebx, offset, result_register(), ecx);
13323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
13350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
13370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
13383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
13403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1342402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1343402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Comment cmnt(masm_, "[ Assignment");
1344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // on the left-hand side.
1346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->target()->IsValidLeftHandSide()) {
1347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->target());
1348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1351402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Left-hand side can only be a property, a global or a (parameter or local)
1352402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1353402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1354402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LhsKind assign_type = VARIABLE;
135580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Property* property = expr->target()->AsProperty();
135680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (property != NULL) {
135780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    assign_type = (property->key()->IsPropertyName())
135880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? NAMED_PROPERTY
135980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : KEYED_PROPERTY;
1360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate LHS expression.
1363402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1364402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Nothing to do here.
1366402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1367402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1368402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // We need the receiver both on the stack and in the accumulator.
13700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(property->obj());
1371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1372402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
13730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
1374402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1375402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1376402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1377402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
13780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
13790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(property->key());
1380402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ mov(edx, Operand(esp, 0));
1381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(eax);
1382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
13830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
13840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->key());
1385402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1386402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1387402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1388402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1389402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
13900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    { AccumulatorValueContext context(this);
13910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
13920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
13930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitVariableLoad(expr->target()->AsVariableProxy()->var());
13940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
13950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
13960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitNamedPropertyLoad(property);
13970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
13980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
13990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitKeyedPropertyLoad(property);
14000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
14010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
1402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1403402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
140480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Token::Value op = expr->binary_op();
140580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ConstantOperand constant = ShouldInlineSmiCase(op)
140680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? GetConstantOperand(op, expr->target(), expr->value())
140780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : kNoConstants;
140880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ASSERT(constant == kRightConstant || constant == kNoConstants);
140980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (constant == kNoConstants) {
141080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ push(eax);  // Left operand goes on the stack.
14110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->value());
141280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
1413402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
141480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
141580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? OVERWRITE_RIGHT
141680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : NO_OVERWRITE;
141780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    SetSourcePosition(expr->position() + 1);
14180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
141980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (ShouldInlineSmiCase(op)) {
142080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      EmitInlineSmiBinaryOp(expr,
142180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            op,
142280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            mode,
142380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            expr->target(),
142480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            expr->value(),
142580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            constant);
142680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    } else {
14270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitBinaryOp(op, mode);
142880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
142980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
14300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->value());
1431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1433402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Record source position before possible IC call.
1434402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  SetSourcePosition(expr->position());
1435402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1436402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Store the value.
1437402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1438402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
14400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             expr->op());
1441402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1442402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1443402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitNamedPropertyAssignment(expr);
1444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitKeyedPropertyAssignment(expr);
1447402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1451402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1452d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Literal* key = prop->key()->AsLiteral();
1455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(ecx, Immediate(key->handle()));
1456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
14570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1461d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
14640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
146880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitConstantSmiAdd(Expression* expr,
146980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                           OverwriteMode mode,
147080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                           bool left_is_constant_smi,
147180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                           Smi* value) {
14720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel call_stub;
14730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label done;
147480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ add(Operand(eax), Immediate(value));
147580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(overflow, &call_stub);
147680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ test(eax, Immediate(kSmiTagMask));
147780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(zero, &done);
147880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
147980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Undo the optimistic add operation and call the shared stub.
148080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&call_stub);
148180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ sub(Operand(eax), Immediate(value));
148280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Token::Value op = Token::ADD;
148380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown());
148480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (left_is_constant_smi) {
148580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(Immediate(value));
148680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(eax);
148780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
148880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(eax);
148980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(Immediate(value));
149080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
149180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ CallStub(&stub);
149280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&done);
14930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
149480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
149580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
149680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
149780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitConstantSmiSub(Expression* expr,
149880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                           OverwriteMode mode,
149980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                           bool left_is_constant_smi,
150080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                           Smi* value) {
150180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label call_stub, done;
150280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (left_is_constant_smi) {
150380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(ecx, eax);
150480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(eax, Immediate(value));
150580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ sub(Operand(eax), ecx);
150680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
150780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ sub(Operand(eax), Immediate(value));
150880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
150980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(overflow, &call_stub);
151080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ test(eax, Immediate(kSmiTagMask));
151180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(zero, &done);
151280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
151380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&call_stub);
151480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (left_is_constant_smi)  {
151580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(Immediate(value));
151680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(ecx);
151780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
151880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Undo the optimistic sub operation.
151980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ add(Operand(eax), Immediate(value));
152080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
152180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(eax);
152280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(Immediate(value));
152380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
152480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
152580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Token::Value op = Token::SUB;
152680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown());
1527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
152880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&done);
15290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
153080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
153180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
153280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
153380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitConstantSmiShiftOp(Expression* expr,
153480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                               Token::Value op,
153580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                               OverwriteMode mode,
153680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                               Smi* value) {
153780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label call_stub, smi_case, done;
153880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int shift_value = value->value() & 0x1f;
153980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
154080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ test(eax, Immediate(kSmiTagMask));
154180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(zero, &smi_case);
154280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
154380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&call_stub);
154480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown());
154580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ push(eax);
154680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ push(Immediate(value));
154780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ CallStub(&stub);
154880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(&done);
154980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
155080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&smi_case);
155180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
155280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHL:
155380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      if (shift_value != 0) {
155480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ mov(edx, eax);
155580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        if (shift_value > 1) {
155680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          __ shl(edx, shift_value - 1);
155780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        }
155880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        // Convert int result to smi, checking that it is in int range.
155980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ASSERT(kSmiTagSize == 1);  // Adjust code if not the case.
156080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ add(edx, Operand(edx));
156180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ j(overflow, &call_stub);
156280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ mov(eax, edx);  // Put result back into eax.
156380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
156480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
156580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SAR:
156680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      if (shift_value != 0) {
156780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ sar(eax, shift_value);
156880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ and_(eax, ~kSmiTagMask);
156980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
157080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
157180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHR:
157280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      if (shift_value < 2) {
157380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ mov(edx, eax);
157480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ SmiUntag(edx);
157580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ shr(edx, shift_value);
157680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ test(edx, Immediate(0xc0000000));
157780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ j(not_zero, &call_stub);
157880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ SmiTag(edx);
157980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ mov(eax, edx);  // Put result back into eax.
158080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      } else {
158180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ SmiUntag(eax);
158280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ shr(eax, shift_value);
158380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ SmiTag(eax);
158480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
158580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
158680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    default:
158780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      UNREACHABLE();
158880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
158980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
159080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&done);
15910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
159280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
159380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
159480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
159580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitConstantSmiBitOp(Expression* expr,
159680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                             Token::Value op,
159780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                             OverwriteMode mode,
159880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                             Smi* value) {
159980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label smi_case, done;
160080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ test(eax, Immediate(kSmiTagMask));
160180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(zero, &smi_case);
160280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
160380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown());
160480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The order of the arguments does not matter for bit-ops with a
160580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // constant operand.
160680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ push(Immediate(value));
160780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ push(eax);
160880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ CallStub(&stub);
160980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(&done);
161080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
161180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&smi_case);
161280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
161380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_OR:
161480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ or_(Operand(eax), Immediate(value));
161580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
161680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_XOR:
161780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ xor_(Operand(eax), Immediate(value));
161880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
161980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_AND:
162080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ and_(Operand(eax), Immediate(value));
162180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
162280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    default:
162380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      UNREACHABLE();
162480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
162580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
162680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&done);
16270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
162880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
162980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
163080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
163180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitConstantSmiBinaryOp(Expression* expr,
163280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                Token::Value op,
163380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                OverwriteMode mode,
163480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                bool left_is_constant_smi,
163580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                Smi* value) {
163680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
163780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_OR:
163880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_XOR:
163980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_AND:
16400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitConstantSmiBitOp(expr, op, mode, value);
164180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
164280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHL:
164380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SAR:
164480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHR:
164580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      ASSERT(!left_is_constant_smi);
16460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitConstantSmiShiftOp(expr, op, mode, value);
164780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
164880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::ADD:
16490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitConstantSmiAdd(expr, mode, left_is_constant_smi, value);
165080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
165180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SUB:
16520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitConstantSmiSub(expr, mode, left_is_constant_smi, value);
165380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
165480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    default:
165580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      UNREACHABLE();
165680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
165780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
165880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
165980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
166080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
166180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Token::Value op,
166280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              OverwriteMode mode,
166380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Expression* left,
166480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Expression* right,
166580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              ConstantOperand constant) {
166680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (constant == kRightConstant) {
166780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Smi* value =  Smi::cast(*right->AsLiteral()->handle());
16680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitConstantSmiBinaryOp(expr, op, mode, false, value);
166980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return;
167080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (constant == kLeftConstant) {
167180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Smi* value =  Smi::cast(*left->AsLiteral()->handle());
16720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitConstantSmiBinaryOp(expr, op, mode, true, value);
167380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return;
167480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
167580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
167680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Do combined smi check of the operands. Left operand is on the
167780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // stack. Right operand is in eax.
167880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label done, stub_call, smi_case;
167980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ pop(edx);
168080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ mov(ecx, eax);
168180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ or_(eax, Operand(edx));
168280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ test(eax, Immediate(kSmiTagMask));
168380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(zero, &smi_case);
168480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
168580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&stub_call);
168680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown());
168780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (stub.ArgsInRegistersSupported()) {
168880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    stub.GenerateCall(masm_, edx, ecx);
168980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
169080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(edx);
169180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(ecx);
169280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CallStub(&stub);
169380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
169480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(&done);
169580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
169680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&smi_case);
169780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ mov(eax, edx);  // Copy left operand in case of a stub call.
169880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
169980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
170080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SAR:
170180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(eax);
170280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(ecx);
170380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ sar_cl(eax);  // No checks of result necessary
170480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiTag(eax);
170580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
170680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHL: {
170780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label result_ok;
170880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(eax);
170980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(ecx);
171080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ shl_cl(eax);
171180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // Check that the *signed* result fits in a smi.
171280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ cmp(eax, 0xc0000000);
171380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(positive, &result_ok);
171480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiTag(ecx);
171580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ jmp(&stub_call);
171680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&result_ok);
171780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiTag(eax);
171880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
171980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
172080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHR: {
172180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label result_ok;
172280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(eax);
172380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(ecx);
172480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ shr_cl(eax);
172580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ test(eax, Immediate(0xc0000000));
172680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(zero, &result_ok);
172780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiTag(ecx);
172880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ jmp(&stub_call);
172980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&result_ok);
173080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiTag(eax);
173180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
173280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
173380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::ADD:
173480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ add(eax, Operand(ecx));
173580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(overflow, &stub_call);
173680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
173780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SUB:
173880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ sub(eax, Operand(ecx));
173980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(overflow, &stub_call);
174080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
174180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::MUL: {
174280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(eax);
174380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ imul(eax, Operand(ecx));
174480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(overflow, &stub_call);
174580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ test(eax, Operand(eax));
174680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(not_zero, &done, taken);
174780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ mov(ebx, edx);
174880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ or_(ebx, Operand(ecx));
174980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(negative, &stub_call);
175080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
175180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
175280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_OR:
175380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ or_(eax, Operand(ecx));
175480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
175580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_AND:
175680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ and_(eax, Operand(ecx));
175780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
175880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_XOR:
175980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ xor_(eax, Operand(ecx));
176080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
176180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    default:
176280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      UNREACHABLE();
176380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
176480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
176580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&done);
17660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
176780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
176880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
176980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
177080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitBinaryOp(Token::Value op,
177180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                     OverwriteMode mode) {
177280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  TypeInfo type = TypeInfo::Unknown();
177380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS, type);
177480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (stub.ArgsInRegistersSupported()) {
177580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ pop(edx);
177680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    stub.GenerateCall(masm_, edx, eax);
177780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
177880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(result_register());
177980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CallStub(&stub);
178080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
17810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
1782e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1783e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitAssignment(Expression* expr) {
1786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw
1787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ReferenceError' on the left-hand side.
1788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->IsValidLeftHandSide()) {
1789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr);
1790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand side can only be a property, a global or a (parameter or local)
1794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  LhsKind assign_type = VARIABLE;
1797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = expr->AsProperty();
1798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (prop != NULL) {
1799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    assign_type = (prop->key()->IsPropertyName())
1800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ? NAMED_PROPERTY
1801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        : KEYED_PROPERTY;
1802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (assign_type) {
1805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case VARIABLE: {
1806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->AsVariableProxy()->var();
18070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EffectContext context(this);
18080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitVariableAssignment(var, Token::ASSIGN);
1809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case NAMED_PROPERTY: {
1812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(eax);  // Preserve value.
18130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
1814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(edx, eax);
1815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(eax);  // Restore value.
1816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(ecx, prop->key()->AsLiteral()->handle());
1817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
18180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
1819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case KEYED_PROPERTY: {
1822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(eax);  // Preserve value.
18230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(prop->obj());
18240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->key());
1825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(ecx, eax);
1826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(edx);
1827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(eax);  // Restore value.
1828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
18290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
1830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1836d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var,
18370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                               Token::Value op) {
1838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand sides that rewrite to explicit property accesses do not reach
1839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // here.
18403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(var != NULL);
18410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(var->is_global() || var->AsSlot() != NULL);
1842d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
18433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (var->is_global()) {
1844d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT(!var->is_this());
1845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Assignment to a global variable.  Use inline caching for the
1846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // assignment.  Right-hand-side value is passed in eax, variable name in
1847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // ecx, and the global object on the stack.
18483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(ecx, var->name());
18498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ mov(edx, GlobalObjectOperand());
18503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
18510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET);
1852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) {
1854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Perform the assignment for non-const variables and for initialization
1855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // of const variables.  Const assignments are simply skipped.
1856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Label done;
18570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* slot = var->AsSlot();
1858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
1859e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
1860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      case Slot::LOCAL:
1861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Detect const reinitialization by checking for the hole value.
1863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ mov(edx, Operand(ebp, SlotOffset(slot)));
1864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ cmp(edx, Factory::the_hole_value());
1865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ j(not_equal, &done);
1866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment.
1868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(Operand(ebp, SlotOffset(slot)), eax);
1869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT: {
1872e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        MemOperand target = EmitSlotSearch(slot, ecx);
1873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Detect const reinitialization by checking for the hole value.
1875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ mov(edx, target);
1876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ cmp(edx, Factory::the_hole_value());
1877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ j(not_equal, &done);
1878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment and issue the write barrier.
1880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(target, eax);
1881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The value of the assignment is in eax.  RecordWrite clobbers its
1882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // register arguments.
1883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(edx, eax);
1884d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
1885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ RecordWrite(ecx, offset, edx, ebx);
1886d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
18873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
1888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP:
1890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Call the runtime for the assignment.  The runtime will ignore
1891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // const reinitialization.
1892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(eax);  // Value.
1893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(esi);  // Context.
1894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(Immediate(var->name()));
1895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // The runtime will ignore const redeclaration.
1897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else {
1899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kStoreContextSlot, 3);
1900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
19023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&done);
19043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
19073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
19083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1910d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1911d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
1912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
1913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop != NULL);
1914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop->key()->AsLiteral() != NULL);
19153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1920e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1921e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(Operand(esp, kPointerSize));  // Receiver is now under value.
1922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1923e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(ecx, prop->key()->AsLiteral()->handle());
19294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (expr->ends_initialization_block()) {
19304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ mov(edx, Operand(esp, 0));
19314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
19324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ pop(edx);
19334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
1934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
19350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1939d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(eax);  // Result of assignment, saved even if not needed.
1940d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(esp, kPointerSize));  // Receiver is under value.
1941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1942d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(eax);
19430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->DropAndPlug(1, eax);
19444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
19450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
1946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1947d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1948d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1950d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
1952d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Receiver is now under the key and value.
1959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(esp, 2 * kPointerSize));
1960d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1961e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1962d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1963d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
19646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ pop(ecx);
19656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (expr->ends_initialization_block()) {
19666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ mov(edx, Operand(esp, 0));  // Leave receiver on the stack for later.
19676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
19686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ pop(edx);
19696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1970e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1971e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1972d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
19730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1974d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1975d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1976d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
19776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ pop(edx);
1978d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(eax);  // Result of assignment, saved even if not needed.
19796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ push(edx);
1980d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1981d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(eax);
1982d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1983d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
19840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
1985d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1986d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1987d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1988d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) {
1989d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Property");
1990d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* key = expr->key();
1991d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1992e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (key->IsPropertyName()) {
19930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->obj());
1994e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitNamedPropertyLoad(expr);
1995d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
19960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(expr->obj());
19970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->key());
1998402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop(edx);
1999e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitKeyedPropertyLoad(expr);
2000d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
20010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2002d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2003d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2004d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2005d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr,
2006e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       Handle<Object> name,
2007e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       RelocInfo::Mode mode) {
2008d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the IC.
2009d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
20103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
20113e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  { PreserveStatementPositionScope scope(masm()->positions_recorder());
20123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
20133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
20143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
20153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    __ Set(ecx, Immediate(name));
20163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source position of the IC call.
20183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  SetSourcePosition(expr->position(), FORCED_POSITION);
2019e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
20208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
20210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, mode);
2022d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Restore context register.
2023d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
20240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2025d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2026d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2027d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
20287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
20297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                            Expression* key,
20307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                            RelocInfo::Mode mode) {
20318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the key.
20328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForAccumulatorValue(key);
20338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Swap the name of the function and the receiver on the stack to follow
20358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // the calling convention for call ICs.
20368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ pop(ecx);
20378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(eax);
20388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(ecx);
20398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the arguments.
20417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
20427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  int arg_count = args->length();
20433e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  { PreserveStatementPositionScope scope(masm()->positions_recorder());
20443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
20453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
20463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
20477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
20487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Record source position of the IC call.
20493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  SetSourcePosition(expr->position(), FORCED_POSITION);
20507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
20518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
20528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize));  // Key.
20530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, mode);
20547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Restore context register.
20557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
20568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  context()->DropAndPlug(1, eax);  // Drop the key still on the stack.
20577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
20587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
20597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2060d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) {
2061d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the call stub.
2062d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2063d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
20643e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  { PreserveStatementPositionScope scope(masm()->positions_recorder());
20653e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
20663e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
20673e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2068d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2069d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
20703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  SetSourcePosition(expr->position(), FORCED_POSITION);
2071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
2073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ CallStub(&stub);
20743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore context register.
20753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
20760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->DropAndPlug(1, eax);
2077d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2078d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2079d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2080d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) {
2081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Call");
2082d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* fun = expr->expression();
2083d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Variable* var = fun->AsVariableProxy()->AsVariable();
2084d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2085d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (var != NULL && var->is_possibly_eval()) {
2086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // In a call to eval, we first call %ResolvePossiblyDirectEval to
2087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // resolve the function we need to call and the receiver of the
2088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // call.  Then we call the resolved function using the given
2089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // arguments.
2090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    ZoneList<Expression*>* args = expr->arguments();
2091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    int arg_count = args->length();
20923e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    { PreserveStatementPositionScope pos_scope(masm()->positions_recorder());
20933e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(fun);
20943e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Reserved receiver slot.
20953e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ push(Immediate(Factory::undefined_value()));
2096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Push the arguments.
20983e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      for (int i = 0; i < arg_count; i++) {
20993e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        VisitForStackValue(args->at(i));
21003e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      }
2101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Push copy of the function - found below the arguments.
21033e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ push(Operand(esp, (arg_count + 1) * kPointerSize));
2104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21053e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Push copy of the first argument or undefined if it doesn't exist.
21063e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      if (arg_count > 0) {
21073e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        __ push(Operand(esp, arg_count * kPointerSize));
21083e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      } else {
21093e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        __ push(Immediate(Factory::undefined_value()));
21103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      }
2111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Push the receiver of the enclosing function and do runtime call.
21133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
21143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
2115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21163e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // The runtime call returns a pair of values in eax (function) and
21173e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // edx (receiver). Touch up the stack with the right values.
21183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
21193e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
21203e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Record source position for debugger.
21223e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    SetSourcePosition(expr->position(), FORCED_POSITION);
2123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
2125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
2126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Restore context register.
2127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
21280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->DropAndPlug(1, eax);
2129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (var != NULL && !var->is_this() && var->is_global()) {
2130e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Push global object as receiver for the call IC.
21318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ push(GlobalObjectOperand());
2132e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
21330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (var != NULL && var->AsSlot() != NULL &&
21340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen             var->AsSlot()->type() == Slot::LOOKUP) {
213559151504615d929945dc59db37bf1166937748c6Steve Block    // Call to a lookup slot (dynamically introduced variable).
213659151504615d929945dc59db37bf1166937748c6Steve Block    Label slow, done;
213759151504615d929945dc59db37bf1166937748c6Steve Block
21383e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    { PreserveStatementPositionScope scope(masm()->positions_recorder());
21393e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Generate code for loading from variables potentially shadowed
21403e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // by eval-introduced variables.
21413e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      EmitDynamicLoadFromSlotFastCase(var->AsSlot(),
21423e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                                      NOT_INSIDE_TYPEOF,
21433e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                                      &slow,
21443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                                      &done);
21453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
214659151504615d929945dc59db37bf1166937748c6Steve Block
214759151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
214859151504615d929945dc59db37bf1166937748c6Steve Block    // Call the runtime to find the function to call (returned in eax)
214959151504615d929945dc59db37bf1166937748c6Steve Block    // and the object holding it (returned in edx).
2150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(context_register());
2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Immediate(var->name()));
2152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(eax);  // Function.
2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(edx);  // Receiver.
215559151504615d929945dc59db37bf1166937748c6Steve Block
215659151504615d929945dc59db37bf1166937748c6Steve Block    // If fast case code has been generated, emit code to push the
215759151504615d929945dc59db37bf1166937748c6Steve Block    // function and receiver and have the slow path jump around this
215859151504615d929945dc59db37bf1166937748c6Steve Block    // code.
215959151504615d929945dc59db37bf1166937748c6Steve Block    if (done.is_linked()) {
216059151504615d929945dc59db37bf1166937748c6Steve Block      Label call;
216159151504615d929945dc59db37bf1166937748c6Steve Block      __ jmp(&call);
216259151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&done);
216359151504615d929945dc59db37bf1166937748c6Steve Block      // Push function.
216459151504615d929945dc59db37bf1166937748c6Steve Block      __ push(eax);
216559151504615d929945dc59db37bf1166937748c6Steve Block      // Push global receiver.
21668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ mov(ebx, GlobalObjectOperand());
216759151504615d929945dc59db37bf1166937748c6Steve Block      __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
216859151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&call);
216959151504615d929945dc59db37bf1166937748c6Steve Block    }
217059151504615d929945dc59db37bf1166937748c6Steve Block
2171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitCallWithStub(expr);
2172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (fun->AsProperty() != NULL) {
2173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to an object property.
2174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Property* prop = fun->AsProperty();
2175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = prop->key()->AsLiteral();
2176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (key != NULL && key->handle()->IsSymbol()) {
2177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Call to a named property, use call IC.
21780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(prop->obj());
2179e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
2180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
21817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Call to a keyed property.
21827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // For a synthetic property use keyed load IC followed by function call,
21830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // for a regular property use keyed EmitCallIC.
21843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      { PreserveStatementPositionScope scope(masm()->positions_recorder());
21853e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        VisitForStackValue(prop->obj());
21863e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      }
2187402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (prop->is_synthetic()) {
21883e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        { PreserveStatementPositionScope scope(masm()->positions_recorder());
21893e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          VisitForAccumulatorValue(prop->key());
21903e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        }
21917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        // Record source code position for IC call.
21923e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        SetSourcePosition(prop->position(), FORCED_POSITION);
2193402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ pop(edx);  // We do not need to keep the receiver.
2194402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
21957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
21960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        EmitCallIC(ic, RelocInfo::CODE_TARGET);
2197402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // Push result (function).
2198402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(eax);
2199402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // Push Global receiver.
22008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ mov(ecx, GlobalObjectOperand());
2201e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset));
22027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        EmitCallWithStub(expr);
2203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
22047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
2205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
22073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to some other expression.  If the expression is an anonymous
2209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // function literal not called in a loop, mark it as one that should
2210d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // also use the full code generator.
2211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    FunctionLiteral* lit = fun->AsFunctionLiteral();
2212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (lit != NULL &&
2213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        lit->name()->Equals(Heap::empty_string()) &&
2214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        loop_depth() == 0) {
2215d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      lit->set_try_full_codegen(true);
2216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
22173e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    { PreserveStatementPositionScope scope(masm()->positions_recorder());
22183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(fun);
22193e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load global receiver object.
22218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ mov(ebx, GlobalObjectOperand());
2222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
2223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit function call.
2224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    EmitCallWithStub(expr);
22253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
22263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
22273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
22283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2229d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
2230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
2231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
2232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
2233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
2234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
223580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Push constructor on the stack.  If it's not a function it's used as
223680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
223780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ignored.
22380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->expression());
2239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
2241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
2243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
22440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
2245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
2248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
2249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
2250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
225180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load function and argument count into edi and eax.
2252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Set(eax, Immediate(arg_count));
225380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ mov(edi, Operand(esp, arg_count * kPointerSize));
2254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
2256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
22570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
2262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
22640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
226980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
22700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
22710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
227480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(zero, if_true, if_false, fall_through);
2275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
22760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
2281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
22830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
228880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
22890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
22900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask | 0x80000000));
229380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(zero, if_true, if_false, fall_through);
2294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
22950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
2300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
230780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
23080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
23090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, if_false);
2313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Factory::null_value());
2314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
2315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Undetectable objects behave like undefined when tested with typeof.
2317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset));
2318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(ecx, Immediate(1 << Map::kIsUndetectable));
2319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_zero, if_false);
2320f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset));
2321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, if_false);
2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(ecx, LAST_JS_OBJECT_TYPE);
232480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(below_equal, if_true, if_false, fall_through);
2325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
23313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(args->length() == 1);
23323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
23330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
23343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
23353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label materialize_true, materialize_false;
23363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_true = NULL;
23373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_false = NULL;
233880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
23390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
23400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
23413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
23423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ test(eax, Immediate(kSmiTagMask));
23433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ j(equal, if_false);
23443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ebx);
234580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(above_equal, if_true, if_false, fall_through);
23463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
23470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
23483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
23493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
23503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
2351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
2352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
235980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
23600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
23610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, if_false);
2365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
2367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(ebx, Immediate(1 << Map::kIsUndetectable));
236880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(not_zero, if_true, if_false, fall_through);
2369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2374756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2375756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    ZoneList<Expression*>* args) {
2376756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ASSERT(args->length() == 1);
2377756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
23780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2379756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2380756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label materialize_true, materialize_false;
2381756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_true = NULL;
2382756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_false = NULL;
238380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
23840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
23850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2386756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2387756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only
2388756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // used in a few functions in runtime.js which should not normally be hit by
2389756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // this compiler.
2390756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ jmp(if_false);
23910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2392756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2393756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2394756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
2396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
240380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, if_false);
2409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
241080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
2417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
242480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_false);
2430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
243180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
2438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2444f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
244580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_false);
2451f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx);
245280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
2460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
246580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the frame pointer for the calling frame.
2470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Skip the arguments adaptor frame if it exists.
2473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label check_frame_marker;
2474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(Operand(eax, StandardFrameConstants::kContextOffset),
2475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &check_frame_marker);
2477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(eax, StandardFrameConstants::kCallerFPOffset));
2478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check the marker in the calling frame.
2480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&check_frame_marker);
2481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset),
2482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
248380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
2490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the two objects into registers and perform the comparison.
24930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
24940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
2495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
249980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
25010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(ebx);
2504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Operand(ebx));
250580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ArgumentsAccessStub expects the key in edx and the formal
2515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // parameter count in eax.
25160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, eax);
2518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
2519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
25210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label exit;
2529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the number of formal parameters.
2530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Set(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
2531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the calling frame is an arguments adaptor frame.
2533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset),
2535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Arguments adaptor case: Read the arguments length from the
2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // adaptor frame.
2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (FLAG_debug_code) __ AbortIfNotSmi(eax);
25440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
2549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, null, function, non_function_constructor;
2551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, we return null.
2555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, &null);
2557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check that the object is a JS object but take special care of JS
2559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // functions to make sure they have 'Function' as their class.
2560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, eax);  // Map is now in eax.
2561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, &null);
2562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // As long as JS_FUNCTION_TYPE is the last instance type and it is
2564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
2565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // LAST_JS_OBJECT_TYPE.
2566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
2567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
25688defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ CmpInstanceType(eax, JS_FUNCTION_TYPE);
2569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &function);
2570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the constructor in the map is a function.
2572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, Map::kConstructorOffset));
2573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &non_function_constructor);
2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // eax now contains the constructor function. Grab the
2577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // instance class name from there.
2578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
2579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset));
2580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Functions have class 'Function'.
2583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&function);
2584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Factory::function_class_symbol());
2585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Objects with a non-function constructor have class 'Object'.
2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&non_function_constructor);
2589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Factory::Object_symbol());
2590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-JS objects have class null.
2593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&null);
2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Factory::null_value());
2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // All done.
2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
2604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Conditionally generate a log call.
2605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Args:
2606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   0 (literal string): The type of logging (corresponds to the flags).
2607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     This is used to determine whether or not to generate the log call.
2608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   1 (string): Format string.  Access the string at argument index 2
2609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     with '%2s' (see Logger::LogRuntime for all the formats).
2610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   2 (array): Arguments to the format string.
2611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 3);
2612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING
2613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
26140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(1));
26150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(2));
2616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLog, 2);
2617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif
2619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Finally, we're expected to leave a value on the top of the stack.
2620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Factory::undefined_value());
26210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
2626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2628f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label slow_allocate_heapnumber;
2629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label heapnumber_allocated;
2630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber);
2632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&heapnumber_allocated);
2633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&slow_allocate_heapnumber);
26353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Allocate a heap number.
26363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CallRuntime(Runtime::kNumberAlloc, 0);
2637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edi, eax);
2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&heapnumber_allocated);
2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ PrepareCallCFunction(0, ebx);
2642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallCFunction(ExternalReference::random_uint32_function(), 0);
2643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert 32 random bits in eax to 0.(32 random bits) in a double
2645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // by computing:
2646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
2647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // This is implemented on both SSE2 and FPU.
2648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (CpuFeatures::IsSupported(SSE2)) {
2649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CpuFeatures::Scope fscope(SSE2);
2650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(ebx, Immediate(0x49800000));  // 1.0 x 2^20 as single.
2651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movd(xmm1, Operand(ebx));
2652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movd(xmm0, Operand(eax));
2653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ cvtss2sd(xmm1, xmm1);
2654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ pxor(xmm0, xmm1);
2655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ subsd(xmm0, xmm1);
2656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0);
2657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
2658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0x4130000000000000 is 1.0 x 2^20 as a double.
2659f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(FieldOperand(edi, HeapNumber::kExponentOffset),
2660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke           Immediate(0x41300000));
2661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), eax);
2662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
2663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), Immediate(0));
2664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
2665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fsubp(1);
2666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fstp_d(FieldOperand(edi, HeapNumber::kValueOffset));
2667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, edi);
26690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2670f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
2674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SubStringStub stub;
2676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
26770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
26780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
26790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
2680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
26810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
2686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  RegExpExecStub stub;
2688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 4);
26890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
26900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
26910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
26920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(3));
2693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
26940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
2699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));  // Load the object.
2702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel done;
2704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi return the object.
2705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, &done);
2707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the object.
2708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_VALUE_TYPE, ebx);
2709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &done);
2710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, JSValue::kValueOffset));
2711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
27130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
2718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the runtime function.
2719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
27200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
27210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
2722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_pow, 2);
27230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
2728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));  // Load the object.
27310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));  // Load the value.
2732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(ebx);  // eax = value. ebx = object.
2733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel done;
2735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, return the value.
2736f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(ebx, Immediate(kSmiTagMask));
2737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, &done);
2738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the value.
2740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx);
2741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &done);
2742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Store the value.
2744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax);
2745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the write barrier.  Save the value as it will be
2746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // overwritten by the write barrier code and is needed afterward.
2747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, eax);
2748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ RecordWrite(ebx, JSValue::kValueOffset, edx, ecx);
2749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
27510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2752f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
2756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 1);
2757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
27590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  NumberToStringStub stub;
2762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
27630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
2768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
27737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharFromCodeGenerator generator(eax, ebx);
27747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
2775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
27787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
2779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
27810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(ebx);
2782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
27867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
27877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
27890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
27907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = ebx;
27927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = eax;
27937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch = ecx;
27947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = edx;
27957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
27977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
27997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
28007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
28017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharCodeAtGenerator generator(object,
28027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      index,
28037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      scratch,
28047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      result,
28057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
28067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
28077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &index_out_of_range,
28087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      STRING_INDEX_IS_NUMBER);
28097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
28107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
28117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
28137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
28147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // NaN.
28157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Set(result, Immediate(Factory::nan_value()));
28167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
28177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
2819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Move the undefined value into the result register, which will
28207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // trigger conversion.
28217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Set(result, Immediate(Factory::undefined_value()));
28227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
28237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
28257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
28267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
28280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
2829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
28337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
28347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
28360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
28377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = ebx;
28397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = eax;
28407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch1 = ecx;
28417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch2 = edx;
28427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = eax;
28437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
28457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
28477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
28487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
28497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharAtGenerator generator(object,
28507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  index,
28517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  scratch1,
28527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  scratch2,
28537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  result,
28547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
28557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
28567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &index_out_of_range,
28577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  STRING_INDEX_IS_NUMBER);
28587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
28597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
28607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
28627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
28637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the empty string.
28647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Set(result, Immediate(Factory::empty_string()));
28657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
28667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
28687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move smi zero into the result register, which will trigger
28697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // conversion.
28707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Set(result, Immediate(Smi::FromInt(0)));
28717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
28727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
28747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
28757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
28770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
28787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
28797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
2882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
28850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
2886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringAddStub stub(NO_STRING_ADD_FLAGS);
2888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
28890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
2894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
28970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
2898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringCompareStub stub;
2900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
29010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
2906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
2907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  TranscendentalCacheStub stub(TranscendentalCache::SIN);
2908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
29090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
29110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
2916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
2917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  TranscendentalCacheStub stub(TranscendentalCache::COS);
2918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
29190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
29210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
2926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the runtime function.
2927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
29280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_sqrt, 1);
29300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
2935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() >= 2);
2936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int arg_count = args->length() - 2;  // For receiver and function.
29380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));  // Receiver.
2939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < arg_count; i++) {
29400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i + 1));
2941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
29420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(arg_count + 1));  // Function.
2943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // InvokeFunction requires function in edi. Move it in there.
2945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!result_register().is(edi)) __ mov(edi, result_register());
2946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ParameterCount count(arg_count);
2947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeFunction(edi, count, CALL_FUNCTION);
2948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
29490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
2954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
29550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
29560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
29570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
2958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kRegExpConstructResult, 3);
29590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
2964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
29650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
29660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
29670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
2968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kSwapElements, 3);
29690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
2974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_NE(NULL, args->at(0)->AsLiteral());
2977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
2978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<FixedArray> jsfunction_result_caches(
2980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Top::global_context()->jsfunction_result_caches());
2981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (jsfunction_result_caches->length() <= cache_id) {
2982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Abort("Attempt to use undefined cache.");
2983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(eax, Factory::undefined_value());
29840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
2985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
2989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register key = eax;
2991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register cache = ebx;
2992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register tmp = ecx;
299359151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(cache, ContextOperand(esi, Context::GLOBAL_INDEX));
2994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(cache,
2995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         FieldOperand(cache, GlobalObject::kGlobalContextOffset));
299659151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
2997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(cache,
2998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
2999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, not_found;
3001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // tmp now holds finger offset as a smi.
3002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
3004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(key, CodeGenerator::FixedArrayElementOperand(cache, tmp));
3005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &not_found);
3006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, CodeGenerator::FixedArrayElementOperand(cache, tmp, 1));
3008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
3009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&not_found);
3011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call runtime to perform the lookup.
3012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(cache);
3013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(key);
3014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetFromCache, 2);
3015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
30170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3021bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
3022bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT_EQ(2, args->length());
3023bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3024bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register right = eax;
3025bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register left = ebx;
3026bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register tmp = ecx;
3027bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
30280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
30290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
3030bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(left);
3031bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3032bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label done, fail, ok;
3033bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(left, Operand(right));
3034bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(equal, &ok);
3035bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Fail if either is a non-HeapObject.
3036bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(tmp, left);
3037bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ and_(Operand(tmp), right);
3038bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ test(Operand(tmp), Immediate(kSmiTagMask));
3039bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(zero, &fail);
3040bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CmpObjectType(left, JS_REGEXP_TYPE, tmp);
3041bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(not_equal, &fail);
3042bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(tmp, FieldOperand(right, HeapObject::kMapOffset));
3043bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(not_equal, &fail);
3044bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset));
3045bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset));
3046bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(equal, &ok);
3047bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&fail);
3048bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(eax, Immediate(Factory::false_value()));
3049bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ jmp(&done);
3050bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&ok);
3051bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(eax, Immediate(Factory::true_value()));
3052bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&done);
3053bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
30540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3055bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
3056bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3057bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
305880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
305980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(args->length() == 1);
306080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
30610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
306280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
306380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (FLAG_debug_code) {
306480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ AbortIfNotString(eax);
306580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
306680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
306780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
306880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
306980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
307080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
30710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
30720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
307380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
307480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ test(FieldOperand(eax, String::kHashFieldOffset),
307580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Immediate(String::kContainsCachedArrayIndexMask));
307680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(zero, if_true, if_false, fall_through);
307780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
30780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
307980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
308080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
308180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
308280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
308380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(args->length() == 1);
308480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
30850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
308680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
308780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (FLAG_debug_code) {
308880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ AbortIfNotString(eax);
308980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
309080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
309180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
309280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ IndexFromHash(eax, eax);
309380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
30940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
309580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
309680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
309780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
30988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
30998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label bailout;
31008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label done;
31018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(args->length() == 2);
31038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // We will leave the separator on the stack until the end of the function.
31048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForStackValue(args->at(1));
31058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load this to eax (= array)
31068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForAccumulatorValue(args->at(0));
31078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // All aliases of the same register have disjoint lifetimes.
31098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register array = eax;
31108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register result_pos = no_reg;
31118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register index = edi;
31138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register current_string_length = ecx;  // Will be ecx when live.
31158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register current_string = edx;
31178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register scratch = ebx;
31198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register scratch_2 = esi;
31218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register new_padding_chars = scratch_2;
31228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Operand separator = Operand(esp, 4 * kPointerSize);  // Already pushed.
31248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Operand elements = Operand(esp, 3 * kPointerSize);
31258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Operand result = Operand(esp, 2 * kPointerSize);
31268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Operand padding_chars = Operand(esp, 1 * kPointerSize);
31278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Operand array_length = Operand(esp, 0);
31288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ sub(Operand(esp), Immediate(4 * kPointerSize));
31298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check that eax is a JSArray
31328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ test(array, Immediate(kSmiTagMask));
31338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(zero, &bailout);
31348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
31358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(not_equal, &bailout);
31368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check that the array has fast elements.
31388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ test_b(FieldOperand(scratch, Map::kBitField2Offset),
31398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang            1 << Map::kHasFastElements);
31408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(zero, &bailout);
31418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If the array is empty, return the empty string.
31438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(scratch, FieldOperand(array, JSArray::kLengthOffset));
31448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ sar(scratch, 1);
31458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label non_trivial;
31468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(not_zero, &non_trivial);
31478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(result, Factory::empty_string());
31488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ jmp(&done);
31498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&non_trivial);
31518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(array_length, scratch);
31528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(scratch, FieldOperand(array, JSArray::kElementsOffset));
31548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(elements, scratch);
31558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // End of array's live range.
31578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  result_pos = array;
31588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  array = no_reg;
31598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check that the separator is a flat ascii string.
31628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(current_string, separator);
31638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ test(current_string, Immediate(kSmiTagMask));
31648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(zero, &bailout);
31658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset));
31668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
31678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ and_(scratch, Immediate(
31688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
31698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
31708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(not_equal, &bailout);
31718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If the separator is the empty string, replace it with NULL.
31728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // The test for NULL is quicker than the empty string test, in a loop.
31738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ cmp(FieldOperand(current_string, SeqAsciiString::kLengthOffset),
31748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang         Immediate(0));
31758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label separator_checked;
31768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(not_zero, &separator_checked);
31778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(separator, Immediate(0));
31788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&separator_checked);
31798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check that elements[0] is a flat ascii string, and copy it in new space.
31818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(scratch, elements);
31828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(current_string, FieldOperand(scratch, FixedArray::kHeaderSize));
31838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ test(current_string, Immediate(kSmiTagMask));
31848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(zero, &bailout);
31858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset));
31868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
31878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ and_(scratch, Immediate(
31888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
31898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
31908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(not_equal, &bailout);
31918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Allocate space to copy it.  Round up the size to the alignment granularity.
31938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(current_string_length,
31948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang         FieldOperand(current_string, String::kLengthOffset));
31958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ shr(current_string_length, 1);
31968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
31978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Live registers and stack values:
31988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //   current_string_length: length of elements[0].
31998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // New string result in new space = elements[0]
32018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ AllocateAsciiString(result_pos, current_string_length, scratch_2,
32028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                         index, no_reg, &bailout);
32038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(result, result_pos);
32048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Adjust current_string_length to include padding bytes at end of string.
32068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Keep track of the number of padding bytes.
32078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(new_padding_chars, current_string_length);
32088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ add(Operand(current_string_length), Immediate(kObjectAlignmentMask));
32098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ and_(Operand(current_string_length), Immediate(~kObjectAlignmentMask));
32108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ sub(new_padding_chars, Operand(current_string_length));
32118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ neg(new_padding_chars);
32128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(padding_chars, new_padding_chars);
32138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label copy_loop_1_done;
32158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label copy_loop_1;
32168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ test(current_string_length, Operand(current_string_length));
32178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(zero, &copy_loop_1_done);
32188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&copy_loop_1);
32198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ sub(Operand(current_string_length), Immediate(kPointerSize));
32208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(scratch, FieldOperand(current_string, current_string_length,
32218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                               times_1, SeqAsciiString::kHeaderSize));
32228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(FieldOperand(result_pos, current_string_length,
32238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                      times_1, SeqAsciiString::kHeaderSize),
32248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang         scratch);
32258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(not_zero, &copy_loop_1);
32268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&copy_loop_1_done);
32278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(index, Immediate(1));
32298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Loop condition: while (index < length).
32308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label loop;
32318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&loop);
32328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ cmp(index, array_length);
32338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(greater_equal, &done);
32348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If the separator is the empty string, signalled by NULL, skip it.
32368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label separator_done;
32378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(current_string, separator);
32388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ test(current_string, Operand(current_string));
32398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(zero, &separator_done);
32408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Append separator to result.  It is known to be a flat ascii string.
32428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ AppendStringToTopOfNewSpace(current_string, current_string_length,
32438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                 result_pos, scratch, scratch_2, result,
32448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                 padding_chars, &bailout);
32458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&separator_done);
32468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Add next element of array to the end of the result.
32488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Get current_string = array[index].
32498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(scratch, elements);
32508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(current_string, FieldOperand(scratch, index,
32518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                      times_pointer_size,
32528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                      FixedArray::kHeaderSize));
32538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If current != flat ascii string drop result, return undefined.
32548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ test(current_string, Immediate(kSmiTagMask));
32558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(zero, &bailout);
32568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset));
32578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
32588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ and_(scratch, Immediate(
32598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
32608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
32618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(not_equal, &bailout);
32628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Append current to the result.
32648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ AppendStringToTopOfNewSpace(current_string, current_string_length,
32658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                 result_pos, scratch, scratch_2, result,
32668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                 padding_chars, &bailout);
32678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ add(Operand(index), Immediate(1));
32688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ jmp(&loop);  // End while (index < length).
32698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&bailout);
32718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(result, Factory::undefined_value());
32728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&done);
32738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(eax, result);
32748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Drop temp values from the stack, and restore context register.
32758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ add(Operand(esp), Immediate(5 * kPointerSize));
32768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
32788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  context()->Plug(eax);
32798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
32808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3282d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
3283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<String> name = expr->name();
3284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (name->length() > 0 && name->Get(0) == '_') {
3285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ InlineRuntimeCall");
3286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitInlineRuntimeCall(expr);
3287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ CallRuntime");
32913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* args = expr->arguments();
32923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
3294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Prepare for calling JS runtime function.
32958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ mov(eax, GlobalObjectOperand());
3296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
3297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
32983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
32993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Push the arguments ("left-to-right").
33003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
33013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
33020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
3303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
3306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Call the JS runtime function via a call IC.
3307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ Set(ecx, Immediate(expr->name()));
3308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
33098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
33100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET);
33110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Restore context register.
3312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
3314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call the C runtime function.
3315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(expr->function(), arg_count);
3316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
33170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3320d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3321d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3322d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
3323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Token::DELETE: {
3324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
3325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Property* prop = expr->expression()->AsProperty();
3326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
3327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (prop == NULL && var == NULL) {
3328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Result of deleting non-property, non-variable reference is true.
3329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The subexpression may have side effects.
3330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForEffect(expr->expression());
33310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(true);
3332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else if (var != NULL &&
3333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 !var->is_global() &&
33340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 var->AsSlot() != NULL &&
33350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 var->AsSlot()->type() != Slot::LOOKUP) {
3336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Result of deleting non-global, non-dynamic variables is false.
3337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The subexpression does not have side effects.
33380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(false);
3339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else {
3340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Property or variable reference.  Call the delete builtin with
3341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // object and property name as arguments.
3342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (prop != NULL) {
33430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForStackValue(prop->obj());
33440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForStackValue(prop->key());
3345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (var->is_global()) {
33468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang          __ push(GlobalObjectOperand());
3347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(Immediate(var->name()));
3348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else {
3349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Non-global variable.  Call the runtime to look up the context
3350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // where the variable was introduced.
3351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(context_register());
3352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(Immediate(var->name()));
3353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kLookupContext, 2);
3354f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(eax);
3355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(Immediate(var->name()));
3356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
3357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
33580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(eax);
3359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
3360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
3361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
3362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
3364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
3365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
33660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(Factory::undefined_value());
3367d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
33683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
3369d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3370d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
3371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
337280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label materialize_true, materialize_false;
3374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label* if_true = NULL;
3375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label* if_false = NULL;
337680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label* fall_through = NULL;
3377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Notice that the labels are swapped.
33780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->PrepareTest(&materialize_true, &materialize_false,
33790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             &if_false, &if_true, &fall_through);
338080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      VisitForControl(expr->expression(), if_true, if_false, fall_through);
33810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(if_false, if_true);  // Labels swapped.
3382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
3386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
33870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      { StackValueContext context(this);
33880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForTypeofValue(expr->expression());
33890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
3390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallRuntime(Runtime::kTypeof, 1);
33910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(eax);
3392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3395d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Token::ADD: {
3396d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Comment cmt(masm_, "[ UnaryOperation (ADD)");
33970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->expression());
3398d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Label no_conversion;
3399d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ test(result_register(), Immediate(kSmiTagMask));
3400d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ j(zero, &no_conversion);
3401d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ push(result_register());
3402d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
3403d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ bind(&no_conversion);
34040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(result_register());
3405d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      break;
3406d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3407d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
34084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::SUB: {
34094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (SUB)");
341080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
3411ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke      UnaryOverwriteMode overwrite =
3412ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke          can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
34130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      GenericUnaryOpStub stub(Token::SUB, overwrite, NO_UNARY_FLAGS);
34144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // GenericUnaryOpStub expects the argument to be in the
34154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // accumulator register eax.
34160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->expression());
34174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
34180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(eax);
34194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
34204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
34214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
34224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::BIT_NOT: {
34234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
342480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // The generic unary operation stub expects the argument to be
342580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // in the accumulator register eax.
34260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->expression());
342780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label done;
34280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      bool inline_smi_case = ShouldInlineSmiCase(expr->op());
34290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (inline_smi_case) {
34300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        NearLabel call_stub;
343180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ test(eax, Immediate(kSmiTagMask));
343280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ j(not_zero, &call_stub);
343380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ lea(eax, Operand(eax, kSmiTagMask));
343480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ not_(eax);
343580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ jmp(&done);
343680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&call_stub);
343780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
343880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      bool overwrite = expr->expression()->ResultOverwriteAllowed();
343980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      UnaryOverwriteMode mode =
344080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
34410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      UnaryOpFlags flags = inline_smi_case
34420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          ? NO_UNARY_SMI_CODE_IN_STUB
34430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          : NO_UNARY_FLAGS;
34440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      GenericUnaryOpStub stub(Token::BIT_NOT, mode, flags);
34454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
34464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ bind(&done);
34470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(eax);
34484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
34494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
34504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
3452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
34533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
3454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3457d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CountOperation");
345980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
346080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
3462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // as the left-hand side.
3463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->expression()->IsValidLeftHandSide()) {
3464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->expression());
3465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3468e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Expression can only be a property, a global or a (parameter or local)
3469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
3470e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
3471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LhsKind assign_type = VARIABLE;
3472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
3473e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In case of a property we use the uninitialized expression context
3474e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // of the key to detect a named property.
3475e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (prop != NULL) {
3476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    assign_type =
3477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
3478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
3481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
3482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
34830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
34840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitVariableLoad(expr->expression()->AsVariableProxy()->var());
3485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
3486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
34870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (expr->is_postfix() && !context()->IsEffect()) {
3488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ push(Immediate(Smi::FromInt(0)));
3489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (assign_type == NAMED_PROPERTY) {
3491402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Put the object both on the stack and in the accumulator.
34920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
3493402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ push(eax);
3494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitNamedPropertyLoad(prop);
3495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
34960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(prop->obj());
34970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->key());
3498402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ mov(edx, Operand(esp, 0));
3499402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ push(eax);
3500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitKeyedPropertyLoad(prop);
3501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3504d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Call ToNumber only if operand is not a smi.
35050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel no_conversion;
350680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (ShouldInlineSmiCase(expr->op())) {
350780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(eax, Immediate(kSmiTagMask));
350880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(zero, &no_conversion);
350980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
3510d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ push(eax);
3511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
3512d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&no_conversion);
35133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
3515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
35160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (!context()->IsEffect()) {
35170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Save the result on the stack. If we have a named or keyed property
35180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // we store the result under the receiver that is currently on top
35190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // of the stack.
35200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
35210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
35220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ push(eax);
35230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
35240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
35250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ mov(Operand(esp, kPointerSize), eax);
35260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
35270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
35280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ mov(Operand(esp, 2 * kPointerSize), eax);
35290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
35300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
3531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3532d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3534d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Inline smi case if we are in a loop.
35350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel stub_call;
35360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label done;
353780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (ShouldInlineSmiCase(expr->op())) {
3538d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
3539d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ add(Operand(eax), Immediate(Smi::FromInt(1)));
3540d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
3541d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
3542d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3543d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ j(overflow, &stub_call);
3544d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // We could eliminate this smi check if we split the code at
3545d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // the first smi check before calling ToNumber.
3546d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ test(eax, Immediate(kSmiTagMask));
3547d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ j(zero, &done);
3548d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ bind(&stub_call);
3549d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Call stub. Undo operation first.
3550d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
3551d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
3552d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
3553d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ add(Operand(eax), Immediate(Smi::FromInt(1)));
3554d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3555d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
3556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call stub for +1/-1.
3557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  GenericBinaryOpStub stub(expr->binary_op(),
3558e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_OVERWRITE,
35596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           NO_GENERIC_BINARY_FLAGS,
35606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           TypeInfo::Unknown());
3561d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  stub.GenerateCall(masm(), eax, Smi::FromInt(1));
3562d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
3563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in eax.
3565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
3566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case VARIABLE:
3567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
3568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
35690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        { EffectContext context(this);
35700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
35710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                 Token::ASSIGN);
35720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        }
35730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        // For all contexts except EffectContext We have the result on
3574e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
35750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
35760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
3579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
3580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
35810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                               Token::ASSIGN);
3582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3584e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
3585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(ecx, prop->key()->AsLiteral()->handle());
35864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ pop(edx);
3587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
35880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
3589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
35900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
35910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
35940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(eax);
3595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3596d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
35996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ pop(ecx);
36006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ pop(edx);
3601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
36020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
3603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
36046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // Result is on the stack
36050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
36060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
36090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(eax);
3610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
36133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
36143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
36153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
36163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
36170d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
361880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  VariableProxy* proxy = expr->AsVariableProxy();
36190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!context()->IsEffect());
36200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!context()->IsTest());
36210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
362280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
362380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Comment cmnt(masm_, "Global variable");
36248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ mov(eax, GlobalObjectOperand());
362580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(ecx, Immediate(proxy->name()));
362680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
362780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Use a regular load, not a contextual load, to avoid a reference
362880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // error.
36290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET);
36300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
363180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (proxy != NULL &&
36320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen             proxy->var()->AsSlot() != NULL &&
36330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen             proxy->var()->AsSlot()->type() == Slot::LOOKUP) {
363459151504615d929945dc59db37bf1166937748c6Steve Block    Label done, slow;
363559151504615d929945dc59db37bf1166937748c6Steve Block
363659151504615d929945dc59db37bf1166937748c6Steve Block    // Generate code for loading from variables potentially shadowed
363759151504615d929945dc59db37bf1166937748c6Steve Block    // by eval-introduced variables.
36380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* slot = proxy->var()->AsSlot();
363959151504615d929945dc59db37bf1166937748c6Steve Block    EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
364059151504615d929945dc59db37bf1166937748c6Steve Block
364159151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
364280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(esi);
364380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(Immediate(proxy->name()));
364480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
364559151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&done);
364659151504615d929945dc59db37bf1166937748c6Steve Block
36470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
364880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
364980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // This expression cannot throw a reference error at the top level.
36500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Visit(expr);
3651d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
36533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
36543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
365580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenbool FullCodeGenerator::TryLiteralCompare(Token::Value op,
365680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Expression* left,
365780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Expression* right,
365880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Label* if_true,
365980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Label* if_false,
366080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Label* fall_through) {
366180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (op != Token::EQ && op != Token::EQ_STRICT) return false;
366280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
366380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check for the pattern: typeof <expression> == <string literal>.
366480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Literal* right_literal = right->AsLiteral();
366580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (right_literal == NULL) return false;
366680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Handle<Object> right_literal_value = right_literal->handle();
366780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (!right_literal_value->IsString()) return false;
366880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  UnaryOperation* left_unary = left->AsUnaryOperation();
366980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
367080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Handle<String> check = Handle<String>::cast(right_literal_value);
367180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
36720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  { AccumulatorValueContext context(this);
36730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForTypeofValue(left_unary->expression());
36740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
36750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
367680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (check->Equals(Heap::number_symbol())) {
367780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(eax, Immediate(kSmiTagMask));
367880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(zero, if_true);
367980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
368080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           Factory::heap_number_map());
368180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
368280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::string_symbol())) {
368380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(eax, Immediate(kSmiTagMask));
368480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(zero, if_false);
368580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
368680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
368780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
368880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(ecx, Immediate(1 << Map::kIsUndetectable));
368980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(not_zero, if_false);
369080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE);
369180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(below, if_true, if_false, fall_through);
369280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::boolean_symbol())) {
369380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(eax, Factory::true_value());
3694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
369580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(eax, Factory::false_value());
369680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
369780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::undefined_symbol())) {
369880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(eax, Factory::undefined_value());
3699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
370080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(eax, Immediate(kSmiTagMask));
370180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(zero, if_false);
370280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => true.
370380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
370480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
370580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(ecx, Immediate(1 << Map::kIsUndetectable));
370680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(not_zero, if_true, if_false, fall_through);
370780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::function_symbol())) {
370880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(eax, Immediate(kSmiTagMask));
370980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(zero, if_false);
371080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CmpObjectType(eax, JS_FUNCTION_TYPE, edx);
3711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
371280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Regular expressions => 'function' (they are callable).
371380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CmpInstanceType(edx, JS_REGEXP_TYPE);
371480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
371580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::object_symbol())) {
371680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(eax, Immediate(kSmiTagMask));
3717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(zero, if_false);
371880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(eax, Factory::null_value());
371980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_true);
372080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Regular expressions => 'function', not 'object'.
372180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CmpObjectType(eax, JS_REGEXP_TYPE, edx);
372280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_false);
372380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
372480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
372580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(ecx, Immediate(1 << Map::kIsUndetectable));
372680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(not_zero, if_false);
372780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for JS objects => true.
372880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset));
372980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
373080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(less, if_false);
373180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(ecx, LAST_JS_OBJECT_TYPE);
373280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(less_equal, if_true, if_false, fall_through);
373380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
373480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (if_false != fall_through) __ jmp(if_false);
3735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
373680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
373780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return true;
3738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3741d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
3742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
374380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
3744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
3746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
3747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
375180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
37520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
37530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
375480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
375580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // First we try a fast inlined version of the compare when one of
375680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the operands is a literal.
375780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Token::Value op = expr->op();
375880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Expression* left = expr->left();
375980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Expression* right = expr->right();
376080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) {
37610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(if_true, if_false);
376280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return;
376380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
3764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
37650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->left());
3766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
3767e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
37680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
3769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
3770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ cmp(eax, Factory::true_value());
377180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(equal, if_true, if_false, fall_through);
3772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
37733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
37750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
3776d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      InstanceofStub stub;
3777d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
3778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ test(eax, Operand(eax));
377980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // The stub returns 0 for true.
378080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(zero, if_true, if_false, fall_through);
3781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
37850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->right());
3786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Condition cc = no_condition;
3787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      bool strict = false;
378880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      switch (op) {
3789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::EQ_STRICT:
3790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          strict = true;
3791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Fall through
379280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        case Token::EQ:
3793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = equal;
3794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(edx);
3795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LT:
3797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
3798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(edx);
3799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GT:
3801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Reverse left and right sizes to obtain ECMA-262 conversion order.
3802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
3803e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(edx, result_register());
3804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(eax);
3805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block         break;
3806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LTE:
3807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Reverse left and right sizes to obtain ECMA-262 conversion order.
3808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
3809e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(edx, result_register());
3810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(eax);
3811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GTE:
3813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
3814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(edx);
3815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::IN:
3817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::INSTANCEOF:
3818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default:
3819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
3820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
3821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
38220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      bool inline_smi_code = ShouldInlineSmiCase(op);
38230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (inline_smi_code) {
38240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        NearLabel slow_case;
382580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ mov(ecx, Operand(edx));
382680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ or_(ecx, Operand(eax));
382780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ test(ecx, Immediate(kSmiTagMask));
382880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ j(not_zero, &slow_case, not_taken);
382980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ cmp(edx, Operand(eax));
383080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Split(cc, if_true, if_false, NULL);
383180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&slow_case);
383280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
3833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
38340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      CompareFlags flags = inline_smi_code
38350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          ? NO_SMI_COMPARE_IN_STUB
38360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          : NO_COMPARE_FLAGS;
38370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      CompareStub stub(cc, strict, flags);
3838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
3839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ test(eax, Operand(eax));
384080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(cc, if_true, if_false, fall_through);
3841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
38423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
38433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
3845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
38460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3847e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
385080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) {
385180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
385280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
385380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
385480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
38550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
38560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
385780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
38580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(expr->expression());
385980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ cmp(eax, Factory::null_value());
386080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (expr->is_strict()) {
386180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
386280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
386380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_true);
386480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(eax, Factory::undefined_value());
386580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_true);
386680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(eax, Immediate(kSmiTagMask));
386780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(zero, if_false);
386880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // It can be an undetectable object.
386980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
387080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movzx_b(edx, FieldOperand(edx, Map::kBitFieldOffset));
387180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(edx, Immediate(1 << Map::kIsUndetectable));
387280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(not_zero, if_true, if_false, fall_through);
387380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
38740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
387580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
387680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
387780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3878d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
3879e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
38800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
38810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
38820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
38830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
38840d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() {
38850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return eax;
3886e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
38890d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() {
38900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return esi;
38910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
3892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3893e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
38940d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) {
38950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(mode == RelocInfo::CODE_TARGET ||
38960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen         mode == RelocInfo::CODE_TARGET_CONTEXT);
38970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ call(ic, mode);
38980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
38990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // If we're calling a (keyed) load or store stub, we have to mark
39000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // the call as containing no inlined code so we will not attempt to
39010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // patch it.
39020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  switch (ic->kind()) {
39030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    case Code::LOAD_IC:
39040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    case Code::KEYED_LOAD_IC:
39050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    case Code::STORE_IC:
39060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    case Code::KEYED_STORE_IC:
39070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ nop();  // Signals no inlined code.
39080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      break;
39090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    default:
39100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Do nothing.
39110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      break;
39120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
39130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
3914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3916d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
3917e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
3918e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(Operand(ebp, frame_offset), value);
39193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
39203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
39213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3922d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
392359151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(dst, ContextOperand(esi, context_index));
3924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ----------------------------------------------------------------------------
3928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support.
3929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3930d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() {
3931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Cook return address on top of stack (smi encoded Code* delta)
3932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(edx));
3933e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(edx, Operand(esp, 0));
3934e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ sub(Operand(edx), Immediate(masm_->CodeObject()));
3935e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
3936e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, kSmiTag);
3937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(edx, Operand(edx));  // Convert to smi.
3938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(Operand(esp, 0), edx);
3939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store result register while executing finally block.
3940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
3941e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3943e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3944d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() {
3945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(edx));
3946e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Restore result register from stack.
3947e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(result_register());
3948e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Uncook return address.
3949e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(edx, Operand(esp, 0));
3950e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ sar(edx, 1);  // Convert smi to int.
3951e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(Operand(edx), Immediate(masm_->CodeObject()));
3952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(Operand(esp, 0), edx);
3953e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // And return.
3954e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ret(0);
3955e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3956e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef __
3959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
39603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} }  // namespace v8::internal
3961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
3963