full-codegen-x64.cc revision bb769b257e753aafcbd96767abb2abc645eaa20c
14515c472dc3e5ed2448a564600976759e569a0a8Leon 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_X64)
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "codegen-inl.h"
33d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h"
343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "debug.h"
35d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "full-codegen.h"
363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "parser.h"
376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "scopes.h"
383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 {
403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal {
413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_)
433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function.  On entry to the function the receiver
453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, 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 rdi: the JS function object being called (ie, ourselves)
513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rsi: our context
523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rbp: our caller's frame pointer
533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rsp: stack pointer (pointing to return address)
543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame.  Please see JavaScriptFrameConstants in
563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-x64.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(rbp);  // Caller's frame pointer.
654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ movq(rbp, rsp);
664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ push(rsi);  // Callee's context.
674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ push(rdi);  // 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        __ PushRoot(Heap::kUndefinedValueRootIndex);
734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      } else if (locals_count > 1) {
744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        for (int i = 0; i < locals_count; i++) {
764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ push(rdx);
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 rdi.
884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ push(rdi);
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 rax and rsi.  It replaces the context
974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // passed to us.  It's saved in the stack and kept live in rsi.
984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
1004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Copy any necessary parameters into the context.
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          __ movq(rax, Operand(rbp, parameter_offset));
1094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // Store it in the context.
1104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          int context_offset = Context::SlotOffset(slot->index());
1114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(Operand(rsi, context_offset), rax);
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 rsi.
1154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(rcx, rsi);
1164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ RecordWrite(rcx, context_offset, rax, rbx);
1174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        }
118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // Possibly allocate an arguments object.
1223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    Variable* arguments = scope()->arguments()->AsVariable();
1234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (arguments != NULL) {
1244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Arguments object must be allocated after the context object, in
1254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // case the "arguments" or ".arguments" variables are in the context.
1264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmnt(masm_, "[ Allocate arguments object");
1274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      if (function_in_register) {
1284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        __ push(rdi);
1294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      } else {
1304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      }
1324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // The receiver is just before the parameters on the caller's stack.
1333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int offset = scope()->num_parameters() * kPointerSize;
1343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      __ lea(rdx,
1353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu             Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
1364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ push(rdx);
1373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      __ Push(Smi::FromInt(scope()->num_parameters()));
1384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Arguments to ArgumentsAccessStub:
1394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      //   function, receiver address, parameter count.
1404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // The stub will rewrite receiver and parameter count if the previous
1414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // stack frame was an arguments adapter frame.
1424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
1434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
1444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Store new arguments object in both "arguments" and ".arguments" slots.
1454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ movq(rcx, rax);
1464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Move(arguments->slot(), rax, rbx, rdx);
1474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Slot* dot_arguments_slot =
1483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          scope()->arguments_shadow()->AsVariable()->slot();
1494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Move(dot_arguments_slot, rcx, rbx, rdx);
150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
152d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
153e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  { Comment cmnt(masm_, "[ Declarations");
154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // For named function expressions, declare the function name as a
155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // constant.
156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (scope()->is_function_scope() && scope()->function() != NULL) {
157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      EmitDeclaration(scope()->function(), Variable::CONST, NULL);
158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Visit all the explicit declarations unless there is an illegal
160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // redeclaration.
161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (scope()->HasIllegalRedeclaration()) {
162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      scope()->VisitIllegalRedeclaration(this);
163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitDeclarations(scope()->declarations());
165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
166e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
167e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ Stack check");
1693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label ok;
1703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
1713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(above_equal, &ok);
1723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    StackCheckStub stub;
1733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CallStub(&stub);
1743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&ok);
1753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (FLAG_trace) {
1783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CallRuntime(Runtime::kTraceEnter, 0);
1793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ Body");
182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    VisitStatements(function()->body());
184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit a 'return undefined' in case control fell off the end of the body.
1893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    EmitReturnSequence();
191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() {
196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ jmp(&return_label_);
199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
2013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
2023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(rax);
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
210bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
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    __ movq(rsp, rbp);
2153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ pop(rbp);
2163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    __ ret((scope()->num_parameters() + 1) * kPointerSize);
2173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT
2183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Add padding that will be overwritten by a debugger breakpoint.  We
2193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7
2203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // (3 + 1 + 3).
221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    const int kPadding = Assembler::kJSReturnSequenceLength - 7;
2223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    for (int i = 0; i < kPadding; ++i) {
2233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      masm_->int3();
2243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Check that the size of the code used for returning matches what is
226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // expected by the debugger.
227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_EQ(Assembler::kJSReturnSequenceLength,
228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
2293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#endif
2303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
2323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
234d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Register reg) {
235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Nothing to do.
241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValue:
244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Move value into place.
245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (!reg.is(result_register())) __ movq(result_register(), reg);
248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(reg);
251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTest:
256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // For simplicity we always test the accumulator register.
257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!reg.is(result_register())) __ movq(result_register(), reg);
258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!reg.is(result_register())) __ movq(result_register(), reg);
264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
277d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Slot* slot) {
278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Nothing to do.
283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue: {
285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      MemOperand slot_operand = EmitSlotSearch(slot, result_register());
286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(result_register(), slot_operand);
289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Memory operands can be pushed directly.
292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(slot_operand);
293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Move(result_register(), slot);
300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Move(result_register(), slot);
306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
319d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Literal* lit) {
320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Nothing to do.
325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Move(result_register(), lit->handle());
330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Push(lit->handle());
333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
335e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
337e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
338e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Move(result_register(), lit->handle());
339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Move(result_register(), lit->handle());
345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
358d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ApplyTOS(Expression::Context context) {
359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
360d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
361d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
372e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ pop(result_register());
379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTestValue:
384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(result_register(), Operand(rsp, 0));
390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
398d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DropAndApply(int count,
399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     Expression::Context context,
400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     Register reg) {
401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(count > 0);
402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!reg.is(rsp));
403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
405d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(count);
409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValue:
412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Drop(count);
415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (!reg.is(result_register())) __ movq(result_register(), reg);
416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (count > 1) __ Drop(count - 1);
419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(Operand(rsp, 0), reg);
420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
424e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(count);
426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!reg.is(result_register())) __ movq(result_register(), reg);
427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTestValue:
432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Drop(count);
435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (!reg.is(result_register())) __ movq(result_register(), reg);
436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (count > 1) __ Drop(count - 1);
439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(result_register(), reg);
440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(Operand(rsp, 0), result_register());
441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::PrepareTest(Label* materialize_true,
450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                    Label* materialize_false,
451f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                    Label** if_true,
452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                    Label** if_false) {
453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (context_) {
454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kUninitialized:
455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      UNREACHABLE();
456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kEffect:
458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // In an effect context, the true and the false case branch to the
459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // same label.
460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_true = *if_false = materialize_true;
461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kValue:
463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_true = materialize_true;
464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_false = materialize_false;
465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kTest:
467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_true = true_label_;
468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_false = false_label_;
469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kValueTest:
471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_true = materialize_true;
472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_false = false_label_;
473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kTestValue:
475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_true = true_label_;
476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      *if_false = materialize_false;
477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
482d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context,
483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                              Label* materialize_true,
484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                              Label* materialize_false) {
485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT_EQ(materialize_true, materialize_false);
490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(materialize_true);
491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue: {
494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Label done;
495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_true);
498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Move(result_register(), Factory::true_value());
499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(&done);
500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_false);
501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Move(result_register(), Factory::false_value());
502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
504e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_true);
505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Push(Factory::true_value());
506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(&done);
507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_false);
508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Push(Factory::false_value());
509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(&done);
512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(materialize_true);
520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
521e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Move(result_register(), Factory::true_value());
523e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
524e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
525e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Push(Factory::true_value());
526e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(true_label_);
529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(materialize_false);
533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Move(result_register(), Factory::false_value());
536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Push(Factory::false_value());
539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
541e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(false_label_);
542e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
546d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// Convert constant control flow (true or false) to the result expected for
548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// a given expression context.
549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, bool flag) {
550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (context) {
551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kUninitialized:
552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      UNREACHABLE();
553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kEffect:
555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kValue: {
557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Heap::RootListIndex value_root_index =
558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      switch (location_) {
560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kAccumulator:
561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ LoadRoot(result_register(), value_root_index);
562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kStack:
564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ PushRoot(value_root_index);
565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kTest:
570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ jmp(flag ? true_label_ : false_label_);
571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kTestValue:
573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      switch (location_) {
574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kAccumulator:
575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // If value is false it's needed.
576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (!flag) __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kStack:
579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // If value is false it's needed.
580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (!flag) __ PushRoot(Heap::kFalseValueRootIndex);
581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ jmp(flag ? true_label_ : false_label_);
584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Expression::kValueTest:
586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      switch (location_) {
587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kAccumulator:
588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // If value is true it's needed.
589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (flag) __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case kStack:
592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // If value is true it's needed.
593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (flag) __ PushRoot(Heap::kTrueValueRootIndex);
594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          break;
595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ jmp(flag ? true_label_ : false_label_);
597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
602d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DoTest(Expression::Context context) {
603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // The value to test is in the accumulator.  If the value might be needed
604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // on the stack (value/test and test/value contexts with a stack location
605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // desired), then the value is already duplicated on the stack.
606e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_NE(NULL, true_label_);
607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_NE(NULL, false_label_);
608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In value/test and test/value expression contexts with stack as the
610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // desired location, there is already an extra value on the stack.  Use a
611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // label to discard it if unneeded.
612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label discard;
613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label* if_true = true_label_;
614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label* if_false = false_label_;
615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_false = &discard;
628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_true = &discard;
637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
638e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the inlined tests assumed by the stub.
643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex);
644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_true);
647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CompareRoot(result_register(), Heap::kFalseValueRootIndex);
648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, kSmiTag);
650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ SmiCompare(result_register(), Smi::FromInt(0));
651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Condition is_smi = masm_->CheckSmi(result_register());
653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(is_smi, if_true);
654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save a copy of the value if it may be needed and isn't already saved.
656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValue:
660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
665e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
666e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
672e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
677e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call the ToBoolean stub for all other cases.
684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ToBooleanStub stub;
685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
686e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ testq(rax, rax);
688e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // The stub returns nonzero for true.  Complete based on the context.
690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
693e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
694e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTest:
697e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(not_zero, true_label_);
698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(false_label_);
699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
700e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
701e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
702e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
704e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(zero, &discard);
705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
706e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(true_label_);
707e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
708e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
709e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(not_zero, true_label_);
710e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ bind(&discard);
713e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ jmp(false_label_);
715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
719e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(not_zero, &discard);
721e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
722e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(false_label_);
723e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(zero, false_label_);
726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ bind(&discard);
729e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ jmp(true_label_);
731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
736d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
737e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (slot->type()) {
738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::PARAMETER:
739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOCAL:
740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return Operand(rbp, SlotOffset(slot));
741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::CONTEXT: {
742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      int context_chain_length =
7433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          scope()->ContextChainLength(slot->var()->scope());
744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ LoadContext(scratch, context_chain_length);
745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return CodeGenerator::ContextOperand(scratch, slot->index());
746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOOKUP:
748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  UNREACHABLE();
751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return Operand(rax, 0);
752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
755d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) {
756e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(source, destination);
757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(destination, location);
758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
761d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst,
762e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register src,
763e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch1,
764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch2) {
765e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(dst->type() != Slot::LOOKUP);  // Not yet implemented.
766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!scratch1.is(src) && !scratch2.is(src));
767e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(dst, scratch1);
768e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(location, src);
769e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
770e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (dst->type() == Slot::CONTEXT) {
771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
772e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ RecordWrite(scratch1, offset, src, scratch2);
773e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
775d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
776d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitDeclaration(Variable* variable,
778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Variable::Mode mode,
779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        FunctionLiteral* function) {
780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Declaration");
781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(variable != NULL);  // Must have been resolved.
782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Slot* slot = variable->slot();
783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = variable->AsProperty();
784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (slot != NULL) {
786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
787e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOCAL:
789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
791e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister);
792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          VisitForValue(function, kAccumulator);
794e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(Operand(rbp, SlotOffset(slot)), result_register());
795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT:
799e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // We bypass the general EmitSlotSearch because we know more about
800e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // this specific context.
801e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // The variable in the decl always resides in the current context.
803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (FLAG_debug_code) {
805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Check if we have the correct context pointer.
806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ movq(rbx,
807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                  CodeGenerator::ContextOperand(rsi, Context::FCONTEXT_INDEX));
808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ cmpq(rbx, rsi);
809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Check(equal, "Unexpected declaration in current context.");
810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ movq(CodeGenerator::ContextOperand(rsi, slot->index()),
814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                  kScratchRegister);
815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // No write barrier since the hole value is in old space.
816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          VisitForValue(function, kAccumulator);
818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(CodeGenerator::ContextOperand(rsi, slot->index()),
819e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                  result_register());
820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          int offset = Context::SlotOffset(slot->index());
8214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(rbx, rsi);
8224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ RecordWrite(rbx, offset, result_register(), rcx);
823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP: {
827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(rsi);
828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ Push(variable->name());
829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Declaration nodes are always introduced in one of two modes.
830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ASSERT(mode == Variable::VAR || mode == Variable::CONST);
831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY;
832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Push(Smi::FromInt(attr));
833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Push initial value, if any.
834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Note: For variables we must not push an initial value (such as
835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // 'undefined') because we may have a (legal) redeclaration and we
836d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // must not destroy the current value.
837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ PushRoot(Heap::kTheHoleValueRootIndex);
839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          VisitForValue(function, kStack);
841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else {
842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Push(Smi::FromInt(0));  // no initial value!
843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDeclareContextSlot, 4);
845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (prop != NULL) {
850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (function != NULL || mode == Variable::CONST) {
851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // We are declaring a function or constant that rewrites to a
852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // property.  Use (keyed) IC to set the initial value.
853e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->obj(), kStack);
854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (function != NULL) {
855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForValue(prop->key(), kStack);
856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForValue(function, kAccumulator);
857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ pop(rcx);
858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForValue(prop->key(), kAccumulator);
860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ movq(rcx, result_register());
861e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex);
862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(rdx);
864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ call(ic, RelocInfo::CODE_TARGET);
867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Absence of a test rax instruction following the call
868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // indicates that none of the load was inlined.
869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ nop();
870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) {
876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
880d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(rsi);  // The context is the first argument.
8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(pairs);
8843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  __ Push(Smi::FromInt(is_eval() ? 1 : 0));
8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kDeclareGlobals, 3);
8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ SwitchStatement");
892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Breakable nested_statement(this, stmt);
893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Keep the switch value on the stack until a case matches.
895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(stmt->tag(), kStack);
896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<CaseClause*>* clauses = stmt->cases();
898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label next_test;  // Recycled for each test.
901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the tests with branches to their bodies.
902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The default is not a test, but remember it as final fall through.
905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (clause->is_default()) {
906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      default_clause = clause;
907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      continue;
908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case comparison");
911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&next_test);
912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    next_test.Unuse();
913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Compile the label expression.
915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(clause->label(), kAccumulator);
916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Perform the comparison as if via '==='.  The comparison stub expects
918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // the smi vs. smi case to be handled before it is called.
919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Label slow_case;
920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movq(rdx, Operand(rsp, 0));  // Switch value.
921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ JumpIfNotBothSmi(rdx, rax, &slow_case);
922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ SmiCompare(rdx, rax);
923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(not_equal, &next_test);
924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(clause->body_target()->entry_label());
926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&slow_case);
928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CompareStub stub(equal, true);
929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ testq(rax, rax);
931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(not_equal, &next_test);
932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(clause->body_target()->entry_label());
934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Discard the test value and jump to the default if present, otherwise to
937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the end of the statement.
938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&next_test);
939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(1);  // Switch value is no longer needed.
940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (default_clause == NULL) {
941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(nested_statement.break_target());
942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(default_clause->body_target()->entry_label());
944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the case bodies.
947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case body");
949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(clause->body_target()->entry_label());
951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitStatements(clause->statements());
952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(nested_statement.break_target());
955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ ForInStatement");
960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label loop, exit;
963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ForIn loop_statement(this, stmt);
964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  increment_loop_depth();
965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the object to enumerate over. Both SpiderMonkey and JSC
967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ignore null and undefined in contrast to the specification; see
968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ECMA-262 section 12.6.4.
969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(stmt->enumerable(), kAccumulator);
970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareRoot(rax, Heap::kNullValueRootIndex);
973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the object to a JS object.
976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label convert, done_convert;
977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, &convert);
978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx);
979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(above_equal, &done_convert);
980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&convert);
981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);
982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done_convert);
984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);
985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
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(rax);  // 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  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
1001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 Heap::kMetaMapRootIndex);
1002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &fixed_array);
1003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a map in register rax. Get the enumeration cache from it.
1005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rcx, FieldOperand(rax, Map::kInstanceDescriptorsOffset));
1006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset));
1007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Setup the four remaining stack slots.
1010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);  // Map.
1011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rdx);  // Enumeration cache.
1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset));
1013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);  // Enumeration cache length (as smi).
1014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(Smi::FromInt(0));  // Initial index.
1015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
1016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a fixed array in register rax. Iterate through that.
1018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&fixed_array);
1019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(Smi::FromInt(0));  // Map (0) - force slow check.
1020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);
1021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset));
1022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);  // Fixed array length (as smi).
1023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(Smi::FromInt(0));  // Initial index.
1024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for doing the condition check.
1026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&loop);
1027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, Operand(rsp, 0 * kPointerSize));  // Get the current index.
1028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(rax, Operand(rsp, 1 * kPointerSize));  // Compare to the array length.
1029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(above_equal, loop_statement.break_target());
1030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the current entry of the array into register rbx.
1032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, Operand(rsp, 2 * kPointerSize));
1033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SmiIndex index = __ SmiToIndex(rax, rax, kPointerSizeLog2);
1034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, FieldOperand(rbx,
1035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.reg,
1036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.scale,
1037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            FixedArray::kHeaderSize));
1038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the expected map from the stack or a zero map in the
1040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // permanent slow case into register rdx.
1041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rdx, Operand(rsp, 3 * kPointerSize));
1042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the expected map still matches that of the enumerable.
1044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If not, we have to filter the key.
1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label update_each;
1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rcx, Operand(rsp, 4 * kPointerSize));
1047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset));
1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &update_each);
1049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the entry to a string or null if it isn't a property
1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // anymore. If the property has been removed while iterating, we
1052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // just skip it.
1053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rcx);  // Enumerable.
1054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rbx);  // Current entry.
1055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareRoot(rax, Heap::kNullValueRootIndex);
1057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, loop_statement.continue_target());
1058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, rax);
1059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the 'each' property or variable from the possibly filtered
1061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // entry in register rbx.
1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&update_each);
1063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(result_register(), rbx);
1064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Perform the assignment as if via '='.
1065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  EmitAssignment(stmt->each());
1066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the body of the loop.
1068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label stack_limit_hit, stack_check_done;
1069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Visit(stmt->body());
1070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ StackLimitCheck(&stack_limit_hit);
1072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&stack_check_done);
1073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for going to the next element by incrementing the
1075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // index (smi) stored on top of the stack.
1076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(loop_statement.continue_target());
1077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1));
1078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
1079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Slow case for the stack limit check.
1081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StackCheckStub stack_check_stub;
1082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&stack_limit_hit);
1083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stack_check_stub);
1084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&stack_check_done);
1085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Remove the pointers stored on the stack.
1087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(loop_statement.break_target());
1088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ addq(rsp, Immediate(5 * kPointerSize));
1089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Exit and decrement the loop depth.
1091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
1092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  decrement_loop_depth();
1093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
10943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
1097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Use the fast case closure allocation code that allocates in new
1098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // space for nested functions that don't need literals cloning.
1099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (scope()->is_function_scope() && info->num_literals() == 0) {
1100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    FastNewClosureStub stub;
1101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Push(info);
1102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
1103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(rsi);
1105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Push(info);
1106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kNewClosure, 2);
1107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, rax);
11093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1112d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
11133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ VariableProxy");
1114e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  EmitVariableLoad(expr->var(), context_);
1115e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1116e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1117e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1118d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableLoad(Variable* var,
1119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Expression::Context context) {
1120d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Four cases: non-this global variables, lookup slots, all other
1121d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // types of slots, and parameters that rewrite to explicit property
1122d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // accesses on the arguments object.
1123d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Slot* slot = var->slot();
1124d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Property* property = var->AsProperty();
1125d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1126d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (var->is_global() && !var->is_this()) {
11273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Comment cmnt(masm_, "Global variable");
11283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Use inline caching. Variable name is passed in rcx and the global
11293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // object on the stack.
1130e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ Move(rcx, var->name());
11317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ movq(rax, CodeGenerator::GlobalObject());
11323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
11333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
11343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // A test rax instruction following the call is used by the IC to
11353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // indicate that the inobject property case was inlined.  Ensure there
11363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is no test rax instruction here.
1137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ nop();
11387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Apply(context, rax);
1139d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1140d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
1141d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Lookup slot");
1142d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ push(rsi);  // Context.
1143d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ Push(var->name());
1144d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
1145d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Apply(context, rax);
1146d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1147d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL) {
1148d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1149d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            ? "Context slot"
1150d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            : "Stack slot");
1151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (var->mode() == Variable::CONST) {
1152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Constants may be the hole value if they have not been initialized.
1153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Unhole them.
1154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label done;
1155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      MemOperand slot_operand = EmitSlotSearch(slot, rax);
1156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ movq(rax, slot_operand);
1157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ j(not_equal, &done);
1159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ bind(&done);
1161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Apply(context, rax);
1162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
1163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Apply(context, slot);
1164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1165d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1167d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Rewritten parameter");
1168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(property);
1169d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Rewritten parameter accesses are of the form "slot[literal]".
1170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the object is in a slot.
1172e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT_NOT_NULL(object_var);
1174e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Slot* object_slot = object_var->slot();
1175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(object_slot);
1176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the object.
1178e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    MemOperand object_loc = EmitSlotSearch(object_slot, rax);
11797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ movq(rdx, object_loc);
1180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1181e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the key is a smi.
1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key_literal = property->key()->AsLiteral();
1183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(key_literal);
1184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(key_literal->handle()->IsSmi());
1185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the key.
11877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ Move(rax, key_literal->handle());
1188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Do a keyed property load.
1190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ call(ic, RelocInfo::CODE_TARGET);
1192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Notice: We must not have a "test rax, ..." instruction after the
1193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // call. It is treated specially by the LoadIC code.
1194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ nop();
11957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Apply(context, rax);
11963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1200d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ RegExpLiteral");
1202bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label materialized;
12033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Registers will be used as follows:
12043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // rdi = JS function.
1205bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // rcx = literals array.
1206bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // rbx = regexp literal.
1207bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // rax = regexp literal clone.
12083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1209bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
12103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int literal_offset =
12113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1212bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(rbx, FieldOperand(rcx, literal_offset));
1213bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
1214bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(not_equal, &materialized);
1215bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
12163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Create regexp literal using runtime function
12173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Result will be in rax.
1218bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(rcx);
12193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
12203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(expr->pattern());
12213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(expr->flags());
12223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1223bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(rbx, rax);
1224bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1225bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&materialized);
1226bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1227bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label allocated, runtime_allocate;
1228bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
1229bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ jmp(&allocated);
1230bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1231bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&runtime_allocate);
1232bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(rbx);
1233bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ Push(Smi::FromInt(size));
1234bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1235bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(rbx);
1236bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1237bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&allocated);
1238bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Copy the content into the newly allocated memory.
1239bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // (Unroll copy loop once for better throughput).
1240bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
1241bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(rdx, FieldOperand(rbx, i));
1242bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(rcx, FieldOperand(rbx, i + kPointerSize));
1243bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(FieldOperand(rax, i), rdx);
1244bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(FieldOperand(rax, i + kPointerSize), rcx);
1245bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1246bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if ((size % (2 * kPointerSize)) != 0) {
1247bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(rdx, FieldOperand(rbx, size - kPointerSize));
1248bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(FieldOperand(rax, size - kPointerSize), rdx);
1249bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, rax);
1251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1254d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
1256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
1258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
1259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Push(expr->constant_properties());
12606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(Smi::FromInt(expr->fast_elements() ? 1 : 0));
1261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->depth() > 1) {
12626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
12633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
12646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
1265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
1268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in rax.
1269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
1270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < expr->properties()->length(); i++) {
1272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectLiteral::Property* property = expr->properties()->at(i);
1273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
1274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = property->key();
1276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
1277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
1278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ push(rax);  // Save result on the stack
1279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
1280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
1282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::CONSTANT:
1283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        UNREACHABLE();
1284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
1288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (key->handle()->IsSymbol()) {
1289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          VisitForValue(value, kAccumulator);
1290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Move(rcx, key->handle());
12914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(rdx, Operand(rsp, 0));
1292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ call(ic, RelocInfo::CODE_TARGET);
1294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ nop();
1295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::PROTOTYPE:
1299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(rsp, 0));  // Duplicate receiver.
1300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(key, kStack);
1301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(value, kStack);
1302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kSetProperty, 3);
1303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::SETTER:
1305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::GETTER:
1306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(rsp, 0));  // Duplicate receiver.
1307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(key, kStack);
1308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Push(property->kind() == ObjectLiteral::Property::SETTER ?
1309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                Smi::FromInt(1) :
1310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                Smi::FromInt(0));
1311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(value, kStack);
1312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDefineAccessor, 4);
1313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
1318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ApplyTOS(context_);
1319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
1320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Apply(context_, rax);
13213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
13233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1325d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
13263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
1327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<Expression*>* subexprs = expr->values();
1329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int length = subexprs->length();
1330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
13313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
13333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
1334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Push(expr->constant_elements());
13353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (expr->depth() > 1) {
1336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
1337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (length > FastCloneShallowArrayStub::kMaximumLength) {
1338e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
1339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    FastCloneShallowArrayStub stub(length);
1341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
13423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
13453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
13473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
1348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < length; i++) {
13493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Expression* subexpr = subexprs->at(i);
13503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
13513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
13523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (subexpr->AsLiteral() != NULL ||
13533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        CompileTimeValue::IsCompileTimeValue(subexpr)) {
13543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      continue;
13553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
13563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
13583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(rax);
13593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
13603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(subexpr, kAccumulator);
13623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Store the subexpression value in the array's elements.
13643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(rbx, Operand(rsp, 0));  // Copy of array literal.
13653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
13663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ movq(FieldOperand(rbx, offset), result_register());
13683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Update the write barrier for the array store.
1370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ RecordWrite(rbx, offset, result_register(), rcx);
13713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
1374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ApplyTOS(context_);
1375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
1376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Apply(context_, rax);
13773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
13793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Comment cmnt(masm_, "[ Assignment");
1383f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1384f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // on the left-hand side.
1385f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->target()->IsValidLeftHandSide()) {
1386f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->target());
1387f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1390402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Left-hand side can only be a property, a global or a (parameter or local)
1391402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1392402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LhsKind assign_type = VARIABLE;
1394402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Property* prop = expr->target()->AsProperty();
1395402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (prop != NULL) {
1396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    assign_type =
1397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
1398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate LHS expression.
1401402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1403402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Nothing to do here.
1404402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1405402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1406402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1407402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // We need the receiver both on the stack and in the accumulator.
1408402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        VisitForValue(prop->obj(), kAccumulator);
1409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
1411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        VisitForValue(prop->obj(), kStack);
1412402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1413402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1414402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (expr->is_compound()) {
1416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForValue(prop->obj(), kStack);
1417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForValue(prop->key(), kAccumulator);
1418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ movq(rdx, Operand(rsp, 0));
1419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(rax);
1420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else {
1421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForValue(prop->obj(), kStack);
1422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForValue(prop->key(), kStack);
1423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
1424402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1425402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1426402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1427402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // If we have a compound assignment: Get value of LHS expression and
1428402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // store in on top of the stack.
1429402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
1430402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Location saved_location = location_;
1431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = kStack;
1432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    switch (assign_type) {
1433402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      case VARIABLE:
1434402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        EmitVariableLoad(expr->target()->AsVariableProxy()->var(),
1435402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                         Expression::kValue);
1436402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        break;
1437402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      case NAMED_PROPERTY:
1438402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        EmitNamedPropertyLoad(prop);
1439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1440402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        break;
1441402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      case KEYED_PROPERTY:
1442402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        EmitKeyedPropertyLoad(prop);
1443402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        break;
1445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = saved_location;
1447402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate RHS expression.
1450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Expression* rhs = expr->value();
1451402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  VisitForValue(rhs, kAccumulator);
1452402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // If we have a compound assignment: Apply operator.
1454402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
1455402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Location saved_location = location_;
1456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = kAccumulator;
1457402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    EmitBinaryOp(expr->binary_op(), Expression::kValue);
1458402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = saved_location;
1459402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1461402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Record source position before possible IC call.
1462402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  SetSourcePosition(expr->position());
1463402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1464402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Store the value.
1465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1466402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1467402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                             expr->op(),
1469402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                             context_);
1470402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1471402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1472402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitNamedPropertyAssignment(expr);
1473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1474402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1475402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitKeyedPropertyAssignment(expr);
1476402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1477402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1478402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1480402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1481d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Literal* key = prop->key()->AsLiteral();
1484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, key->handle());
1485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Call(ic, RelocInfo::CODE_TARGET);
1487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ nop();
1488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1491d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Call(ic, RelocInfo::CODE_TARGET);
1495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ nop();
1496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1499d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitBinaryOp(Token::Value op,
1500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     Expression::Context context) {
1501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
1502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  GenericBinaryOpStub stub(op,
1503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_OVERWRITE,
1504e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_GENERIC_BINARY_FLAGS);
1505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
1506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context, rax);
1507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitAssignment(Expression* expr) {
1511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw
1512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ReferenceError' on the left-hand side.
1513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->IsValidLeftHandSide()) {
1514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr);
1515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand side can only be a property, a global or a (parameter or local)
1519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  LhsKind assign_type = VARIABLE;
1522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = expr->AsProperty();
1523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (prop != NULL) {
1524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    assign_type = (prop->key()->IsPropertyName())
1525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ? NAMED_PROPERTY
1526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        : KEYED_PROPERTY;
1527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (assign_type) {
1530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case VARIABLE: {
1531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->AsVariableProxy()->var();
1532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect);
1533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case NAMED_PROPERTY: {
1536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(rax);  // Preserve value.
1537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitForValue(prop->obj(), kAccumulator);
1538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ movq(rdx, rax);
1539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(rax);  // Restore value.
1540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ Move(rcx, prop->key()->AsLiteral()->handle());
1541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ call(ic, RelocInfo::CODE_TARGET);
1543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ nop();  // Signal no inlined code.
1544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case KEYED_PROPERTY: {
1547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(rax);  // Preserve value.
1548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitForValue(prop->obj(), kStack);
15498defd9ff6930b4e24729971a61cf7469daf119beSteve Block      VisitForValue(prop->key(), kAccumulator);
15508defd9ff6930b4e24729971a61cf7469daf119beSteve Block      __ movq(rcx, rax);
15518defd9ff6930b4e24729971a61cf7469daf119beSteve Block      __ pop(rdx);
15528defd9ff6930b4e24729971a61cf7469daf119beSteve Block      __ pop(rax);
1553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ call(ic, RelocInfo::CODE_TARGET);
1555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ nop();  // Signal no inlined code.
1556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1562d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var,
1563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                               Token::Value op,
1564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                               Expression::Context context) {
1565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand sides that rewrite to explicit property accesses do not reach
1566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // here.
15673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(var != NULL);
15683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(var->is_global() || var->slot() != NULL);
1569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
15703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (var->is_global()) {
1571d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT(!var->is_this());
1572d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Assignment to a global variable.  Use inline caching for the
1573d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // assignment.  Right-hand-side value is passed in rax, variable name in
1574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // rcx, and the global object on the stack.
15753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(rcx, var->name());
15764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ movq(rdx, CodeGenerator::GlobalObject());
15773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
15783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Call(ic, RelocInfo::CODE_TARGET);
1579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ nop();
1580d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) {
1582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Perform the assignment for non-const variables and for initialization
1583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // of const variables.  Const assignments are simply skipped.
1584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Label done;
1585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Slot* slot = var->slot();
1586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
1587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
1588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      case Slot::LOCAL:
1589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Detect const reinitialization by checking for the hole value.
1591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ movq(rdx, Operand(rbp, SlotOffset(slot)));
1592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ j(not_equal, &done);
1594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment.
1596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ movq(Operand(rbp, SlotOffset(slot)), rax);
1597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT: {
1600e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        MemOperand target = EmitSlotSearch(slot, rcx);
1601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Detect const reinitialization by checking for the hole value.
1603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ movq(rdx, target);
1604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ j(not_equal, &done);
1606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment and issue the write barrier.
1608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ movq(target, rax);
1609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The value of the assignment is in rax.  RecordWrite clobbers its
1610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // register arguments.
1611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ movq(rdx, rax);
1612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
1613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ RecordWrite(rcx, offset, rdx, rbx);
1614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
16153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
1616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP:
1618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Call the runtime for the assignment.  The runtime will ignore
1619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // const reinitialization.
1620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(rax);  // Value.
1621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(rsi);  // Context.
1622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ Push(var->name());
1623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // The runtime will ignore const redeclaration.
1625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else {
1627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kStoreContextSlot, 3);
1628f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
16303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&done);
16323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context, rax);
16353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1638d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
1640d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
1641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop != NULL);
1642d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop->key()->AsLiteral() != NULL);
16433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1644d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1647d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(Operand(rsp, kPointerSize));  // Receiver is now under value.
1650d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Move(rcx, prop->key()->AsLiteral()->handle());
16574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (expr->ends_initialization_block()) {
16584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ movq(rdx, Operand(rsp, 0));
16594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
16604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ pop(rdx);
16614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
1662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1663d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Call(ic, RelocInfo::CODE_TARGET);
1664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ nop();
1665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1666d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(rax);  // Result of assignment, saved even if not needed.
1669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(rsp, kPointerSize));  // Receiver is under value.
1670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(rax);
16724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    DropAndApply(1, context_, rax);
16734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
16744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Apply(context_, rax);
1675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1679d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
1681d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1686e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Receiver is now under the key and value.
1688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(rsp, 2 * kPointerSize));
1689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(rcx);
1694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (expr->ends_initialization_block()) {
1695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movq(rdx, Operand(rsp, 0));  // Leave receiver on the stack for later.
1696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ pop(rdx);
1698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1700e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Call(ic, RelocInfo::CODE_TARGET);
1703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This nop signals to the IC that there is no inlined code at the call
1704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // site for it to patch.
1705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ nop();
1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ pop(rdx);
1710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(rax);  // Result of assignment, saved even if not needed.
1711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(rdx);
1712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(rax);
1714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
1717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1720d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) {
1721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Property");
1722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* key = expr->key();
1723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (key->IsPropertyName()) {
17257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    VisitForValue(expr->obj(), kAccumulator);
1726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitNamedPropertyLoad(expr);
17277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Apply(context_, rax);
1728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
17297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    VisitForValue(expr->obj(), kStack);
17307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    VisitForValue(expr->key(), kAccumulator);
17317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ pop(rdx);
1732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitKeyedPropertyLoad(expr);
17337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Apply(context_, rax);
1734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1738d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr,
1739402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                       Handle<Object> name,
1740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       RelocInfo::Mode mode) {
1741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the IC.
1742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
17433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
17443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
1745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
17463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1747402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ Move(rcx, name);
1748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
17493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SetSourcePosition(expr->position());
17503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the IC initialization code.
1751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
17523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
1753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                                         in_loop);
1754e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Call(ic, mode);
1755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Restore context register.
1756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1757402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Apply(context_, rax);
1758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
17619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
17629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                            Expression* key,
17639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                            RelocInfo::Mode mode) {
17649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Code common for calls using the IC.
17659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ZoneList<Expression*>* args = expr->arguments();
17669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  int arg_count = args->length();
17679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  for (int i = 0; i < arg_count; i++) {
17689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    VisitForValue(args->at(i), kStack);
17699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
17709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  VisitForValue(key, kAccumulator);
17719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ movq(rcx, rax);
17729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Record source position for debugger.
17739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  SetSourcePosition(expr->position());
17749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Call the IC initialization code.
17759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
17769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count,
17779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                                              in_loop);
17789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ Call(ic, mode);
17799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Restore context register.
17809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
17819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Apply(context_, rax);
17829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
17839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
17849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1785d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) {
1786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the call stub.
1787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
1789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
1790e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
1791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
1793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
1794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ CallStub(&stub);
17973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore context register.
17983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
17993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Discard the function left on TOS.
1800e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  DropAndApply(1, context_, rax);
1801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1804d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) {
1805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Call");
1806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* fun = expr->expression();
1807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Variable* var = fun->AsVariableProxy()->AsVariable();
1808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (var != NULL && var->is_possibly_eval()) {
1810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // In a call to eval, we first call %ResolvePossiblyDirectEval to
1811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // resolve the function we need to call and the receiver of the
1812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // call.  The we call the resolved function using the given
1813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // arguments.
1814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(fun, kStack);
1815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ PushRoot(Heap::kUndefinedValueRootIndex);  // Reserved receiver slot.
1816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push the arguments.
1818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    ZoneList<Expression*>* args = expr->arguments();
1819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    int arg_count = args->length();
1820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    for (int i = 0; i < arg_count; i++) {
1821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitForValue(args->at(i), kStack);
1822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push copy of the function - found below the arguments.
1825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Operand(rsp, (arg_count + 1) * kPointerSize));
1826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push copy of the first argument or undefined if it doesn't exist.
1828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (arg_count > 0) {
1829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(Operand(rsp, arg_count * kPointerSize));
1830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
1831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ PushRoot(Heap::kUndefinedValueRootIndex);
1832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push the receiver of the enclosing function and do runtime call.
1835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize));
1836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
1837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The runtime call returns a pair of values in rax (function) and
1839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // rdx (receiver). Touch up the stack with the right values.
1840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
1841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
1842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Record source position for debugger.
1844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    SetSourcePosition(expr->position());
1845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
1848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Restore context register.
1849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    DropAndApply(1, context_, rax);
1851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (var != NULL && !var->is_this() && var->is_global()) {
1852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to a global variable.
1853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Push global object as receiver for the call IC lookup.
1854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(CodeGenerator::GlobalObject());
1855e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
1856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (var != NULL && var->slot() != NULL &&
1857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block             var->slot()->type() == Slot::LOOKUP) {
1858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Call to a lookup slot (dynamically introduced variable).  Call
1859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // the runtime to find the function to call (returned in rax) and
1860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // the object holding it (returned in rdx).
1861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(context_register());
1862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Push(var->name());
1863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
1864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(rax);  // Function.
1865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(rdx);  // Receiver.
1866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitCallWithStub(expr);
1867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (fun->AsProperty() != NULL) {
1868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to an object property.
1869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Property* prop = fun->AsProperty();
1870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = prop->key()->AsLiteral();
1871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (key != NULL && key->handle()->IsSymbol()) {
1872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Call to a named property, use call IC.
1873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->obj(), kStack);
1874e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
18769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Call to a keyed property.
18779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // For a synthetic property use keyed load IC followed by function call,
18789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // for a regular property use KeyedCallIC.
1879e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->obj(), kStack);
1880d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (prop->is_synthetic()) {
18819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        VisitForValue(prop->key(), kAccumulator);
18829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        __ movq(rdx, Operand(rsp, 0));
18839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // Record source code position for IC call.
18849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        SetSourcePosition(prop->position());
18859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
18869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        __ call(ic, RelocInfo::CODE_TARGET);
18879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // By emitting a nop we make sure that we do not have a "test rax,..."
18889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // instruction after the call as it is treated specially
18899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // by the LoadIC code.
18909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        __ nop();
18919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // Pop receiver.
18929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        __ pop(rbx);
18939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // Push result (function).
18949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        __ push(rax);
18959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // Push receiver object on stack.
1896e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ movq(rcx, CodeGenerator::GlobalObject());
1897e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
18989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        EmitCallWithStub(expr);
1899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
19009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
1901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
19033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to some other expression.  If the expression is an anonymous
1905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // function literal not called in a loop, mark it as one that should
1906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // also use the fast code generator.
1907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    FunctionLiteral* lit = fun->AsFunctionLiteral();
1908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (lit != NULL &&
1909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        lit->name()->Equals(Heap::empty_string()) &&
1910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        loop_depth() == 0) {
1911d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      lit->set_try_full_codegen(true);
1912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1913e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(fun, kStack);
1914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load global receiver object.
1915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ movq(rbx, CodeGenerator::GlobalObject());
1916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
1917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit function call.
1918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    EmitCallWithStub(expr);
1919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1920d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1923d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
1924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
1925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
1926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
1927d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
1928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push function on the stack.
1929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  VisitForValue(expr->expression(), kStack);
1930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1931d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push global object (receiver).
1932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ push(CodeGenerator::GlobalObject());
1933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
1935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
1937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
1938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
19393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1940d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
1942d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
1943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
1944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1945d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Load function, arg_count into rdi and rax.
1946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Set(rax, arg_count);
1947d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Function is in rsp[arg_count + 1].
1948d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize));
1949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
1951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
1952d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Replace function on TOS with result in rax, or pop it.
1954e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  DropAndApply(1, context_, rax);
19553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
19563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsSmi(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  __ JumpIfSmi(rax, if_true);
1969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
1970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
1972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
1976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
1979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
1983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
1984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Condition positive_smi = __ CheckPositiveSmi(rax);
1986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(positive_smi, if_true);
1987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
1988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
1990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
1994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
1997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareRoot(rax, Heap::kNullValueRootIndex);
2005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
2006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Undetectable objects behave like undefined when tested with typeof.
2008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke           Immediate(1 << Map::kIsUndetectable));
2010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_zero, if_false);
2011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE));
2013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, if_false);
2014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE));
2015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below_equal, if_true);
2016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
2017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
20233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(args->length() == 1);
20243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  VisitForValue(args->at(0), kAccumulator);
20263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label materialize_true, materialize_false;
20283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_true = NULL;
20293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_false = NULL;
20303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
20313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ JumpIfSmi(rax, if_false);
20333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx);
20343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ j(above_equal, if_true);
20353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ jmp(if_false);
20363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Apply(context_, if_true, if_false);
20383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
20393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
2041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
2042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke           Immediate(1 << Map::kIsUndetectable));
2055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_zero, if_true);
2056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
2057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
2063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
2075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
2076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
2082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
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::EmitIsRegExp(ZoneList<Expression*>* args) {
2101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
2112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
2113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
2114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2117f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2118f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
2121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the frame pointer for the calling frame.
2129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Skip the arguments adaptor frame if it exists.
2132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label check_frame_marker;
2133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset),
2134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &check_frame_marker);
2136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
2137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check the marker in the calling frame.
2139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&check_frame_marker);
2140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset),
2141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                Smi::FromInt(StackFrame::CONSTRUCT));
2142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
2143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
2144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
2150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the two objects into registers and perform the comparison.
2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kAccumulator);
2155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
2159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(rbx);
2162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(rax, rbx);
2163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
2164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
2165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, if_true, if_false);
2167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2172f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ArgumentsAccessStub expects the key in edx and the formal
2174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // parameter count in eax.
2175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2176f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rdx, rax);
2177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Move(rax, Smi::FromInt(scope()->num_parameters()));
2178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label exit;
2188f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the number of formal parameters.
2189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Move(rax, Smi::FromInt(scope()->num_parameters()));
2190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2191f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the calling frame is an arguments adaptor frame.
2192f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ SmiCompare(Operand(rbx, StandardFrameConstants::kContextOffset),
2194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Arguments adaptor case: Read the arguments length from the
2198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // adaptor frame.
2199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
2202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (FLAG_debug_code) __ AbortIfNotSmi(rax);
2203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
2208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, null, function, non_function_constructor;
2210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, we return null.
2214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, &null);
2215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check that the object is a JS object but take special care of JS
2217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // functions to make sure they have 'Function' as their class.
2218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rax);  // Map is now in rax.
2219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, &null);
2220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // As long as JS_FUNCTION_TYPE is the last instance type and it is
2222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
2223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // LAST_JS_OBJECT_TYPE.
2224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
2225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
2226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpInstanceType(rax, JS_FUNCTION_TYPE);
2227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &function);
2228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the constructor in the map is a function.
2230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rax, Map::kConstructorOffset));
2231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &non_function_constructor);
2233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // rax now contains the constructor function. Grab the
2235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // instance class name from there.
2236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
2237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset));
2238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Functions have class 'Function'.
2241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&function);
2242f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Move(rax, Factory::function_class_symbol());
2243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Objects with a non-function constructor have class 'Object'.
2246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&non_function_constructor);
2247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Move(rax, Factory::Object_symbol());
2248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-JS objects have class null.
2251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&null);
2252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(rax, Heap::kNullValueRootIndex);
2253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // All done.
2255f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
2262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Conditionally generate a log call.
2263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Args:
2264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   0 (literal string): The type of logging (corresponds to the flags).
2265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     This is used to determine whether or not to generate the log call.
2266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   1 (string): Format string.  Access the string at argument index 2
2267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     with '%2s' (see Logger::LogRuntime for all the formats).
2268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   2 (array): Arguments to the format string.
2269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 3);
2270f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING
2271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(args->at(1), kStack);
2273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(args->at(2), kStack);
2274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLog, 2);
2275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif
2277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Finally, we're expected to leave a value on the top of the stack.
2278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
2284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label slow_allocate_heapnumber;
2287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label heapnumber_allocated;
2288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ AllocateHeapNumber(rbx, rcx, &slow_allocate_heapnumber);
2290f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&heapnumber_allocated);
2291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&slow_allocate_heapnumber);
22933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Allocate a heap number.
22943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CallRuntime(Runtime::kNumberAlloc, 0);
2295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, rax);
2296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&heapnumber_allocated);
2298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Return a random uint32 number in rax.
2300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs.
2301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ PrepareCallCFunction(0);
2302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallCFunction(ExternalReference::random_uint32_function(), 0);
2303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert 32 random bits in rax to 0.(32 random bits) in a double
2305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // by computing:
2306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
2307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rcx, Immediate(0x49800000));  // 1.0 x 2^20 as single.
2308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movd(xmm1, rcx);
2309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movd(xmm0, rax);
2310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cvtss2sd(xmm1, xmm1);
2311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ xorpd(xmm0, xmm1);
2312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ subsd(xmm0, xmm1);
2313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0);
2314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, rbx);
2316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2320f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
2321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SubStringStub stub;
2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(2), kStack);
2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
2333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  RegExpExecStub stub;
2335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 4);
2336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(2), kStack);
2339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(3), kStack);
2340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2343f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
2346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);  // Load the object.
2349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
2351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi return the object.
2352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, &done);
2353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the object.
2354f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_VALUE_TYPE, rbx);
2355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &done);
2356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rax, JSValue::kValueOffset));
2357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
2364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the runtime function.
2365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2368f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_pow, 2);
2369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2370f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
2374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2376f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);  // Load the object.
2377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kAccumulator);  // Load the value.
2378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(rbx);  // rax = value. ebx = object.
2379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2380f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
2381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, return the value.
2382f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rbx, &done);
2383f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2384f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the value.
2385f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx);
2386f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &done);
2387f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Store the value.
2389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(FieldOperand(rbx, JSValue::kValueOffset), rax);
2390f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the write barrier.  Save the value as it will be
2391f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // overwritten by the write barrier code and is needed afterward.
2392f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rdx, rax);
2393f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ RecordWrite(rbx, JSValue::kValueOffset, rdx, rcx);
2394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
2401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 1);
2402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2403f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
2404f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  NumberToStringStub stub;
2407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
2413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kAccumulator);
2416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
24187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharFromCodeGenerator generator(rax, rbx);
24197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
24207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
2421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
24237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
2424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
24267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Apply(context_, rbx);
24277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
24287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
24317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
24327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  VisitForValue(args->at(0), kStack);
24347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  VisitForValue(args->at(1), kAccumulator);
24357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = rbx;
24377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = rax;
24387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch = rcx;
24397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = rdx;
24407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
24427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
24447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
24457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
24467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharCodeAtGenerator generator(object,
24477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      index,
24487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      scratch,
24497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      result,
24507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
24517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
24527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &index_out_of_range,
24537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      STRING_INDEX_IS_NUMBER);
24547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
2455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
24587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
24597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // NaN.
24607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kNanValueRootIndex);
24617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
24627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
24647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move the undefined value into the result register, which will
24657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // trigger conversion.
24667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
24677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
24687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
24707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
2471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
24737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Apply(context_, result);
2474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
24787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
24797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  VisitForValue(args->at(0), kStack);
24817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  VisitForValue(args->at(1), kAccumulator);
24827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = rbx;
24847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = rax;
24857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch1 = rcx;
24867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch2 = rdx;
24877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = rax;
24887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
24907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
24927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
24937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
24947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharAtGenerator generator(object,
24957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  index,
24967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  scratch1,
24977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  scratch2,
24987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  result,
24997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
25007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
25017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &index_out_of_range,
25027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  STRING_INDEX_IS_NUMBER);
25037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
25047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
25057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
25077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
25087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the empty string.
25097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kEmptyStringRootIndex);
25107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
25117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
25137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move smi zero into the result register, which will trigger
25147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // conversion.
25157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Move(result, Smi::FromInt(0));
25167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
25177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
25197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
25207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
25227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Apply(context_, result);
2523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringAddStub stub(NO_STRING_ADD_FLAGS);
2533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringCompareStub stub;
2545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
2551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
2552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  TranscendentalCacheStub stub(TranscendentalCache::SIN);
2553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
2561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
2562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  TranscendentalCacheStub stub(TranscendentalCache::COS);
2563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
2566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the runtime function.
2572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_sqrt, 1);
2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
2580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() >= 2);
2581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int arg_count = args->length() - 2;  // For receiver and function.
2583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);  // Receiver.
2584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < arg_count; i++) {
2585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForValue(args->at(i + 1), kStack);
2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(arg_count + 1), kAccumulator);  // Function.
2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // InvokeFunction requires function in rdi. Move it in there.
2590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!result_register().is(rdi)) __ movq(rdi, result_register());
2591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ParameterCount count(arg_count);
2592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeFunction(rdi, count, CALL_FUNCTION);
2593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
2599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
2600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(2), kStack);
2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kRegExpConstructResult, 3);
2604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
2609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
2610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(0), kStack);
2611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kStack);
2612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(2), kStack);
2613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kSwapElements, 3);
2614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
2619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_NE(NULL, args->at(0)->AsLiteral());
2622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
2623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<FixedArray> jsfunction_result_caches(
2625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Top::global_context()->jsfunction_result_caches());
2626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (jsfunction_result_caches->length() <= cache_id) {
2627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Abort("Attempt to use undefined cache.");
2628f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Apply(context_, rax);
2630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  VisitForValue(args->at(1), kAccumulator);
2634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register key = rax;
2636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register cache = rbx;
2637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register tmp = rcx;
2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(cache, CodeGenerator::ContextOperand(rsi, Context::GLOBAL_INDEX));
2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(cache,
2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          FieldOperand(cache, GlobalObject::kGlobalContextOffset));
2641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(cache,
2642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          CodeGenerator::ContextOperand(
2643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke              cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
2644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(cache,
2645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
2646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, not_found;
2648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // tmp now holds finger offset as a smi.
2649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
2650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
2651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SmiIndex index =
2652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2);
2653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(key, FieldOperand(cache,
2654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.reg,
2655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.scale,
2656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            FixedArray::kHeaderSize));
2657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &not_found);
2658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(cache,
2659f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.reg,
2660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.scale,
2661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            FixedArray::kHeaderSize + kPointerSize));
2662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&not_found);
2665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call runtime to perform the lookup.
2666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(cache);
2667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(key);
2668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetFromCache, 2);
2669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2670f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Apply(context_, rax);
2672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2675bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
2676bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT_EQ(2, args->length());
2677bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2678bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register right = rax;
2679bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register left = rbx;
2680bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register tmp = rcx;
2681bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2682bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  VisitForValue(args->at(0), kStack);
2683bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  VisitForValue(args->at(1), kAccumulator);
2684bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(left);
2685bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2686bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label done, fail, ok;
2687bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmpq(left, right);
2688bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(equal, &ok);
2689bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Fail if either is a non-HeapObject.
2690bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Condition either_smi = masm()->CheckEitherSmi(left, right, tmp);
2691bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(either_smi, &fail);
2692bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(zero, &fail);
2693bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(tmp, FieldOperand(left, HeapObject::kMapOffset));
2694bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmpb(FieldOperand(tmp, Map::kInstanceTypeOffset),
2695bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch          Immediate(JS_REGEXP_TYPE));
2696bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(not_equal, &fail);
2697bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmpq(tmp, FieldOperand(right, HeapObject::kMapOffset));
2698bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(not_equal, &fail);
2699bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(tmp, FieldOperand(left, JSRegExp::kDataOffset));
2700bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmpq(tmp, FieldOperand(right, JSRegExp::kDataOffset));
2701bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(equal, &ok);
2702bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&fail);
2703bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ Move(rax, Factory::false_value());
2704bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ jmp(&done);
2705bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&ok);
2706bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ Move(rax, Factory::true_value());
2707bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&done);
2708bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2709bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Apply(context_, rax);
2710bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
2711bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2712bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2713d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
2714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<String> name = expr->name();
2715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (name->length() > 0 && name->Get(0) == '_') {
2716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ InlineRuntimeCall");
2717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitInlineRuntimeCall(expr);
2718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ CallRuntime");
27223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* args = expr->arguments();
27233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
2725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Prepare for calling JS runtime function.
2726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ movq(rax, CodeGenerator::GlobalObject());
2727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
2728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
27293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
27303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Push the arguments ("left-to-right").
27313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
27323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
2733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
2734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
2737402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Call the JS runtime function using a call IC.
2738402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ Move(rcx, expr->name());
2739402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2740402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
2741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ call(ic, RelocInfo::CODE_TARGET);
2742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Restore context register.
2743d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
2745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(expr->function(), arg_count);
2746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2747402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Apply(context_, rax);
2748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2751d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
2753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Token::DELETE: {
2754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
2755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Property* prop = expr->expression()->AsProperty();
2756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
2757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (prop == NULL && var == NULL) {
2758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Result of deleting non-property, non-variable reference is true.
2759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The subexpression may have side effects.
2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForEffect(expr->expression());
2761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        Apply(context_, true);
2762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else if (var != NULL &&
2763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 !var->is_global() &&
2764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 var->slot() != NULL &&
2765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 var->slot()->type() != Slot::LOOKUP) {
2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Result of deleting non-global, non-dynamic variables is false.
2767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The subexpression does not have side effects.
2768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        Apply(context_, false);
2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else {
2770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Property or variable reference.  Call the delete builtin with
2771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // object and property name as arguments.
2772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (prop != NULL) {
2773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          VisitForValue(prop->obj(), kStack);
2774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          VisitForValue(prop->key(), kStack);
2775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (var->is_global()) {
2776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(CodeGenerator::GlobalObject());
2777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ Push(var->name());
2778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else {
2779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Non-global variable.  Call the runtime to look up the context
2780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // where the variable was introduced.
2781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(context_register());
2782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ Push(var->name());
2783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kLookupContext, 2);
2784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(rax);
2785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ Push(var->name());
2786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
2787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
2788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        Apply(context_, rax);
2789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
2790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
2794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
2795e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
2796e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (context_) {
2797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kUninitialized:
2798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
2799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
2800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kEffect:
2801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
2802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kValue:
2803e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          switch (location_) {
2804e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kAccumulator:
2805e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex);
2806e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
2807e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kStack:
2808e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ PushRoot(Heap::kUndefinedValueRootIndex);
2809e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
2810e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
2811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
2812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kTestValue:
2813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Value is false so it's needed.
2814e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          switch (location_) {
2815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kAccumulator:
2816e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex);
2817e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
2818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kStack:
2819e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ PushRoot(Heap::kUndefinedValueRootIndex);
2820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
2821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
2822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Fall through.
2823e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case Expression::kTest:
2824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kValueTest:
2825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ jmp(false_label_);
2826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
2827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2830d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
2832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label materialize_true, materialize_false;
2834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label* if_true = NULL;
2835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label* if_false = NULL;
2836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Notice that the labels are swapped.
2838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true);
2839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2840e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForControl(expr->expression(), if_true, if_false);
2841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Apply(context_, if_false, if_true);  // Labels swapped.
2843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
2847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
2848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      VariableProxy* proxy = expr->expression()->AsVariableProxy();
2849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (proxy != NULL &&
2850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          !proxy->var()->is_this() &&
2851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          proxy->var()->is_global()) {
2852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        Comment cmnt(masm_, "Global variable");
2853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Move(rcx, proxy->name());
28547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        __ movq(rax, CodeGenerator::GlobalObject());
2855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
2856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Use a regular load, not a contextual load, to avoid a reference
2857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // error.
2858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Call(ic, RelocInfo::CODE_TARGET);
28597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        __ push(rax);
2860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else if (proxy != NULL &&
2861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                 proxy->var()->slot() != NULL &&
2862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                 proxy->var()->slot()->type() == Slot::LOOKUP) {
2863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(rsi);
2864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Push(proxy->name());
2865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(rax);
2867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
2868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // This expression cannot throw a reference error at the top level.
2869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(expr->expression(), kStack);
2870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallRuntime(Runtime::kTypeof, 1);
2873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Apply(context_, rax);
2874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2877d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Token::ADD: {
2878d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Comment cmt(masm_, "[ UnaryOperation (ADD)");
2879d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      VisitForValue(expr->expression(), kAccumulator);
2880d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Label no_conversion;
28814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Condition is_smi = masm_->CheckSmi(result_register());
2882d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ j(is_smi, &no_conversion);
2883d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ push(result_register());
2884d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
2885d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ bind(&no_conversion);
2886d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Apply(context_, result_register());
2887d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      break;
2888d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
2889d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
28904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::SUB: {
28914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (SUB)");
2892ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke      bool can_overwrite =
28934515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          (expr->expression()->AsBinaryOperation() != NULL &&
28944515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
2895ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke      UnaryOverwriteMode overwrite =
2896ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke          can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
28974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      GenericUnaryOpStub stub(Token::SUB, overwrite);
28984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // GenericUnaryOpStub expects the argument to be in the
28994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // accumulator register rax.
29004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      VisitForValue(expr->expression(), kAccumulator);
29014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
29024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Apply(context_, rax);
29034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
29044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
29054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
29064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::BIT_NOT: {
29074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
2908ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke      bool can_overwrite =
29094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          (expr->expression()->AsBinaryOperation() != NULL &&
29104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
2911ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke      UnaryOverwriteMode overwrite =
2912ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke          can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
29134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
29144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // GenericUnaryOpStub expects the argument to be in the
29154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // accumulator register rax.
29164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      VisitForValue(expr->expression(), kAccumulator);
29174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Avoid calling the stub for Smis.
29184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Label smi, done;
29194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Condition is_smi = masm_->CheckSmi(result_register());
29204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ j(is_smi, &smi);
29214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Non-smi: call stub leaving result in accumulator register.
29224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
29234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ jmp(&done);
29244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Perform operation directly on Smis.
29254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ bind(&smi);
29264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ SmiNot(result_register(), result_register());
29274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ bind(&done);
29284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Apply(context_, result_register());
29294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
29304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
29314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
2932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
2933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
29343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
29353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
29363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
29373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2938d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
2939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Comment cmnt(masm_, "[ CountOperation");
2940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand-sides are rewritten to have a 'throw
2942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ReferenceError' as the left-hand side.
2943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->expression()->IsValidLeftHandSide()) {
2944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->expression());
2945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2948e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Expression can only be a property, a global or a (parameter or local)
2949e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
2950e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
2951e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LhsKind assign_type = VARIABLE;
2952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
2953e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In case of a property we use the uninitialized expression context
2954e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // of the key to detect a named property.
2955e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (prop != NULL) {
2956e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    assign_type =
2957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
2958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2960e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
2961e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
2962e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
2963e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Location saved_location = location_;
2964d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    location_ = kAccumulator;
2965e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
2966e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     Expression::kValue);
2967e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    location_ = saved_location;
2968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
2969e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
2970e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (expr->is_postfix() && context_ != Expression::kEffect) {
2971e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Push(Smi::FromInt(0));
2972e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2973e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (assign_type == NAMED_PROPERTY) {
29747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      VisitForValue(prop->obj(), kAccumulator);
29757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(rax);  // Copy of receiver, needed for later store.
2976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitNamedPropertyLoad(prop);
2977e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
29787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      VisitForValue(prop->obj(), kStack);
29797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      VisitForValue(prop->key(), kAccumulator);
29807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ movq(rdx, Operand(rsp, 0));  // Leave receiver on stack
29817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(rax);  // Copy of key, needed for later store.
2982e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitKeyedPropertyLoad(prop);
2983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2985e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2986d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Call ToNumber only if operand is not a smi.
2987d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label no_conversion;
2988d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Condition is_smi;
2989d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  is_smi = masm_->CheckSmi(rax);
2990d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ j(is_smi, &no_conversion);
2991d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ push(rax);
2992e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
2993d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&no_conversion);
2994e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2995e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
2996e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
2997e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    switch (context_) {
2998e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kUninitialized:
2999e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        UNREACHABLE();
3000e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kEffect:
3001e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Do not save result.
3002e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        break;
3003e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kValue:
3004e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kTest:
3005e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kValueTest:
3006e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kTestValue:
3007e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Save the result on the stack. If we have a named or keyed property
3008e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // we store the result under the receiver that is currently on top
3009e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // of the stack.
3010e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        switch (assign_type) {
3011e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          case VARIABLE:
3012e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            __ push(rax);
3013e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            break;
3014e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          case NAMED_PROPERTY:
3015e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            __ movq(Operand(rsp, kPointerSize), rax);
3016e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            break;
3017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          case KEYED_PROPERTY:
3018e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            __ movq(Operand(rsp, 2 * kPointerSize), rax);
3019e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            break;
3020e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3021e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        break;
3022e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3023e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3024e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3025d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Inline smi case if we are in a loop.
3026d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label stub_call, done;
3027d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (loop_depth() > 0) {
3028d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
3029d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiAddConstant(rax, rax, Smi::FromInt(1));
3030d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
3031d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiSubConstant(rax, rax, Smi::FromInt(1));
3032d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3033d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ j(overflow, &stub_call);
3034d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // We could eliminate this smi check if we split the code at
3035d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // the first smi check before calling ToNumber.
3036d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    is_smi = masm_->CheckSmi(rax);
3037d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ j(is_smi, &done);
3038d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ bind(&stub_call);
3039d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Call stub. Undo operation first.
3040d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
3041d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiSubConstant(rax, rax, Smi::FromInt(1));
3042d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
3043d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiAddConstant(rax, rax, Smi::FromInt(1));
3044d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3045d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
3046e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call stub for +1/-1.
3047e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  GenericBinaryOpStub stub(expr->binary_op(),
3048e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_OVERWRITE,
3049e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_GENERIC_BINARY_FLAGS);
30504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  stub.GenerateCall(masm_, rax, Smi::FromInt(1));
3051d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
3052e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3053e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in rax.
3054e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
3055e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case VARIABLE:
3056e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
3057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
3058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               Token::ASSIGN,
3060e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               Expression::kEffect);
3061e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // For all contexts except kEffect: We have the result on
3062e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
3063e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (context_ != Expression::kEffect) {
3064e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          ApplyTOS(context_);
3065e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3066e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
3067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
3068e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               Token::ASSIGN,
3070e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               context_);
3071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3072e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
3073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
3074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Move(rcx, prop->key()->AsLiteral()->handle());
30754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ pop(rdx);
3076e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
3077e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ call(ic, RelocInfo::CODE_TARGET);
3078e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // This nop signals to the IC that there is no inlined code at the call
3079e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // site for it to patch.
3080e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ nop();
3081e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
3082e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (context_ != Expression::kEffect) {
3083e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          ApplyTOS(context_);
3084e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3085e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
30864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        Apply(context_, rax);
3087e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3088e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
3089e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3090e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
3091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(rcx);
3092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(rdx);
3093e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
3094e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ call(ic, RelocInfo::CODE_TARGET);
3095e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // This nop signals to the IC that there is no inlined code at the call
3096e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // site for it to patch.
3097e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ nop();
3098e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
3099e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (context_ != Expression::kEffect) {
3100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          ApplyTOS(context_);
3101e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
3103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        Apply(context_, rax);
3104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3105e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
3106e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3107e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3109e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3110d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
3111d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ BinaryOperation");
3112d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
3113d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::COMMA:
3114e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->left());
3115d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Visit(expr->right());
3116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::OR:
3119d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::AND:
3120d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      EmitLogicalOperation(expr);
3121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::ADD:
3124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::SUB:
3125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::DIV:
3126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::MOD:
3127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::MUL:
3128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::BIT_OR:
3129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::BIT_AND:
3130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::BIT_XOR:
3131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::SHL:
3132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::SHR:
3133e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::SAR:
3134e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->left(), kStack);
3135e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kAccumulator);
3136e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitBinaryOp(expr->op(), context_);
3137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3138e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
3140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
31413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
3142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
31433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
31443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNullCompare(bool strict,
3146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Register obj,
3147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Register null_const,
3148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Label* if_true,
3149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Label* if_false,
3150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Register scratch) {
3151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(obj, null_const);
3152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (strict) {
3153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
3154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
3155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
3156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CompareRoot(obj, Heap::kUndefinedValueRootIndex);
3157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
3158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ JumpIfSmi(obj, if_false);
3159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // It can be an undetectable object.
3160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movq(scratch, FieldOperand(obj, HeapObject::kMapOffset));
3161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ testb(FieldOperand(scratch, Map::kBitFieldOffset),
3162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke             Immediate(1 << Map::kIsUndetectable));
3163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(not_zero, if_true);
3164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
3166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3169d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
3170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
3171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3172e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
3173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
3174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3176f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
3177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
3178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3179e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  VisitForValue(expr->left(), kStack);
3180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
3181e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
3182e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kStack);
3183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
3184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CompareRoot(rax, Heap::kTrueValueRootIndex);
3185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(equal, if_true);
3186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
3187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
31883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
3190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kStack);
3191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      InstanceofStub stub;
3192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
3193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ testq(rax, rax);
3194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(zero, if_true);  // The stub returns 0 for true.
3195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
3196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
3200e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kAccumulator);
3201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Condition cc = no_condition;
3202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      bool strict = false;
3203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (expr->op()) {
3204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::EQ_STRICT:
3205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          strict = true;
3206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Fall through.
3207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        case Token::EQ: {
3208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = equal;
3209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rdx);
3210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // If either operand is constant null we do a fast compare
3211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // against null.
3212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          Literal* right_literal = expr->right()->AsLiteral();
3213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          Literal* left_literal = expr->left()->AsLiteral();
3214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (right_literal != NULL && right_literal->handle()->IsNull()) {
3215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            EmitNullCompare(strict, rdx, rax, if_true, if_false, rcx);
3216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Apply(context_, if_true, if_false);
3217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            return;
3218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          } else if (left_literal != NULL && left_literal->handle()->IsNull()) {
3219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            EmitNullCompare(strict, rax, rdx, if_true, if_false, rcx);
3220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Apply(context_, if_true, if_false);
3221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            return;
3222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          }
3223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
3225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LT:
3226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
3227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rdx);
3228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GT:
3230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Reverse left and right sizes to obtain ECMA-262 conversion order.
3231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
3232e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(rdx, result_register());
3233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rax);
3234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block         break;
3235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LTE:
3236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Reverse left and right sizes to obtain ECMA-262 conversion order.
3237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
3238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(rdx, result_register());
3239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rax);
3240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GTE:
3242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
3243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rdx);
3244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::IN:
3246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::INSTANCEOF:
3247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default:
3248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
3249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
3250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // The comparison stub expects the smi vs. smi case to be handled
3252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // before it is called.
3253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Label slow_case;
3254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ JumpIfNotBothSmi(rax, rdx, &slow_case);
3255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ SmiCompare(rdx, rax);
3256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(cc, if_true);
3257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
3258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ bind(&slow_case);
3260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      CompareStub stub(cc, strict);
3261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
3262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ testq(rax, rax);
3263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(cc, if_true);
3264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
3265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
32663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
32673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
3269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
3270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, if_true, if_false);
3271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3274d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
3275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
3276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, rax);
3277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3280d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::result_register() { return rax; }
3281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3283d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::context_register() { return rsi; }
3284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3286d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
3287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(IsAligned(frame_offset, kPointerSize));
3288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(Operand(rbp, frame_offset), value);
32893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
32903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
32913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3292d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
3293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(dst, CodeGenerator::ContextOperand(rsi, context_index));
3294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ----------------------------------------------------------------------------
3298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support.
3299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3301d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() {
3302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rdx));
3303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rcx));
3304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Cook return address on top of stack (smi encoded Code* delta)
3305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(rdx, Operand(rsp, 0));
3306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, masm_->CodeObject());
3307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ subq(rdx, rcx);
3308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Integer32ToSmi(rdx, rdx);
3309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(Operand(rsp, 0), rdx);
3310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store result register while executing finally block.
3311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
3312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3315d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() {
3316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rdx));
3317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rcx));
3318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Restore result register from stack.
3319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(result_register());
3320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Uncook return address.
3321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(rdx, Operand(rsp, 0));
3322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ SmiToInteger32(rdx, rdx);
3323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, masm_->CodeObject());
3324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ addq(rdx, rcx);
3325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(Operand(rsp, 0), rdx);
3326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // And return.
3327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ret(0);
3328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3331d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef __
3332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
33343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} }  // namespace v8::internal
3335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
3337