full-codegen-ia32.cc revision 7f4d5bd8c03935e2c0cd412e561b8fc5a6a880ae
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
323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "codegen-inl.h"
33d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h"
34e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#include "debug.h"
35d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "full-codegen.h"
363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "parser.h"
376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "scopes.h"
383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 {
403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal {
413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_)
433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function.  On entry to the function the receiver
453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, with the
463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them.  The actual argument count matches the
473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function.
483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are:
503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o edi: the JS function object being called (ie, ourselves)
513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o esi: our context
523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o ebp: our caller's frame pointer
533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o esp: stack pointer (pointing to return address)
543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame.  Please see JavaScriptFrameConstants in
563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-ia32.h for its layout.
573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ASSERT(info_ == NULL);
593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  info_ = info;
603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  SetFunctionPosition(function());
616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comment cmnt(masm_, "[ function compiled by full code generator");
623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (mode == PRIMARY) {
644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ push(ebp);  // Caller's frame pointer.
654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ mov(ebp, esp);
664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ push(esi);  // Callee's context.
674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ push(edi);  // Callee's JS Function.
684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    { Comment cmnt(masm_, "[ Allocate locals");
703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int locals_count = scope()->num_stack_slots();
714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      if (locals_count == 1) {
724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        __ push(Immediate(Factory::undefined_value()));
734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      } else if (locals_count > 1) {
744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        __ mov(eax, Immediate(Factory::undefined_value()));
754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        for (int i = 0; i < locals_count; i++) {
764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ push(eax);
774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        }
78d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
79d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
80d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    bool function_in_register = true;
824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // Possibly allocate a local context.
84f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
85f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (heap_slots > 0) {
864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmnt(masm_, "[ Allocate local context");
874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Argument to NewContext is the function, which is still in edi.
884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ push(edi);
89f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (heap_slots <= FastNewContextStub::kMaximumSlots) {
90f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        FastNewContextStub stub(heap_slots);
91f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ CallStub(&stub);
92f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else {
93f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ CallRuntime(Runtime::kNewContext, 1);
94f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      function_in_register = false;
964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Context is returned in both eax and esi.  It replaces the context
974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // passed to us.  It's saved in the stack and kept live in esi.
984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
1004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Copy parameters into context if necessary.
1013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int num_parameters = scope()->num_parameters();
1024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      for (int i = 0; i < num_parameters; i++) {
1033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        Slot* slot = scope()->parameter(i)->slot();
1044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        if (slot != NULL && slot->type() == Slot::CONTEXT) {
1054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          int parameter_offset = StandardFrameConstants::kCallerSPOffset +
1064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                     (num_parameters - 1 - i) * kPointerSize;
1074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // Load parameter from stack.
1084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ mov(eax, Operand(ebp, parameter_offset));
1094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // Store it in the context.
1104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          int context_offset = Context::SlotOffset(slot->index());
1114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ mov(Operand(esi, context_offset), eax);
1124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // Update the write barrier. This clobbers all involved
1134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // registers, so we have use a third register to avoid
1144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // clobbering esi.
1154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ mov(ecx, esi);
1164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ RecordWrite(ecx, context_offset, eax, ebx);
1174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        }
118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    Variable* arguments = scope()->arguments()->AsVariable();
1224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (arguments != NULL) {
1234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Function uses arguments object.
1244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmnt(masm_, "[ Allocate arguments object");
1254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      if (function_in_register) {
1264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        __ push(edi);
1274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      } else {
1284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      }
1304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Receiver is just before the parameters on the caller's stack.
1313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int offset = scope()->num_parameters() * kPointerSize;
1323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      __ lea(edx,
1333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu             Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
1344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ push(edx);
1353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      __ push(Immediate(Smi::FromInt(scope()->num_parameters())));
1364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Arguments to ArgumentsAccessStub:
1374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      //   function, receiver address, parameter count.
1384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // The stub will rewrite receiver and parameter count if the previous
1394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // stack frame was an arguments adapter frame.
1404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
1414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
1424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ mov(ecx, eax);  // Duplicate result.
1434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Move(arguments->slot(), eax, ebx, edx);
1444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Slot* dot_arguments_slot =
1453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          scope()->arguments_shadow()->AsVariable()->slot();
1464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Move(dot_arguments_slot, ecx, ebx, edx);
147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { Comment cmnt(masm_, "[ Declarations");
151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // For named function expressions, declare the function name as a
152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // constant.
153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (scope()->is_function_scope() && scope()->function() != NULL) {
154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      EmitDeclaration(scope()->function(), Variable::CONST, NULL);
155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Visit all the explicit declarations unless there is an illegal
157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // redeclaration.
158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (scope()->HasIllegalRedeclaration()) {
159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      scope()->VisitIllegalRedeclaration(this);
160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitDeclarations(scope()->declarations());
162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ Stack check");
1663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label ok;
167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ExternalReference stack_limit =
168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ExternalReference::address_of_stack_limit();
169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ cmp(esp, Operand::StaticVariable(stack_limit));
1703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(above_equal, &ok, taken);
1713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    StackCheckStub stub;
1723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CallStub(&stub);
1733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&ok);
1743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (FLAG_trace) {
1773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CallRuntime(Runtime::kTraceEnter, 0);
1783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ Body");
181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    VisitStatements(function()->body());
183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit a 'return undefined' in case control fell off the end of the body.
1883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(eax, Factory::undefined_value());
1897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    EmitReturnSequence();
190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() {
195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ jmp(&return_label_);
198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Common return label
200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
2013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
2023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(eax);
2033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ CallRuntime(Runtime::kTraceExit, 1);
2043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG
206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Add a label for checking the size of the code used for returning.
207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Label check_exit_codesize;
208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    masm_->bind(&check_exit_codesize);
209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
2107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    CodeGenerator::RecordPositions(masm_, function()->end_position());
2113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ RecordJSReturn();
2123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Do not use the leave instruction here because it is too short to
2133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // patch with the code required by the debugger.
2143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(esp, ebp);
2153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ pop(ebp);
2163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    __ ret((scope()->num_parameters() + 1) * kPointerSize);
217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT
218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Check that the size of the code used for returning matches what is
219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // expected by the debugger.
220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_EQ(Assembler::kJSReturnSequenceLength,
221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
227d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Register reg) {
228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
231e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Nothing to do.
234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValue:
237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Move value into place.
238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
239e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (!reg.is(result_register())) __ mov(result_register(), reg);
241e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
243e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(reg);
244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTest:
249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // For simplicity we always test the accumulator register.
250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!reg.is(result_register())) __ mov(result_register(), reg);
251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
253e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!reg.is(result_register())) __ mov(result_register(), reg);
257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
270d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Slot* slot) {
271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Nothing to do.
276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue: {
278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      MemOperand slot_operand = EmitSlotSearch(slot, result_register());
279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(result_register(), slot_operand);
282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Memory operands can be pushed directly.
285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(slot_operand);
286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // For simplicity we always test the accumulator register.
293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Move(result_register(), slot);
294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Move(result_register(), slot);
300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
313d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Literal* lit) {
314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Nothing to do.
319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(result_register(), lit->handle());
324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Immediates can be pushed directly.
327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(Immediate(lit->handle()));
328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // For simplicity we always test the accumulator register.
334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(result_register(), lit->handle());
335e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
337e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
338e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(result_register(), lit->handle());
341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
351d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
352d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
353d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
354d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ApplyTOS(Expression::Context context) {
355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
361d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
372e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // For simplicity we always test the accumulator register.
375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ pop(result_register());
376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTestValue:
381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(result_register(), Operand(esp, 0));
387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
395d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DropAndApply(int count,
396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     Expression::Context context,
397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     Register reg) {
398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(count > 0);
399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!reg.is(esp));
400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
401d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(count);
406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValue:
409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Drop(count);
412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (!reg.is(result_register())) __ mov(result_register(), reg);
413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (count > 1) __ Drop(count - 1);
416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(Operand(esp, 0), reg);
417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // For simplicity we always test the accumulator register.
423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(count);
424e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!reg.is(result_register())) __ mov(result_register(), reg);
425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
428e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTestValue:
430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
431e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Drop(count);
433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (!reg.is(result_register())) __ mov(result_register(), reg);
434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (count > 1) __ Drop(count - 1);
437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(result_register(), reg);
438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(Operand(esp, 0), result_register());
439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::PrepareTest(Label* materialize_true,
448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                    Label* materialize_false,
449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                    Label** if_true,
450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                    Label** if_false) {
451f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (context_) {
452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kUninitialized:
453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      UNREACHABLE();
454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kEffect:
456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // In an effect context, the true and the false case branch to the
457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // same label.
458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_true = *if_false = materialize_true;
459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kValue:
461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_true = materialize_true;
462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_false = materialize_false;
463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kTest:
465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_true = true_label_;
466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_false = false_label_;
467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kValueTest:
469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_true = materialize_true;
470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_false = false_label_;
471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kTestValue:
473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_true = true_label_;
474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_false = materialize_false;
475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
480d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context,
481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                              Label* materialize_true,
482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                              Label* materialize_false) {
483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT_EQ(materialize_true, materialize_false);
488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(materialize_true);
489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue: {
492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Label done;
493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_true);
496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(result_register(), Factory::true_value());
497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(&done);
498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_false);
499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(result_register(), Factory::false_value());
500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_true);
503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(Immediate(Factory::true_value()));
504e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(&done);
505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_false);
506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(Immediate(Factory::false_value()));
507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(&done);
510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(materialize_true);
518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(result_register(), Factory::true_value());
521e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
523e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(Immediate(Factory::true_value()));
524e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
525e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
526e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(true_label_);
527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(materialize_false);
531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(result_register(), Factory::false_value());
534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(Immediate(Factory::false_value()));
537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(false_label_);
540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// Convert constant control flow (true or false) to the result expected for
546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// a given expression context.
547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, bool flag) {
548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (context) {
549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kUninitialized:
550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      UNREACHABLE();
551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kEffect:
553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kValue: {
555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Handle<Object> value =
556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          flag ? Factory::true_value() : Factory::false_value();
557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      switch (location_) {
558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kAccumulator:
559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ mov(result_register(), value);
560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kStack:
562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(Immediate(value));
563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kTest:
568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ jmp(flag ? true_label_ : false_label_);
569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kTestValue:
571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      switch (location_) {
572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kAccumulator:
573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // If value is false it's needed.
574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (!flag) __ mov(result_register(), Factory::false_value());
575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kStack:
577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // If value is false it's needed.
578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (!flag) __ push(Immediate(Factory::false_value()));
579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ jmp(flag ? true_label_ : false_label_);
582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kValueTest:
584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      switch (location_) {
585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kAccumulator:
586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // If value is true it's needed.
587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (flag) __ mov(result_register(), Factory::true_value());
588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kStack:
590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // If value is true it's needed.
591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (flag) __ push(Immediate(Factory::true_value()));
592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ jmp(flag ? true_label_ : false_label_);
595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
600d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DoTest(Expression::Context context) {
601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // The value to test is in the accumulator.  If the value might be needed
602e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // on the stack (value/test and test/value contexts with a stack location
603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // desired), then the value is already duplicated on the stack.
604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_NE(NULL, true_label_);
605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_NE(NULL, false_label_);
606e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In value/test and test/value expression contexts with stack as the
608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // desired location, there is already an extra value on the stack.  Use a
609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // label to discard it if unneeded.
610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label discard;
611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label* if_true = true_label_;
612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label* if_false = false_label_;
613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
619d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_false = &discard;
626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_true = &discard;
635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
638e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the inlined tests assumed by the stub.
641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(result_register(), Factory::undefined_value());
642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(result_register(), Factory::true_value());
644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_true);
645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(result_register(), Factory::false_value());
646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, kSmiTag);
648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ test(result_register(), Operand(result_register()));
649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(zero, if_false);
650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ test(result_register(), Immediate(kSmiTagMask));
651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(zero, if_true);
652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save a copy of the value if it may be needed and isn't already saved.
654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValue:
658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
665e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
666e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
672e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
677e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call the ToBoolean stub for all other cases.
682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ToBooleanStub stub;
683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ test(eax, Operand(eax));
686e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // The stub returns nonzero for true.  Complete based on the context.
688e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
693e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTest:
695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(not_zero, true_label_);
696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(false_label_);
697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
700e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
701e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
702e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(zero, &discard);
703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
704e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(true_label_);
705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
706e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
707e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(not_zero, true_label_);
708e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ bind(&discard);
711e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ jmp(false_label_);
713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
714e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
715e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(not_zero, &discard);
719e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(false_label_);
721e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
722e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
723e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(zero, false_label_);
724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ bind(&discard);
727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ jmp(true_label_);
729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
734d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (slot->type()) {
736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::PARAMETER:
737e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOCAL:
738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return Operand(ebp, SlotOffset(slot));
739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::CONTEXT: {
740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      int context_chain_length =
7413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          scope()->ContextChainLength(slot->var()->scope());
742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ LoadContext(scratch, context_chain_length);
743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return CodeGenerator::ContextOperand(scratch, slot->index());
744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOOKUP:
746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  UNREACHABLE();
749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return Operand(eax, 0);
750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
753d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) {
754e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(source, destination);
755e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(destination, location);
756e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
759d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst,
760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register src,
761e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch1,
762e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch2) {
763e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(dst->type() != Slot::LOOKUP);  // Not yet implemented.
764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!scratch1.is(src) && !scratch2.is(src));
765e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(dst, scratch1);
766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(location, src);
767e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
768e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (dst->type() == Slot::CONTEXT) {
769e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
770e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ RecordWrite(scratch1, offset, src, scratch2);
771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitDeclaration(Variable* variable,
776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Variable::Mode mode,
777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        FunctionLiteral* function) {
778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Declaration");
779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(variable != NULL);  // Must have been resolved.
780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Slot* slot = variable->slot();
781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = variable->AsProperty();
782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (slot != NULL) {
783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOCAL:
786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
787e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(Operand(ebp, SlotOffset(slot)),
788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                 Immediate(Factory::the_hole_value()));
789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          VisitForValue(function, kAccumulator);
791e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(Operand(ebp, SlotOffset(slot)), result_register());
792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT:
796e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // We bypass the general EmitSlotSearch because we know more about
797e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // this specific context.
798e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // The variable in the decl always resides in the current context.
800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (FLAG_debug_code) {
802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Check if we have the correct context pointer.
803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ mov(ebx,
804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                 CodeGenerator::ContextOperand(esi, Context::FCONTEXT_INDEX));
805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ cmp(ebx, Operand(esi));
806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Check(equal, "Unexpected declaration in current context.");
807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ mov(CodeGenerator::ContextOperand(esi, slot->index()),
810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 Immediate(Factory::the_hole_value()));
811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // No write barrier since the hole value is in old space.
812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          VisitForValue(function, kAccumulator);
814e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(CodeGenerator::ContextOperand(esi, slot->index()),
815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                 result_register());
816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          int offset = Context::SlotOffset(slot->index());
8174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ mov(ebx, esi);
8184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ RecordWrite(ebx, offset, result_register(), ecx);
819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP: {
823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(esi);
824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(Immediate(variable->name()));
825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Declaration nodes are always introduced in one of two modes.
826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ASSERT(mode == Variable::VAR || mode == Variable::CONST);
827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY;
828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(Immediate(Smi::FromInt(attr)));
829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Push initial value, if any.
830d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Note: For variables we must not push an initial value (such as
831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // 'undefined') because we may have a (legal) redeclaration and we
832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // must not destroy the current value.
833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ push(Immediate(Factory::the_hole_value()));
835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          VisitForValue(function, kStack);
837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else {
838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ push(Immediate(Smi::FromInt(0)));  // No initial value!
839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDeclareContextSlot, 4);
841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (prop != NULL) {
846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (function != NULL || mode == Variable::CONST) {
847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // We are declaring a function or constant that rewrites to a
848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // property.  Use (keyed) IC to set the initial value.
849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->obj(), kStack);
850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (function != NULL) {
8516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        VisitForValue(prop->key(), kStack);
852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForValue(function, kAccumulator);
8536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ pop(ecx);
854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
8556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        VisitForValue(prop->key(), kAccumulator);
8566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ mov(ecx, result_register());
857e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ mov(result_register(), Factory::the_hole_value());
858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
8596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ pop(edx);
860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ call(ic, RelocInfo::CODE_TARGET);
863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Absence of a test eax instruction following the call
864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // indicates that none of the load was inlined.
865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ nop();
866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
8673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) {
872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
876d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
8773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
8783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(esi);  // The context is the first argument.
8793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(pairs));
8803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kDeclareGlobals, 3);
8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ SwitchStatement");
888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Breakable nested_statement(this, stmt);
889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Keep the switch value on the stack until a case matches.
891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(stmt->tag(), kStack);
892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<CaseClause*>* clauses = stmt->cases();
894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label next_test;  // Recycled for each test.
897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the tests with branches to their bodies.
898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The default is not a test, but remember it as final fall through.
901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (clause->is_default()) {
902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      default_clause = clause;
903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      continue;
904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case comparison");
907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&next_test);
908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    next_test.Unuse();
909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Compile the label expression.
911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(clause->label(), kAccumulator);
912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Perform the comparison as if via '==='.  The comparison stub expects
914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // the smi vs. smi case to be handled before it is called.
915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Label slow_case;
916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(edx, Operand(esp, 0));  // Switch value.
917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(ecx, edx);
918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ or_(ecx, Operand(eax));
919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ test(ecx, Immediate(kSmiTagMask));
920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(not_zero, &slow_case, not_taken);
921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ cmp(edx, Operand(eax));
922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(not_equal, &next_test);
923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(clause->body_target()->entry_label());
925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&slow_case);
927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CompareStub stub(equal, true);
928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ test(eax, Operand(eax));
930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(not_equal, &next_test);
931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(clause->body_target()->entry_label());
933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
9343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Discard the test value and jump to the default if present, otherwise to
936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the end of the statement.
937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&next_test);
938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(1);  // Switch value is no longer needed.
939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (default_clause == NULL) {
940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(nested_statement.break_target());
941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(default_clause->body_target()->entry_label());
943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the case bodies.
946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case body");
948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(clause->body_target()->entry_label());
950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitStatements(clause->statements());
951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(nested_statement.break_target());
954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ ForInStatement");
959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label loop, exit;
962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ForIn loop_statement(this, stmt);
963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  increment_loop_depth();
964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the object to enumerate over. Both SpiderMonkey and JSC
966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ignore null and undefined in contrast to the specification; see
967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ECMA-262 section 12.6.4.
968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(stmt->enumerable(), kAccumulator);
969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Factory::undefined_value());
970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Factory::null_value());
972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the object to a JS object.
975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label convert, done_convert;
976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, &convert);
978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(above_equal, &done_convert);
980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&convert);
981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);
982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done_convert);
984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);
9853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // TODO(kasperl): Check cache validity in generated code. This is a
987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // fast case for the JSObject::IsSimpleEnum cache validity
988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // checks. If we cannot guarantee cache validity, call the runtime
989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // system to check cache validity or get the property names in a
990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // fixed array.
991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the set of properties to enumerate.
993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);  // Duplicate the enumerable object on the stack.
994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If we got a map from the runtime call, we can do a fast
997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // modification check. Otherwise, we got a fixed array, and we have
998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // to do a slow check.
999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label fixed_array;
1000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::meta_map());
1001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &fixed_array);
1002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a map in register eax. Get the enumeration cache from it.
1004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset));
1005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset));
1006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Setup the four remaining stack slots.
1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);  // Map.
1010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(edx);  // Enumeration cache.
1011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset));
1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);  // Enumeration cache length (as smi).
1013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(Smi::FromInt(0)));  // Initial index.
1014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
1015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a fixed array in register eax. Iterate through that.
1017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&fixed_array);
1018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(Smi::FromInt(0)));  // Map (0) - force slow check.
1019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);
1020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
1021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);  // Fixed array length (as smi).
1022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(Smi::FromInt(0)));  // Initial index.
1023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for doing the condition check.
1025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&loop);
1026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(esp, 0 * kPointerSize));  // Get the current index.
1027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Operand(esp, 1 * kPointerSize));  // Compare to the array length.
1028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(above_equal, loop_statement.break_target());
1029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the current entry of the array into register ebx.
1031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, Operand(esp, 2 * kPointerSize));
1032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize));
1033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the expected map from the stack or a zero map in the
1035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // permanent slow case into register edx.
1036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, Operand(esp, 3 * kPointerSize));
1037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the expected map still matches that of the enumerable.
1039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If not, we have to filter the key.
1040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label update_each;
1041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ecx, Operand(esp, 4 * kPointerSize));
1042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset));
1043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &update_each);
1044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the entry to a string or null if it isn't a property
1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // anymore. If the property has been removed while iterating, we
1047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // just skip it.
1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(ecx);  // Enumerable.
1049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(ebx);  // Current entry.
1050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Factory::null_value());
1052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, loop_statement.continue_target());
1053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, Operand(eax));
1054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the 'each' property or variable from the possibly filtered
1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // entry in register ebx.
1057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&update_each);
1058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(result_register(), ebx);
1059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Perform the assignment as if via '='.
1060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  EmitAssignment(stmt->each());
1061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the body of the loop.
1063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label stack_limit_hit, stack_check_done;
1064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Visit(stmt->body());
1065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ StackLimitCheck(&stack_limit_hit);
1067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&stack_check_done);
1068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for going to the next element by incrementing the
1070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // index (smi) stored on top of the stack.
1071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(loop_statement.continue_target());
1072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
1073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
1074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Slow case for the stack limit check.
1076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StackCheckStub stack_check_stub;
1077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&stack_limit_hit);
1078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stack_check_stub);
1079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&stack_check_done);
1080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Remove the pointers stored on the stack.
1082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(loop_statement.break_target());
1083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(Operand(esp), Immediate(5 * kPointerSize));
1084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Exit and decrement the loop depth.
1086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
1087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  decrement_loop_depth();
1088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
1092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Use the fast case closure allocation code that allocates in new
1093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // space for nested functions that don't need literals cloning.
1094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (scope()->is_function_scope() && info->num_literals() == 0) {
1095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    FastNewClosureStub stub;
1096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Immediate(info));
1097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
1098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(esi);
1100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Immediate(info));
1101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kNewClosure, 2);
1102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, eax);
11043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1107d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
11083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ VariableProxy");
1109e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  EmitVariableLoad(expr->var(), context_);
1110e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1111e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1112e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1113d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableLoad(Variable* var,
1114e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Expression::Context context) {
1115d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Four cases: non-this global variables, lookup slots, all other
1116d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // types of slots, and parameters that rewrite to explicit property
1117d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // accesses on the arguments object.
1118d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Slot* slot = var->slot();
1119d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Property* property = var->AsProperty();
1120d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1121d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (var->is_global() && !var->is_this()) {
11223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Comment cmnt(masm_, "Global variable");
11233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Use inline caching. Variable name is passed in ecx and the global
11243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // object on the stack.
1125402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(eax, CodeGenerator::GlobalObject());
1126e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ mov(ecx, var->name());
11273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
11283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // By emitting a nop we make sure that we do not have a test eax
1130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // instruction after the call it is treated specially by the LoadIC code
1131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Remember that the assembler may choose to do peephole optimization
1132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // (eg, push/pop elimination).
1133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ nop();
1134402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Apply(context, eax);
1135d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1136d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
1137d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Lookup slot");
1138d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ push(esi);  // Context.
1139d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ push(Immediate(var->name()));
1140d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
1141d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Apply(context, eax);
1142d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1143d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL) {
1144d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1145d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            ? "Context slot"
1146d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            : "Stack slot");
1147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (var->mode() == Variable::CONST) {
1148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Constants may be the hole value if they have not been initialized.
1149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Unhole them.
1150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label done;
1151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      MemOperand slot_operand = EmitSlotSearch(slot, eax);
1152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(eax, slot_operand);
1153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ cmp(eax, Factory::the_hole_value());
1154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ j(not_equal, &done);
1155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(eax, Factory::undefined_value());
1156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ bind(&done);
1157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Apply(context, eax);
1158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
1159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Apply(context, slot);
1160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1161d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1163d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Rewritten parameter");
1164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(property);
1165d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Rewritten parameter accesses are of the form "slot[literal]".
1166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1167e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the object is in a slot.
1168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(object_var);
1170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Slot* object_slot = object_var->slot();
1171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(object_slot);
1172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the object.
1174e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    MemOperand object_loc = EmitSlotSearch(object_slot, eax);
1175402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(edx, object_loc);
1176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1177e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the key is a smi.
1178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key_literal = property->key()->AsLiteral();
1179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(key_literal);
1180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(key_literal->handle()->IsSmi());
1181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the key.
1183402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(eax, Immediate(key_literal->handle()));
1184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Do a keyed property load.
1186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ call(ic, RelocInfo::CODE_TARGET);
1188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Notice: We must not have a "test eax, ..." instruction after the
1189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // call. It is treated specially by the LoadIC code.
1190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ nop();
1191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Drop key and object left on the stack by IC.
1192402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Apply(context, eax);
11933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1197d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ RegExpLiteral");
11993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label done;
12003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Registers will be used as follows:
12013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // edi = JS function.
12023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // ebx = literals array.
12033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // eax = regexp literal.
12043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
12053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset));
12063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int literal_offset =
12073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
12083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(eax, FieldOperand(ebx, literal_offset));
12093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ cmp(eax, Factory::undefined_value());
12103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &done);
12113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Create regexp literal using runtime function
12123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Result will be in eax.
12133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(ebx);
12143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(Smi::FromInt(expr->literal_index())));
12153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(expr->pattern()));
12163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(expr->flags()));
12173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
12183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Label done:
12193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&done);
1220e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, eax);
1221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1224d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
1226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1227e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(edi, JSFunction::kLiteralsOffset));
1228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ push(Immediate(Smi::FromInt(expr->literal_index())));
1229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ push(Immediate(expr->constant_properties()));
12306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(Immediate(Smi::FromInt(expr->fast_elements() ? 1 : 0)));
1231e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->depth() > 1) {
12326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
12333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
12346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
1235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
1238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in eax.
1239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
1240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < expr->properties()->length(); i++) {
1242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectLiteral::Property* property = expr->properties()->at(i);
1243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
1244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = property->key();
1246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
1247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
1248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ push(eax);  // Save result on the stack
1249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
1250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
1252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
1256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (key->handle()->IsSymbol()) {
1257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          VisitForValue(value, kAccumulator);
1258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ mov(ecx, Immediate(key->handle()));
12594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ mov(edx, Operand(esp, 0));
1260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ call(ic, RelocInfo::CODE_TARGET);
1262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ nop();
1263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::PROTOTYPE:
1267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(esp, 0));  // Duplicate receiver.
1268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(key, kStack);
1269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(value, kStack);
1270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kSetProperty, 3);
1271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::SETTER:
1273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::GETTER:
1274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(esp, 0));  // Duplicate receiver.
1275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(key, kStack);
1276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ?
1277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                          Smi::FromInt(1) :
1278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                          Smi::FromInt(0)));
1279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(value, kStack);
1280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDefineAccessor, 4);
1281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      default: UNREACHABLE();
1283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
1287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ApplyTOS(context_);
1288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
1289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Apply(context_, eax);
12903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
12923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1294d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
1296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<Expression*>* subexprs = expr->values();
1298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int length = subexprs->length();
1299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
13003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
13023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(Smi::FromInt(expr->literal_index())));
1303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(Immediate(expr->constant_elements()));
13043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (expr->depth() > 1) {
1305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
1306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (length > FastCloneShallowArrayStub::kMaximumLength) {
1307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
1308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    FastCloneShallowArrayStub stub(length);
1310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
13113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
13143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
13163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
1317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < length; i++) {
13183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Expression* subexpr = subexprs->at(i);
13193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
13203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
13213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (subexpr->AsLiteral() != NULL ||
13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        CompileTimeValue::IsCompileTimeValue(subexpr)) {
13233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      continue;
13243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
13253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
13273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(eax);
13283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
13293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(subexpr, kAccumulator);
13313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Store the subexpression value in the array's elements.
13333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(ebx, Operand(esp, 0));  // Copy of array literal.
13343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
13353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ mov(FieldOperand(ebx, offset), result_register());
13373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Update the write barrier for the array store.
1339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ RecordWrite(ebx, offset, result_register(), ecx);
13403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
1343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ApplyTOS(context_);
1344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
1345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Apply(context_, eax);
13463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
13483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1350402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1351402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Comment cmnt(masm_, "[ Assignment");
1352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // on the left-hand side.
1354f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->target()->IsValidLeftHandSide()) {
1355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->target());
1356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1359402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Left-hand side can only be a property, a global or a (parameter or local)
1360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LhsKind assign_type = VARIABLE;
1363402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Property* prop = expr->target()->AsProperty();
1364402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (prop != NULL) {
1365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    assign_type =
1366402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
1367402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1368402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate LHS expression.
1370402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1372402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Nothing to do here.
1373402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1374402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1375402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1376402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // We need the receiver both on the stack and in the accumulator.
1377402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        VisitForValue(prop->obj(), kAccumulator);
1378402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
1380402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        VisitForValue(prop->obj(), kStack);
1381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1383402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1384402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1385402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        VisitForValue(prop->obj(), kStack);
1386402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        VisitForValue(prop->key(), kAccumulator);
1387402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ mov(edx, Operand(esp, 0));
1388402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(eax);
1389402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
1390402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        VisitForValue(prop->obj(), kStack);
1391402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        VisitForValue(prop->key(), kStack);
1392402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1394402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1395402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // If we have a compound assignment: Get value of LHS expression and
1397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // store in on top of the stack.
1398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
1399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Location saved_location = location_;
1400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = kStack;
1401402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    switch (assign_type) {
1402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      case VARIABLE:
1403402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        EmitVariableLoad(expr->target()->AsVariableProxy()->var(),
1404402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                         Expression::kValue);
1405402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        break;
1406402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      case NAMED_PROPERTY:
1407402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        EmitNamedPropertyLoad(prop);
1408402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        break;
1410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      case KEYED_PROPERTY:
1411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        EmitKeyedPropertyLoad(prop);
1412402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1413402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        break;
1414402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1415402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = saved_location;
1416402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1417402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1418402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate RHS expression.
1419402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Expression* rhs = expr->value();
1420402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  VisitForValue(rhs, kAccumulator);
1421402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1422402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // If we have a compound assignment: Apply operator.
1423402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
1424402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Location saved_location = location_;
1425402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = kAccumulator;
1426402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    EmitBinaryOp(expr->binary_op(), Expression::kValue);
1427402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = saved_location;
1428402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1429402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1430402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Record source position before possible IC call.
1431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  SetSourcePosition(expr->position());
1432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1433402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Store the value.
1434402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1435402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1436402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                             expr->op(),
1438402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                             context_);
1439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1440402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1441402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitNamedPropertyAssignment(expr);
1442402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1443402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitKeyedPropertyAssignment(expr);
1445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1447402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1450d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Literal* key = prop->key()->AsLiteral();
1453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(ecx, Immediate(key->handle()));
1454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ call(ic, RelocInfo::CODE_TARGET);
1456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ nop();
1457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1460d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1461e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ call(ic, RelocInfo::CODE_TARGET);
1464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ nop();
1465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1468d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitBinaryOp(Token::Value op,
1469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     Expression::Context context) {
1470e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
1471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  GenericBinaryOpStub stub(op,
1472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_OVERWRITE,
14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           NO_GENERIC_BINARY_FLAGS,
14746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           TypeInfo::Unknown());
1475e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
1476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context, eax);
1477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitAssignment(Expression* expr) {
1481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw
1482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ReferenceError' on the left-hand side.
1483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->IsValidLeftHandSide()) {
1484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr);
1485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand side can only be a property, a global or a (parameter or local)
1489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  LhsKind assign_type = VARIABLE;
1492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = expr->AsProperty();
1493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (prop != NULL) {
1494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    assign_type = (prop->key()->IsPropertyName())
1495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ? NAMED_PROPERTY
1496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        : KEYED_PROPERTY;
1497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (assign_type) {
1500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case VARIABLE: {
1501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->AsVariableProxy()->var();
1502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect);
1503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1505f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case NAMED_PROPERTY: {
1506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(eax);  // Preserve value.
1507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitForValue(prop->obj(), kAccumulator);
1508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(edx, eax);
1509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(eax);  // Restore value.
1510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(ecx, prop->key()->AsLiteral()->handle());
1511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ call(ic, RelocInfo::CODE_TARGET);
1513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ nop();  // Signal no inlined code.
1514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case KEYED_PROPERTY: {
1517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(eax);  // Preserve value.
1518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitForValue(prop->obj(), kStack);
1519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitForValue(prop->key(), kAccumulator);
1520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(ecx, eax);
1521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(edx);
1522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(eax);  // Restore value.
1523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ call(ic, RelocInfo::CODE_TARGET);
1525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ nop();  // Signal no inlined code.
1526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1532d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var,
1533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                               Token::Value op,
1534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                               Expression::Context context) {
1535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand sides that rewrite to explicit property accesses do not reach
1536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // here.
15373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(var != NULL);
15383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(var->is_global() || var->slot() != NULL);
1539d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
15403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (var->is_global()) {
1541d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT(!var->is_this());
1542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Assignment to a global variable.  Use inline caching for the
1543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // assignment.  Right-hand-side value is passed in eax, variable name in
1544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // ecx, and the global object on the stack.
15453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(ecx, var->name());
15464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ mov(edx, CodeGenerator::GlobalObject());
15473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
15483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ call(ic, RelocInfo::CODE_TARGET);
1549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ nop();
1550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) {
1552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Perform the assignment for non-const variables and for initialization
1553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // of const variables.  Const assignments are simply skipped.
1554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Label done;
1555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Slot* slot = var->slot();
1556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
1557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
1558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      case Slot::LOCAL:
1559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Detect const reinitialization by checking for the hole value.
1561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ mov(edx, Operand(ebp, SlotOffset(slot)));
1562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ cmp(edx, Factory::the_hole_value());
1563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ j(not_equal, &done);
1564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment.
1566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(Operand(ebp, SlotOffset(slot)), eax);
1567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT: {
1570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        MemOperand target = EmitSlotSearch(slot, ecx);
1571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Detect const reinitialization by checking for the hole value.
1573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ mov(edx, target);
1574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ cmp(edx, Factory::the_hole_value());
1575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ j(not_equal, &done);
1576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment and issue the write barrier.
1578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(target, eax);
1579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The value of the assignment is in eax.  RecordWrite clobbers its
1580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // register arguments.
1581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(edx, eax);
1582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
1583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ RecordWrite(ecx, offset, edx, ebx);
1584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
15853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
1586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP:
1588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Call the runtime for the assignment.  The runtime will ignore
1589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // const reinitialization.
1590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(eax);  // Value.
1591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(esi);  // Context.
1592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(Immediate(var->name()));
1593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // The runtime will ignore const redeclaration.
1595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else {
1597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kStoreContextSlot, 3);
1598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
16003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&done);
16023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context, eax);
16053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1608d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
1610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
1611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop != NULL);
1612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop->key()->AsLiteral() != NULL);
16133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(Operand(esp, kPointerSize));  // Receiver is now under value.
1620d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(ecx, prop->key()->AsLiteral()->handle());
16274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (expr->ends_initialization_block()) {
16284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ mov(edx, Operand(esp, 0));
16294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
16304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ pop(edx);
16314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
1632d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1633d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ call(ic, RelocInfo::CODE_TARGET);
1634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ nop();
1635d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1636d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(eax);  // Result of assignment, saved even if not needed.
1639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(esp, kPointerSize));  // Receiver is under value.
1640d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(eax);
16424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    DropAndApply(1, context_, eax);
16434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
16444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Apply(context_, eax);
1645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1647d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1648d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1649d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1650d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
1651d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1654d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Receiver is now under the key and value.
1658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(esp, 2 * kPointerSize));
1659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1661d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
16636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ pop(ecx);
16646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (expr->ends_initialization_block()) {
16656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ mov(edx, Operand(esp, 0));  // Leave receiver on the stack for later.
16666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
16676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ pop(edx);
16686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ call(ic, RelocInfo::CODE_TARGET);
1673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This nop signals to the IC that there is no inlined code at the call
1674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // site for it to patch.
1675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ nop();
1676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
16796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ pop(edx);
1680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(eax);  // Result of assignment, saved even if not needed.
16816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ push(edx);
1682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(eax);
1684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
16866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Apply(context_, eax);
1687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1690d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) {
1691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Property");
1692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* key = expr->key();
1693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1694e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (key->IsPropertyName()) {
1695402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    VisitForValue(expr->obj(), kAccumulator);
1696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitNamedPropertyLoad(expr);
1697402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Apply(context_, eax);
1698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1699402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    VisitForValue(expr->obj(), kStack);
1700402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    VisitForValue(expr->key(), kAccumulator);
1701402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop(edx);
1702e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitKeyedPropertyLoad(expr);
1703402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Apply(context_, eax);
1704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1708d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr,
1709e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       Handle<Object> name,
1710e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       RelocInfo::Mode mode) {
1711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the IC.
1712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
17133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
17143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
1715e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
17163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Set(ecx, Immediate(name));
1718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source position of the IC call.
17193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SetSourcePosition(expr->position());
1720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1721e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
1722e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ call(ic, mode);
1723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Restore context register.
1724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, eax);
1726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
17297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
17307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                            Expression* key,
17317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                            RelocInfo::Mode mode) {
17327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Code common for calls using the IC.
17337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
17347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  int arg_count = args->length();
17357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  for (int i = 0; i < arg_count; i++) {
17367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    VisitForValue(args->at(i), kStack);
17377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
17387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  VisitForValue(key, kAccumulator);
17397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(ecx, eax);
17407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Record source position of the IC call.
17417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetSourcePosition(expr->position());
17427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
17437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(
17447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      arg_count, in_loop);
17457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ call(ic, mode);
17467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Restore context register.
17477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
17487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Apply(context_, eax);
17497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
17507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1752d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) {
1753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the call stub.
1754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
1756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
1757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
1758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
1760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
1761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ CallStub(&stub);
17643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore context register.
17653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  DropAndApply(1, context_, eax);
1767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1770d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) {
1771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Call");
1772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* fun = expr->expression();
1773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Variable* var = fun->AsVariableProxy()->AsVariable();
1774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1775d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (var != NULL && var->is_possibly_eval()) {
1776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // In a call to eval, we first call %ResolvePossiblyDirectEval to
1777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // resolve the function we need to call and the receiver of the
1778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // call.  Then we call the resolved function using the given
1779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // arguments.
1780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(fun, kStack);
1781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Immediate(Factory::undefined_value()));  // Reserved receiver slot.
1782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push the arguments.
1784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    ZoneList<Expression*>* args = expr->arguments();
1785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    int arg_count = args->length();
1786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    for (int i = 0; i < arg_count; i++) {
1787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitForValue(args->at(i), kStack);
1788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push copy of the function - found below the arguments.
1791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Operand(esp, (arg_count + 1) * kPointerSize));
1792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push copy of the first argument or undefined if it doesn't exist.
1794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (arg_count > 0) {
1795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(Operand(esp, arg_count * kPointerSize));
1796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
1797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(Immediate(Factory::undefined_value()));
1798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push the receiver of the enclosing function and do runtime call.
1801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
1802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
1803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The runtime call returns a pair of values in eax (function) and
1805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // edx (receiver). Touch up the stack with the right values.
1806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
1807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
1808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Record source position for debugger.
1810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    SetSourcePosition(expr->position());
1811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
1814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Restore context register.
1815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    DropAndApply(1, context_, eax);
1817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (var != NULL && !var->is_this() && var->is_global()) {
1818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Push global object as receiver for the call IC.
1819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(CodeGenerator::GlobalObject());
1820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
1821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (var != NULL && var->slot() != NULL &&
1822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block             var->slot()->type() == Slot::LOOKUP) {
1823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Call to a lookup slot (dynamically introduced variable).  Call the
1824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // runtime to find the function to call (returned in eax) and the object
1825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // holding it (returned in edx).
1826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(context_register());
1827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Immediate(var->name()));
1828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
1829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(eax);  // Function.
1830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(edx);  // Receiver.
1831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitCallWithStub(expr);
1832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (fun->AsProperty() != NULL) {
1833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to an object property.
1834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Property* prop = fun->AsProperty();
1835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = prop->key()->AsLiteral();
1836d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (key != NULL && key->handle()->IsSymbol()) {
1837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Call to a named property, use call IC.
1838e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->obj(), kStack);
1839e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
18417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Call to a keyed property.
18427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // For a synthetic property use keyed load IC followed by function call,
18437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // for a regular property use keyed CallIC.
1844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->obj(), kStack);
1845402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (prop->is_synthetic()) {
18467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        VisitForValue(prop->key(), kAccumulator);
18477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        // Record source code position for IC call.
18487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        SetSourcePosition(prop->position());
1849402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ pop(edx);  // We do not need to keep the receiver.
1850402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
18527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        __ call(ic, RelocInfo::CODE_TARGET);
18537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        // By emitting a nop we make sure that we do not have a "test eax,..."
18547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        // instruction after the call as it is treated specially
18557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        // by the LoadIC code.
18567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        __ nop();
1857402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // Push result (function).
1858402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(eax);
1859402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // Push Global receiver.
1860e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ mov(ecx, CodeGenerator::GlobalObject());
1861e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset));
18627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        EmitCallWithStub(expr);
1863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
18647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
1865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
18673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
1868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to some other expression.  If the expression is an anonymous
1869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // function literal not called in a loop, mark it as one that should
1870d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // also use the full code generator.
1871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    FunctionLiteral* lit = fun->AsFunctionLiteral();
1872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (lit != NULL &&
1873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        lit->name()->Equals(Heap::empty_string()) &&
1874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        loop_depth() == 0) {
1875d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      lit->set_try_full_codegen(true);
1876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(fun, kStack);
1878d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load global receiver object.
1879d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ mov(ebx, CodeGenerator::GlobalObject());
1880d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
1881d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit function call.
1882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    EmitCallWithStub(expr);
18833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
18843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
18853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1887d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
1888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
1889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
1890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
1891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
1892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push function on the stack.
1893e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  VisitForValue(expr->expression(), kStack);
1894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push global object (receiver).
1896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ push(CodeGenerator::GlobalObject());
1897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
1899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
1901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
1902e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
1903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
1906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
1907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
1908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Load function, arg_count into edi and eax.
1910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Set(eax, Immediate(arg_count));
1911d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Function is in esp[arg_count + 1].
1912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize));
1913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
1915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
1916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Replace function on TOS with result in eax, or pop it.
1918e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  DropAndApply(1, context_, eax);
1919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1920d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
1923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
1926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
1930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
1933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, if_true);
1934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
1935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
1937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
1941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
1944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
1948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask | 0x80000000));
1951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, if_true);
1952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
1953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
1955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
1959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
1962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
1966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
1969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, if_false);
1970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Factory::null_value());
1971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
1972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
1973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Undetectable objects behave like undefined when tested with typeof.
1974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset));
1975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(ecx, Immediate(1 << Map::kIsUndetectable));
1976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_zero, if_false);
1977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset));
1978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
1979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, if_false);
1980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(ecx, LAST_JS_OBJECT_TYPE);
1981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below_equal, if_true);
1982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
1983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
1985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
1989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
1992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
1999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, if_false);
2000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
2002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(ebx, Immediate(1 << Map::kIsUndetectable));
2003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_zero, if_true);
2004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
2005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
2011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, if_false);
2022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
2024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
2025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
2031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_false);
2042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
2043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
2044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
2045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
2051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_false);
2062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx);
2063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
2064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
2065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
2072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the frame pointer for the calling frame.
2080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Skip the arguments adaptor frame if it exists.
2083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label check_frame_marker;
2084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(Operand(eax, StandardFrameConstants::kContextOffset),
2085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &check_frame_marker);
2087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(eax, StandardFrameConstants::kCallerFPOffset));
2088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check the marker in the calling frame.
2090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&check_frame_marker);
2091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset),
2092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
2093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
2094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
2095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
2101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the two objects into registers and perform the comparison.
2104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kAccumulator);
2106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(ebx);
2113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Operand(ebx));
2114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
2115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
2116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2117f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2118f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ArgumentsAccessStub expects the key in edx and the formal
2125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // parameter count in eax.
2126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, eax);
2128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
2129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label exit;
2139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the number of formal parameters.
2140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Set(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
2141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the calling frame is an arguments adaptor frame.
2143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset),
2145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Arguments adaptor case: Read the arguments length from the
2149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // adaptor frame.
2150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (FLAG_debug_code) __ AbortIfNotSmi(eax);
2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
2159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, null, function, non_function_constructor;
2161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, we return null.
2165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, &null);
2167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check that the object is a JS object but take special care of JS
2169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // functions to make sure they have 'Function' as their class.
2170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, eax);  // Map is now in eax.
2171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, &null);
2172f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // As long as JS_FUNCTION_TYPE is the last instance type and it is
2174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
2175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // LAST_JS_OBJECT_TYPE.
2176f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
2177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
2178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(ebx, JS_FUNCTION_TYPE);
2179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &function);
2180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the constructor in the map is a function.
2182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, Map::kConstructorOffset));
2183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &non_function_constructor);
2185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // eax now contains the constructor function. Grab the
2187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // instance class name from there.
2188f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
2189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset));
2190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2191f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2192f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Functions have class 'Function'.
2193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&function);
2194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Factory::function_class_symbol());
2195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Objects with a non-function constructor have class 'Object'.
2198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&non_function_constructor);
2199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Factory::Object_symbol());
2200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-JS objects have class null.
2203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&null);
2204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Factory::null_value());
2205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // All done.
2207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
2214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Conditionally generate a log call.
2215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Args:
2216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   0 (literal string): The type of logging (corresponds to the flags).
2217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     This is used to determine whether or not to generate the log call.
2218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   1 (string): Format string.  Access the string at argument index 2
2219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     with '%2s' (see Logger::LogRuntime for all the formats).
2220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   2 (array): Arguments to the format string.
2221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 3);
2222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING
2223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
2224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(args->at(1), kStack);
2225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(args->at(2), kStack);
2226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLog, 2);
2227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif
2229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Finally, we're expected to leave a value on the top of the stack.
2230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Factory::undefined_value());
2231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
2236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label slow_allocate_heapnumber;
2239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label heapnumber_allocated;
2240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber);
2242f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&heapnumber_allocated);
2243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&slow_allocate_heapnumber);
2245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // To allocate a heap number, and ensure that it is not a smi, we
2246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // call the runtime function FUnaryMinus on 0, returning the double
2247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // -0.0.  A new, distinct heap number is returned each time.
2248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(Smi::FromInt(0)));
2249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kNumberUnaryMinus, 1);
2250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edi, eax);
2251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&heapnumber_allocated);
2253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ PrepareCallCFunction(0, ebx);
2255f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallCFunction(ExternalReference::random_uint32_function(), 0);
2256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert 32 random bits in eax to 0.(32 random bits) in a double
2258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // by computing:
2259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
2260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // This is implemented on both SSE2 and FPU.
2261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (CpuFeatures::IsSupported(SSE2)) {
2262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CpuFeatures::Scope fscope(SSE2);
2263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(ebx, Immediate(0x49800000));  // 1.0 x 2^20 as single.
2264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movd(xmm1, Operand(ebx));
2265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movd(xmm0, Operand(eax));
2266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ cvtss2sd(xmm1, xmm1);
2267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ pxor(xmm0, xmm1);
2268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ subsd(xmm0, xmm1);
2269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0);
2270f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
2271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0x4130000000000000 is 1.0 x 2^20 as a double.
2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(FieldOperand(edi, HeapNumber::kExponentOffset),
2273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke           Immediate(0x41300000));
2274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), eax);
2275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
2276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), Immediate(0));
2277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
2278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fsubp(1);
2279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fstp_d(FieldOperand(edi, HeapNumber::kValueOffset));
2280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, edi);
2282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
2287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SubStringStub stub;
2289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
2290f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(2), kStack);
2293f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
2299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  RegExpExecStub stub;
2301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 4);
2302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(2), kStack);
2305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(3), kStack);
2306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
2312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);  // Load the object.
2315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
2317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi return the object.
2318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, &done);
2320f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the object.
2321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_VALUE_TYPE, ebx);
2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &done);
2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, JSValue::kValueOffset));
2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
2331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the runtime function.
2332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_pow, 2);
2336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
2341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2343f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);  // Load the object.
2344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kAccumulator);  // Load the value.
2345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(ebx);  // eax = value. ebx = object.
2346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
2348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, return the value.
2349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(ebx, Immediate(kSmiTagMask));
2350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, &done);
2351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the value.
2353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx);
2354f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &done);
2355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Store the value.
2357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax);
2358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the write barrier.  Save the value as it will be
2359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // overwritten by the write barrier code and is needed afterward.
2360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, eax);
2361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ RecordWrite(ebx, JSValue::kValueOffset, edx, ecx);
2362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2368f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
2369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 1);
2370f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
2372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  NumberToStringStub stub;
2375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2376f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
2381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2382f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2383f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2384f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
23867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharFromCodeGenerator generator(eax, ebx);
23877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
2388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
23917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
2392f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2393f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
23947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Apply(context_, ebx);
2395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
23997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
24007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  VisitForValue(args->at(0), kStack);
24027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  VisitForValue(args->at(1), kAccumulator);
24037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = ebx;
24057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = eax;
24067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch = ecx;
24077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = edx;
24087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
24107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
24127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
24137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
24147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharCodeAtGenerator generator(object,
24157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      index,
24167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      scratch,
24177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      result,
24187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
24197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
24207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &index_out_of_range,
24217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      STRING_INDEX_IS_NUMBER);
24227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
24237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
24247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
24267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
24277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // NaN.
24287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Set(result, Immediate(Factory::nan_value()));
24297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
24307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
2432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Move the undefined value into the result register, which will
24337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // trigger conversion.
24347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Set(result, Immediate(Factory::undefined_value()));
24357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
24367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
24387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
24397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
24417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Apply(context_, result);
2442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
24467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
24477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  VisitForValue(args->at(0), kStack);
24497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  VisitForValue(args->at(1), kAccumulator);
24507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = ebx;
24527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = eax;
24537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch1 = ecx;
24547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch2 = edx;
24557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = eax;
24567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
24587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
24607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
24617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
24627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharAtGenerator generator(object,
24637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  index,
24647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  scratch1,
24657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  scratch2,
24667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  result,
24677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
24687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
24697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &index_out_of_range,
24707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  STRING_INDEX_IS_NUMBER);
24717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
24727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
24737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
24757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
24767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the empty string.
24777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Set(result, Immediate(Factory::empty_string()));
24787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
24797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
24817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move smi zero into the result register, which will trigger
24827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // conversion.
24837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Set(result, Immediate(Smi::FromInt(0)));
24847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
24857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
24877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
24887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
24907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Apply(context_, result);
24917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
24927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
2495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringAddStub stub(NO_STRING_ADD_FLAGS);
2501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2505f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
2507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringCompareStub stub;
2513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
2519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
2520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  TranscendentalCacheStub stub(TranscendentalCache::SIN);
2521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
2529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
2530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  TranscendentalCacheStub stub(TranscendentalCache::COS);
2531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the runtime function.
2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_sqrt, 1);
2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
2548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() >= 2);
2549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int arg_count = args->length() - 2;  // For receiver and function.
2551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);  // Receiver.
2552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < arg_count; i++) {
2553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(args->at(i + 1), kStack);
2554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(arg_count + 1), kAccumulator);  // Function.
2556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // InvokeFunction requires function in edi. Move it in there.
2558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!result_register().is(edi)) __ mov(edi, result_register());
2559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ParameterCount count(arg_count);
2560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeFunction(edi, count, CALL_FUNCTION);
2561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
2567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
2568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(2), kStack);
2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kRegExpConstructResult, 3);
2572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
2577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
2578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(2), kStack);
2581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kSwapElements, 3);
2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_NE(NULL, args->at(0)->AsLiteral());
2590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
2591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<FixedArray> jsfunction_result_caches(
2593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Top::global_context()->jsfunction_result_caches());
2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (jsfunction_result_caches->length() <= cache_id) {
2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Abort("Attempt to use undefined cache.");
2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(eax, Factory::undefined_value());
2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Apply(context_, eax);
2598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kAccumulator);
2602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register key = eax;
2604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register cache = ebx;
2605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register tmp = ecx;
2606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(cache, CodeGenerator::ContextOperand(esi, Context::GLOBAL_INDEX));
2607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(cache,
2608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         FieldOperand(cache, GlobalObject::kGlobalContextOffset));
2609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(cache,
2610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         CodeGenerator::ContextOperand(
2611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke             cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
2612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(cache,
2613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
2614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, not_found;
2616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // tmp now holds finger offset as a smi.
2617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
2618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
2619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(key, CodeGenerator::FixedArrayElementOperand(cache, tmp));
2620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &not_found);
2621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, CodeGenerator::FixedArrayElementOperand(cache, tmp, 1));
2623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&not_found);
2626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call runtime to perform the lookup.
2627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(cache);
2628f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(key);
2629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetFromCache, 2);
2630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, eax);
2633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2636d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
2637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<String> name = expr->name();
2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (name->length() > 0 && name->Get(0) == '_') {
2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ InlineRuntimeCall");
2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitInlineRuntimeCall(expr);
2641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ CallRuntime");
26453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* args = expr->arguments();
26463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2647d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
2648d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Prepare for calling JS runtime function.
2649d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ mov(eax, CodeGenerator::GlobalObject());
2650d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
2651d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
26523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
26533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Push the arguments ("left-to-right").
26543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
26553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
2656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
2657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
2660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Call the JS runtime function via a call IC.
2661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ Set(ecx, Immediate(expr->name()));
2662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
2664d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ call(ic, RelocInfo::CODE_TARGET);
2665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Restore context register.
2666d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
2668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call the C runtime function.
2669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(expr->function(), arg_count);
2670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, eax);
2672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2675d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
2677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Token::DELETE: {
2678f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
2679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Property* prop = expr->expression()->AsProperty();
2680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
2681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (prop == NULL && var == NULL) {
2682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Result of deleting non-property, non-variable reference is true.
2683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The subexpression may have side effects.
2684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForEffect(expr->expression());
2685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        Apply(context_, true);
2686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else if (var != NULL &&
2687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 !var->is_global() &&
2688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 var->slot() != NULL &&
2689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 var->slot()->type() != Slot::LOOKUP) {
2690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Result of deleting non-global, non-dynamic variables is false.
2691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The subexpression does not have side effects.
2692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        Apply(context_, false);
2693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else {
2694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Property or variable reference.  Call the delete builtin with
2695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // object and property name as arguments.
2696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (prop != NULL) {
2697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          VisitForValue(prop->obj(), kStack);
2698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          VisitForValue(prop->key(), kStack);
2699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (var->is_global()) {
2700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(CodeGenerator::GlobalObject());
2701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(Immediate(var->name()));
2702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else {
2703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Non-global variable.  Call the runtime to look up the context
2704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // where the variable was introduced.
2705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(context_register());
2706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(Immediate(var->name()));
2707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kLookupContext, 2);
2708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(eax);
2709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(Immediate(var->name()));
2710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
2711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
2712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        Apply(context_, eax);
2713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
2714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
2718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
2719e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
2720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (context_) {
2721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kUninitialized:
2722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
2723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
2724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kEffect:
2725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
2726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kValue:
2727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          switch (location_) {
2728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kAccumulator:
2729e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ mov(result_register(), Factory::undefined_value());
2730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
2731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kStack:
2732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ push(Immediate(Factory::undefined_value()));
2733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
2734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
2735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
2736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kTestValue:
2737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Value is false so it's needed.
2738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          switch (location_) {
2739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kAccumulator:
2740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ mov(result_register(), Factory::undefined_value());
2741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
2742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kStack:
2743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ push(Immediate(Factory::undefined_value()));
2744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
2745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
2746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Fall through.
2747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case Expression::kTest:
2748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kValueTest:
2749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ jmp(false_label_);
2750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
2751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
27533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
2754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
2756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label materialize_true, materialize_false;
2758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label* if_true = NULL;
2759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label* if_false = NULL;
2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Notice that the labels are swapped.
2762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true);
2763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForControl(expr->expression(), if_true, if_false);
2765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Apply(context_, if_false, if_true);  // Labels swapped.
2767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
2771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
2772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      VariableProxy* proxy = expr->expression()->AsVariableProxy();
2773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (proxy != NULL &&
2774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          !proxy->var()->is_this() &&
2775d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          proxy->var()->is_global()) {
2776d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        Comment cmnt(masm_, "Global variable");
2777402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ mov(eax, CodeGenerator::GlobalObject());
2778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ mov(ecx, Immediate(proxy->name()));
2779d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
2780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Use a regular load, not a contextual load, to avoid a reference
2781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // error.
2782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ call(ic, RelocInfo::CODE_TARGET);
2783402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(eax);
2784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else if (proxy != NULL &&
2785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                 proxy->var()->slot() != NULL &&
2786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                 proxy->var()->slot()->type() == Slot::LOOKUP) {
2787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(esi);
2788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(Immediate(proxy->name()));
2789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(eax);
2791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
2792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // This expression cannot throw a reference error at the top level.
2793e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(expr->expression(), kStack);
2794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallRuntime(Runtime::kTypeof, 1);
2797e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Apply(context_, eax);
2798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2801d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Token::ADD: {
2802d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Comment cmt(masm_, "[ UnaryOperation (ADD)");
2803d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      VisitForValue(expr->expression(), kAccumulator);
2804d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Label no_conversion;
2805d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ test(result_register(), Immediate(kSmiTagMask));
2806d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ j(zero, &no_conversion);
2807d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ push(result_register());
2808d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
2809d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ bind(&no_conversion);
2810d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Apply(context_, result_register());
2811d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      break;
2812d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
2813d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
28144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::SUB: {
28154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (SUB)");
28164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      bool overwrite =
28174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          (expr->expression()->AsBinaryOperation() != NULL &&
28184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
28194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      GenericUnaryOpStub stub(Token::SUB, overwrite);
28204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // GenericUnaryOpStub expects the argument to be in the
28214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // accumulator register eax.
28224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      VisitForValue(expr->expression(), kAccumulator);
28234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
28244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Apply(context_, eax);
28254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
28264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
28274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
28284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::BIT_NOT: {
28294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
28304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      bool overwrite =
28314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          (expr->expression()->AsBinaryOperation() != NULL &&
28324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
28334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
28344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // GenericUnaryOpStub expects the argument to be in the
28354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // accumulator register eax.
28364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      VisitForValue(expr->expression(), kAccumulator);
28374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Avoid calling the stub for Smis.
28384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Label smi, done;
28394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ test(result_register(), Immediate(kSmiTagMask));
28404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ j(zero, &smi);
28414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Non-smi: call stub leaving result in accumulator register.
28424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
28434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ jmp(&done);
28444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Perform operation directly on Smis.
28454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ bind(&smi);
28464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ not_(result_register());
28474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ and_(result_register(), ~kSmiTagMask);  // Remove inverted smi-tag.
28484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ bind(&done);
28494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Apply(context_, result_register());
28504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
28514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
28524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
2853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
2854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
28553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2859d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
2860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CountOperation");
2861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
2862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // as the left-hand side.
2863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->expression()->IsValidLeftHandSide()) {
2864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->expression());
2865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2868e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Expression can only be a property, a global or a (parameter or local)
2869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
2870e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
2871e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LhsKind assign_type = VARIABLE;
2872e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
2873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In case of a property we use the uninitialized expression context
2874e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // of the key to detect a named property.
2875e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (prop != NULL) {
2876e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    assign_type =
2877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
2878e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2879e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2880e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
2881e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
2882e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
2883e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Location saved_location = location_;
2884d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    location_ = kAccumulator;
2885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
2886e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     Expression::kValue);
2887e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    location_ = saved_location;
2888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
2889e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
2890e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (expr->is_postfix() && context_ != Expression::kEffect) {
2891e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ push(Immediate(Smi::FromInt(0)));
2892e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2893e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (assign_type == NAMED_PROPERTY) {
2894402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Put the object both on the stack and in the accumulator.
2895402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      VisitForValue(prop->obj(), kAccumulator);
2896402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ push(eax);
2897e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitNamedPropertyLoad(prop);
2898e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
2899402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      VisitForValue(prop->obj(), kStack);
2900402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      VisitForValue(prop->key(), kAccumulator);
2901402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ mov(edx, Operand(esp, 0));
2902402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ push(eax);
2903e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitKeyedPropertyLoad(prop);
2904e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2905e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2906e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2907d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Call ToNumber only if operand is not a smi.
2908d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label no_conversion;
2909d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2910d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ j(zero, &no_conversion);
2911d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ push(eax);
2912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
2913d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&no_conversion);
29143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
2916e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
2917e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    switch (context_) {
2918e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kUninitialized:
2919e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        UNREACHABLE();
2920e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kEffect:
2921e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Do not save result.
2922e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        break;
2923e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kValue:
2924e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kTest:
2925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kValueTest:
2926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kTestValue:
2927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Save the result on the stack. If we have a named or keyed property
2928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // we store the result under the receiver that is currently on top
2929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // of the stack.
2930e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        switch (assign_type) {
2931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          case VARIABLE:
2932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            __ push(eax);
2933e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            break;
2934e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          case NAMED_PROPERTY:
2935e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            __ mov(Operand(esp, kPointerSize), eax);
2936e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            break;
2937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          case KEYED_PROPERTY:
2938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            __ mov(Operand(esp, 2 * kPointerSize), eax);
2939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            break;
2940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
2941e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        break;
2942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2944e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2945d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Inline smi case if we are in a loop.
2946d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label stub_call, done;
2947d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (loop_depth() > 0) {
2948d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
2949d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ add(Operand(eax), Immediate(Smi::FromInt(1)));
2950d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
2951d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
2952d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
2953d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ j(overflow, &stub_call);
2954d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // We could eliminate this smi check if we split the code at
2955d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // the first smi check before calling ToNumber.
2956d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ test(eax, Immediate(kSmiTagMask));
2957d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ j(zero, &done);
2958d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ bind(&stub_call);
2959d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Call stub. Undo operation first.
2960d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
2961d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
2962d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
2963d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ add(Operand(eax), Immediate(Smi::FromInt(1)));
2964d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
2965d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
2966e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call stub for +1/-1.
2967e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  GenericBinaryOpStub stub(expr->binary_op(),
2968e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_OVERWRITE,
29696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           NO_GENERIC_BINARY_FLAGS,
29706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           TypeInfo::Unknown());
2971d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  stub.GenerateCall(masm(), eax, Smi::FromInt(1));
2972d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
2973d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2974e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in eax.
2975e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
2976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case VARIABLE:
2977e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
2978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
2979e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
2980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               Token::ASSIGN,
2981e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               Expression::kEffect);
2982e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // For all contexts except kEffect: We have the result on
2983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
2984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (context_ != Expression::kEffect) {
2985e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          ApplyTOS(context_);
2986e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
2987e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
2988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
2989e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
2990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               Token::ASSIGN,
2991e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               context_);
2992e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
2993d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2994e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
2995e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(ecx, prop->key()->AsLiteral()->handle());
29964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ pop(edx);
2997e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
2998e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ call(ic, RelocInfo::CODE_TARGET);
2999e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // This nop signals to the IC that there is no inlined code at the call
3000e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // site for it to patch.
3001e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ nop();
3002e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
3003e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (context_ != Expression::kEffect) {
3004e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          ApplyTOS(context_);
3005e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3006e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
30074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        Apply(context_, eax);
3008e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3009d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3010d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3011e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
30126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ pop(ecx);
30136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ pop(edx);
3014e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
3015e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ call(ic, RelocInfo::CODE_TARGET);
3016e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // This nop signals to the IC that there is no inlined code at the call
3017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // site for it to patch.
3018e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ nop();
3019e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
30206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // Result is on the stack
3021e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (context_ != Expression::kEffect) {
3022e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          ApplyTOS(context_);
3023e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3024e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
30256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Apply(context_, eax);
3026e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3027d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3028d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
30293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
30303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
30313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
30323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3033d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
3034d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ BinaryOperation");
3035d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
3036d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::COMMA:
3037e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->left());
3038d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Visit(expr->right());
3039d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3040d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3041d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::OR:
3042d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::AND:
3043d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      EmitLogicalOperation(expr);
3044d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3045d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3046d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::ADD:
3047d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::SUB:
3048d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::DIV:
3049d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::MOD:
3050d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::MUL:
3051d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::BIT_OR:
3052d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::BIT_AND:
3053d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::BIT_XOR:
3054d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::SHL:
3055d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::SHR:
3056e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::SAR:
3057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->left(), kStack);
3058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kAccumulator);
3059e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitBinaryOp(expr->op(), context_);
3060d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3061e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3062d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
3063d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
3064d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3065d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
30663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
30673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNullCompare(bool strict,
3069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Register obj,
3070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Register null_const,
3071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Label* if_true,
3072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Label* if_false,
3073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Register scratch) {
3074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(obj, Operand(null_const));
3075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (strict) {
3076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
3077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
3078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
3079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ cmp(obj, Factory::undefined_value());
3080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
3081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ test(obj, Immediate(kSmiTagMask));
3082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(zero, if_false);
3083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // It can be an undetectable object.
3084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(scratch, FieldOperand(obj, HeapObject::kMapOffset));
3085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
3086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ test(scratch, Immediate(1 << Map::kIsUndetectable));
3087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(not_zero, if_true);
3088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
3090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3093d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
3094d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
3095e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3096e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
3097e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
3098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
3102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
3103d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  VisitForValue(expr->left(), kStack);
3105d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
3106e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
3107e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kStack);
3108d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
3109d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ cmp(eax, Factory::true_value());
3110e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(equal, if_true);
3111e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
3112d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
31133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3114d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
3115e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kStack);
3116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      InstanceofStub stub;
3117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
3118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ test(eax, Operand(eax));
3119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(zero, if_true);  // The stub returns 0 for true.
3120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
3121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
3125e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kAccumulator);
3126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Condition cc = no_condition;
3127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      bool strict = false;
3128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (expr->op()) {
3129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::EQ_STRICT:
3130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          strict = true;
3131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Fall through
3132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case Token::EQ: {
3133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = equal;
3134d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(edx);
3135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // If either operand is constant null we do a fast compare
3136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // against null.
3137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          Literal* right_literal = expr->right()->AsLiteral();
3138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          Literal* left_literal = expr->left()->AsLiteral();
3139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (right_literal != NULL && right_literal->handle()->IsNull()) {
3140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            EmitNullCompare(strict, edx, eax, if_true, if_false, ecx);
3141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Apply(context_, if_true, if_false);
3142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            return;
3143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          } else if (left_literal != NULL && left_literal->handle()->IsNull()) {
3144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            EmitNullCompare(strict, eax, edx, if_true, if_false, ecx);
3145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Apply(context_, if_true, if_false);
3146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            return;
3147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          }
3148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
3150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LT:
3151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
3152d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(edx);
3153d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3154d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GT:
3155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Reverse left and right sizes to obtain ECMA-262 conversion order.
3156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
3157e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(edx, result_register());
3158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(eax);
3159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block         break;
3160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LTE:
3161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Reverse left and right sizes to obtain ECMA-262 conversion order.
3162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
3163e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(edx, result_register());
3164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(eax);
3165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GTE:
3167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
3168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(edx);
3169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::IN:
3171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::INSTANCEOF:
3172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default:
3173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
3174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
3175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // The comparison stub expects the smi vs. smi case to be handled
3177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // before it is called.
3178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Label slow_case;
3179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ mov(ecx, Operand(edx));
3180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ or_(ecx, Operand(eax));
3181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ test(ecx, Immediate(kSmiTagMask));
3182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ j(not_zero, &slow_case, not_taken);
3183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ cmp(edx, Operand(eax));
3184e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(cc, if_true);
3185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
3186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ bind(&slow_case);
3188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      CompareStub stub(cc, strict);
3189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
3190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ test(eax, Operand(eax));
3191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(cc, if_true);
3192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
3193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
31943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
31953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
3197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
3198e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, if_true, if_false);
3199e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3202d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
3203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
3204e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, eax);
3205e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3208d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::result_register() { return eax; }
3209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3211d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::context_register() { return esi; }
3212e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3213e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3214d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
3215e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
3216e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(Operand(ebp, frame_offset), value);
32173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
32183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
32193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3220d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
3221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(dst, CodeGenerator::ContextOperand(esi, context_index));
3222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3225e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ----------------------------------------------------------------------------
3226e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support.
3227e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3228d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() {
3229e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Cook return address on top of stack (smi encoded Code* delta)
3230e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(edx));
3231e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(edx, Operand(esp, 0));
3232e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ sub(Operand(edx), Immediate(masm_->CodeObject()));
3233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
3234e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, kSmiTag);
3235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(edx, Operand(edx));  // Convert to smi.
3236e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(Operand(esp, 0), edx);
3237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store result register while executing finally block.
3238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
3239e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3241e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3242d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() {
3243e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(edx));
3244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Restore result register from stack.
3245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(result_register());
3246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Uncook return address.
3247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(edx, Operand(esp, 0));
3248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ sar(edx, 1);  // Convert smi to int.
3249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(Operand(edx), Immediate(masm_->CodeObject()));
3250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(Operand(esp, 0), edx);
3251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // And return.
3252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ret(0);
3253e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef __
3257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
32583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} }  // namespace v8::internal
3259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
3261