full-codegen-x64.cc revision 4515c472dc3e5ed2448a564600976759e569a0a8
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
303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "codegen-inl.h"
31d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h"
323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "debug.h"
33d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "full-codegen.h"
343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "parser.h"
353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 {
373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal {
383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_)
403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function.  On entry to the function the receiver
423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, with the
433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them.  The actual argument count matches the
443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function.
453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are:
473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rdi: the JS function object being called (ie, ourselves)
483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rsi: our context
493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rbp: our caller's frame pointer
503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rsp: stack pointer (pointing to return address)
513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame.  Please see JavaScriptFrameConstants in
533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-x64.h for its layout.
544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  function_ = fun;
563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SetFunctionPosition(fun);
573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (mode == PRIMARY) {
594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ push(rbp);  // Caller's frame pointer.
604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ movq(rbp, rsp);
614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ push(rsi);  // Callee's context.
624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ push(rdi);  // Callee's JS Function.
634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    { Comment cmnt(masm_, "[ Allocate locals");
654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      int locals_count = fun->scope()->num_stack_slots();
664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      if (locals_count == 1) {
674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        __ PushRoot(Heap::kUndefinedValueRootIndex);
684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      } else if (locals_count > 1) {
694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        for (int i = 0; i < locals_count; i++) {
714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ push(rdx);
724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        }
73d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
74d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
75d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    bool function_in_register = true;
774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // Possibly allocate a local context.
794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (fun->scope()->num_heap_slots() > 0) {
804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmnt(masm_, "[ Allocate local context");
814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Argument to NewContext is the function, which is still in rdi.
824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ push(rdi);
834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallRuntime(Runtime::kNewContext, 1);
844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      function_in_register = false;
854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Context is returned in both rax and rsi.  It replaces the context
864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // passed to us.  It's saved in the stack and kept live in rsi.
874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Copy any necessary parameters into the context.
904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      int num_parameters = fun->scope()->num_parameters();
914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      for (int i = 0; i < num_parameters; i++) {
924515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        Slot* slot = fun->scope()->parameter(i)->slot();
934515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        if (slot != NULL && slot->type() == Slot::CONTEXT) {
944515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          int parameter_offset = StandardFrameConstants::kCallerSPOffset +
954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                     (num_parameters - 1 - i) * kPointerSize;
964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // Load parameter from stack.
974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(rax, Operand(rbp, parameter_offset));
984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // Store it in the context.
994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          int context_offset = Context::SlotOffset(slot->index());
1004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(Operand(rsi, context_offset), rax);
1014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // Update the write barrier. This clobbers all involved
1024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // registers, so we have use a third register to avoid
1034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // clobbering rsi.
1044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(rcx, rsi);
1054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ RecordWrite(rcx, context_offset, rax, rbx);
1064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        }
107d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // Possibly allocate an arguments object.
1114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Variable* arguments = fun->scope()->arguments()->AsVariable();
1124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (arguments != NULL) {
1134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Arguments object must be allocated after the context object, in
1144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // case the "arguments" or ".arguments" variables are in the context.
1154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmnt(masm_, "[ Allocate arguments object");
1164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      if (function_in_register) {
1174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        __ push(rdi);
1184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      } else {
1194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      }
1214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // The receiver is just before the parameters on the caller's stack.
1224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ lea(rdx, Operand(rbp, StandardFrameConstants::kCallerSPOffset +
1234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                          fun->num_parameters() * kPointerSize));
1244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ push(rdx);
1254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ Push(Smi::FromInt(fun->num_parameters()));
1264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Arguments to ArgumentsAccessStub:
1274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      //   function, receiver address, parameter count.
1284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // The stub will rewrite receiver and parameter count if the previous
1294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // stack frame was an arguments adapter frame.
1304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
1314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
1324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Store new arguments object in both "arguments" and ".arguments" slots.
1334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ movq(rcx, rax);
1344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Move(arguments->slot(), rax, rbx, rdx);
1354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Slot* dot_arguments_slot =
1364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          fun->scope()->arguments_shadow()->AsVariable()->slot();
1374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Move(dot_arguments_slot, rcx, rbx, rdx);
138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
141e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  { Comment cmnt(masm_, "[ Declarations");
142e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitDeclarations(fun->scope()->declarations());
143e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
144e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ Stack check");
1463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label ok;
1473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
1483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(above_equal, &ok);
1493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    StackCheckStub stub;
1503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CallStub(&stub);
1513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&ok);
1523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (FLAG_trace) {
1553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CallRuntime(Runtime::kTraceEnter, 0);
1563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ Body");
159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    VisitStatements(fun->body());
161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit a 'return undefined' in case control fell off the end of the body.
1663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    EmitReturnSequence(function_->end_position());
168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
172d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitReturnSequence(int position) {
173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ jmp(&return_label_);
176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
1783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
1793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(rax);
1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ CallRuntime(Runtime::kTraceExit, 1);
1813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG
183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Add a label for checking the size of the code used for returning.
184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Label check_exit_codesize;
185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    masm_->bind(&check_exit_codesize);
186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CodeGenerator::RecordPositions(masm_, position);
1883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ RecordJSReturn();
1893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Do not use the leave instruction here because it is too short to
1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // patch with the code required by the debugger.
1913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(rsp, rbp);
1923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ pop(rbp);
193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ret((function_->scope()->num_parameters() + 1) * kPointerSize);
1943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT
1953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Add padding that will be overwritten by a debugger breakpoint.  We
1963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7
1973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // (3 + 1 + 3).
198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    const int kPadding = Assembler::kJSReturnSequenceLength - 7;
1993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    for (int i = 0; i < kPadding; ++i) {
2003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      masm_->int3();
2013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Check that the size of the code used for returning matches what is
203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // expected by the debugger.
204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_EQ(Assembler::kJSReturnSequenceLength,
205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
2063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#endif
2073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
2093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
211d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Register reg) {
212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
215e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
217e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Nothing to do.
218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
219e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValue:
221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Move value into place.
222e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
223e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
224e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (!reg.is(result_register())) __ movq(result_register(), reg);
225e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
226e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
227e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(reg);
228e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
229e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
231e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTest:
233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // For simplicity we always test the accumulator register.
234e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!reg.is(result_register())) __ movq(result_register(), reg);
235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
239e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!reg.is(result_register())) __ movq(result_register(), reg);
241e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
243e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
254d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Slot* slot) {
255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Nothing to do.
260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue: {
262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      MemOperand slot_operand = EmitSlotSearch(slot, result_register());
263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(result_register(), slot_operand);
266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Memory operands can be pushed directly.
269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(slot_operand);
270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Move(result_register(), slot);
277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Move(result_register(), slot);
283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
296d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Literal* lit) {
297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Nothing to do.
302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Move(result_register(), lit->handle());
307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Push(lit->handle());
310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Move(result_register(), lit->handle());
316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Move(result_register(), lit->handle());
322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
335d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ApplyTOS(Expression::Context context) {
336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
352d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ pop(result_register());
356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
359e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
360d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTestValue:
361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(result_register(), Operand(rsp, 0));
367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
370d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
374d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
375d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DropAndApply(int count,
376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     Expression::Context context,
377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     Register reg) {
378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(count > 0);
379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!reg.is(rsp));
380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(count);
386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValue:
389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Drop(count);
392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (!reg.is(result_register())) __ movq(result_register(), reg);
393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (count > 1) __ Drop(count - 1);
396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(Operand(rsp, 0), reg);
397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(count);
403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!reg.is(result_register())) __ movq(result_register(), reg);
404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
405d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTestValue:
409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Drop(count);
412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (!reg.is(result_register())) __ movq(result_register(), reg);
413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (count > 1) __ Drop(count - 1);
416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(result_register(), reg);
417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(Operand(rsp, 0), result_register());
418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
426d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context,
427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                              Label* materialize_true,
428e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                              Label* materialize_false) {
429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
431e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT_EQ(materialize_true, materialize_false);
434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(materialize_true);
435d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue: {
438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Label done;
439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_true);
442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Move(result_register(), Factory::true_value());
443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(&done);
444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_false);
445e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Move(result_register(), Factory::false_value());
446e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
448e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_true);
449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Push(Factory::true_value());
450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(&done);
451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_false);
452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Push(Factory::false_value());
453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(&done);
456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
461e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(materialize_true);
464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Move(result_register(), Factory::true_value());
467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
468e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Push(Factory::true_value());
470e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(true_label_);
473e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
474e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
475e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(materialize_false);
477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Move(result_register(), Factory::false_value());
480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Push(Factory::false_value());
483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(false_label_);
486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
487d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
488d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
490d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
491d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DoTest(Expression::Context context) {
492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // The value to test is in the accumulator.  If the value might be needed
493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // on the stack (value/test and test/value contexts with a stack location
494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // desired), then the value is already duplicated on the stack.
495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_NE(NULL, true_label_);
496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_NE(NULL, false_label_);
497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In value/test and test/value expression contexts with stack as the
499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // desired location, there is already an extra value on the stack.  Use a
500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // label to discard it if unneeded.
501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label discard;
502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label* if_true = true_label_;
503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label* if_false = false_label_;
504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_false = &discard;
517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
521e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
523e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
524e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
525e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_true = &discard;
526e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the inlined tests assumed by the stub.
532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex);
533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_true);
536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CompareRoot(result_register(), Heap::kFalseValueRootIndex);
537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, kSmiTag);
539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ SmiCompare(result_register(), Smi::FromInt(0));
540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
541e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Condition is_smi = masm_->CheckSmi(result_register());
542e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(is_smi, if_true);
543e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
544e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save a copy of the value if it may be needed and isn't already saved.
545e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
547e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValue:
549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
550e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
555e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
558e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
559d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
560d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
561e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
562e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
568e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
569e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
571e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call the ToBoolean stub for all other cases.
573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ToBooleanStub stub;
574e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
576e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ testq(rax, rax);
577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // The stub returns nonzero for true.  Complete based on the context.
579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
581e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
584e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTest:
586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(not_zero, true_label_);
587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(false_label_);
588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(zero, &discard);
594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(true_label_);
596e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(not_zero, true_label_);
599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
600d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ bind(&discard);
602e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ jmp(false_label_);
604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
606e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(not_zero, &discard);
610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(false_label_);
612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(zero, false_label_);
615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ bind(&discard);
618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
619d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ jmp(true_label_);
620d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
625d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (slot->type()) {
627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::PARAMETER:
628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOCAL:
629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return Operand(rbp, SlotOffset(slot));
630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::CONTEXT: {
631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      int context_chain_length =
632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          function_->scope()->ContextChainLength(slot->var()->scope());
633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ LoadContext(scratch, context_chain_length);
634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return CodeGenerator::ContextOperand(scratch, slot->index());
635d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOOKUP:
637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  UNREACHABLE();
640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return Operand(rax, 0);
641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
642d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
644d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) {
645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(source, destination);
646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(destination, location);
647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
648d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
650d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst,
651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register src,
652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch1,
653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch2) {
654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(dst->type() != Slot::LOOKUP);  // Not yet implemented.
655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!scratch1.is(src) && !scratch2.is(src));
656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(dst, scratch1);
657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(location, src);
658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (dst->type() == Slot::CONTEXT) {
660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ RecordWrite(scratch1, offset, src, scratch2);
662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
663d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
664d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
666d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) {
667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Declaration");
668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Variable* var = decl->proxy()->var();
669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(var != NULL);  // Must have been resolved.
670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Slot* slot = var->slot();
671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = var->AsProperty();
672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (slot != NULL) {
674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOCAL:
677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (decl->mode() == Variable::CONST) {
678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister);
680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else if (decl->fun() != NULL) {
681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          VisitForValue(decl->fun(), kAccumulator);
682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(Operand(rbp, SlotOffset(slot)), result_register());
683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT:
687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // We bypass the general EmitSlotSearch because we know more about
688e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // this specific context.
689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
690d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // The variable in the decl always resides in the current context.
691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope()));
692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (FLAG_debug_code) {
693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Check if we have the correct context pointer.
694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ movq(rbx,
695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                  CodeGenerator::ContextOperand(rsi, Context::FCONTEXT_INDEX));
696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ cmpq(rbx, rsi);
697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Check(equal, "Unexpected declaration in current context.");
698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (decl->mode() == Variable::CONST) {
700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ movq(CodeGenerator::ContextOperand(rsi, slot->index()),
702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                  kScratchRegister);
703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // No write barrier since the hole value is in old space.
704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else if (decl->fun() != NULL) {
705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          VisitForValue(decl->fun(), kAccumulator);
706e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(CodeGenerator::ContextOperand(rsi, slot->index()),
707e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                  result_register());
708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          int offset = Context::SlotOffset(slot->index());
7094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(rbx, rsi);
7104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ RecordWrite(rbx, offset, result_register(), rcx);
711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP: {
715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(rsi);
716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Push(var->name());
717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Declaration nodes are always introduced in one of two modes.
718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT(decl->mode() == Variable::VAR ||
719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block               decl->mode() == Variable::CONST);
720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        PropertyAttributes attr =
721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            (decl->mode() == Variable::VAR) ? NONE : READ_ONLY;
722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Push(Smi::FromInt(attr));
723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Push initial value, if any.
724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Note: For variables we must not push an initial value (such as
725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // 'undefined') because we may have a (legal) redeclaration and we
726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // must not destroy the current value.
727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (decl->mode() == Variable::CONST) {
728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ PushRoot(Heap::kTheHoleValueRootIndex);
729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else if (decl->fun() != NULL) {
730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          VisitForValue(decl->fun(), kStack);
731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else {
732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Push(Smi::FromInt(0));  // no initial value!
733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDeclareContextSlot, 4);
735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (prop != NULL) {
740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (decl->fun() != NULL || decl->mode() == Variable::CONST) {
741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // We are declaring a function or constant that rewrites to a
742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // property.  Use (keyed) IC to set the initial value.
743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->obj(), kStack);
744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->key(), kStack);
745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (decl->fun() != NULL) {
747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(decl->fun(), kAccumulator);
748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex);
750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ call(ic, RelocInfo::CODE_TARGET);
754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Absence of a test rax instruction following the call
755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // indicates that none of the load was inlined.
756e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ nop();
757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Value in rax is ignored (declarations are statements).  Receiver
759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // and key on stack are discarded.
760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(2);
761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
762d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
766d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
7673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
7683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(rsi);  // The context is the first argument.
7693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(pairs);
7703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(Smi::FromInt(is_eval_ ? 1 : 0));
7713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kDeclareGlobals, 3);
7723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
7733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
7743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
776d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
7773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ FunctionLiteral");
7783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Build the function boilerplate and instantiate it.
780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<JSFunction> boilerplate =
781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Compiler::BuildBoilerplate(expr, script_, this);
7823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (HasStackOverflow()) return;
7833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(boilerplate->IsBoilerplate());
7853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Create a new closure.
7873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(rsi);
7883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(boilerplate);
7893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kNewClosure, 2);
790e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, rax);
7913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
7923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
794d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
7953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ VariableProxy");
796e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  EmitVariableLoad(expr->var(), context_);
797e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
798e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
799e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
800d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableLoad(Variable* var,
801e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Expression::Context context) {
802d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Four cases: non-this global variables, lookup slots, all other
803d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // types of slots, and parameters that rewrite to explicit property
804d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // accesses on the arguments object.
805d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Slot* slot = var->slot();
806d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Property* property = var->AsProperty();
807d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
808d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (var->is_global() && !var->is_this()) {
8093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Comment cmnt(masm_, "Global variable");
8103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Use inline caching. Variable name is passed in rcx and the global
8113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // object on the stack.
8123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ push(CodeGenerator::GlobalObject());
813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ Move(rcx, var->name());
8143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
8153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
8163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // A test rax instruction following the call is used by the IC to
8173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // indicate that the inobject property case was inlined.  Ensure there
8183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is no test rax instruction here.
819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ nop();
820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    DropAndApply(1, context, rax);
821d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
822d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
823d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Lookup slot");
824d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ push(rsi);  // Context.
825d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ Push(var->name());
826d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
827d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Apply(context, rax);
828d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
829d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL) {
830d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
831d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            ? "Context slot"
832d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            : "Stack slot");
833e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Apply(context, slot);
834d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
836d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Rewritten parameter");
837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(property);
838d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Rewritten parameter accesses are of the form "slot[literal]".
839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
840e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the object is in a slot.
841e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT_NOT_NULL(object_var);
843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Slot* object_slot = object_var->slot();
844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(object_slot);
845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the object.
847e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    MemOperand object_loc = EmitSlotSearch(object_slot, rax);
848e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(object_loc);
849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the key is a smi.
851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key_literal = property->key()->AsLiteral();
852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(key_literal);
853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(key_literal->handle()->IsSmi());
854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the key.
856e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ Push(key_literal->handle());
857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
858e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Do a keyed property load.
859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ call(ic, RelocInfo::CODE_TARGET);
861e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Notice: We must not have a "test rax, ..." instruction after the
862e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // call. It is treated specially by the LoadIC code.
863e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ nop();
864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Drop key and object left on the stack by IC, and push the result.
865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    DropAndApply(2, context, rax);
8663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
8673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
870d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ RegExpLiteral");
8723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label done;
8733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Registers will be used as follows:
8743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // rdi = JS function.
8753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // rbx = literals array.
8763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // rax = regexp literal.
8773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
8783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
8793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int literal_offset =
8803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rax, FieldOperand(rbx, literal_offset));
8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &done);
8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Create regexp literal using runtime function
8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Result will be in rax.
8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(rbx);
8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
8883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(expr->pattern());
8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(expr->flags());
8903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
8913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&done);
892e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, rax);
893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
896d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
899e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Push(expr->constant_properties());
902e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->depth() > 1) {
903e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateObjectLiteral, 3);
9043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
905e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3);
906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
908e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
909e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in rax.
910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
911d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < expr->properties()->length(); i++) {
913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectLiteral::Property* property = expr->properties()->at(i);
914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = property->key();
917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ push(rax);  // Save result on the stack
920d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
923e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::CONSTANT:
924e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        UNREACHABLE();
925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (key->handle()->IsSymbol()) {
930e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          VisitForValue(value, kAccumulator);
931d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Move(rcx, key->handle());
9324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(rdx, Operand(rsp, 0));
933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ call(ic, RelocInfo::CODE_TARGET);
935e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ nop();
936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
939d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::PROTOTYPE:
940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(rsp, 0));  // Duplicate receiver.
941e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(key, kStack);
942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(value, kStack);
943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kSetProperty, 3);
944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::SETTER:
946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::GETTER:
947e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(rsp, 0));  // Duplicate receiver.
948e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(key, kStack);
949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Push(property->kind() == ObjectLiteral::Property::SETTER ?
950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                Smi::FromInt(1) :
951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                Smi::FromInt(0));
952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(value, kStack);
953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDefineAccessor, 4);
954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ApplyTOS(context_);
960e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
961e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Apply(context_, rax);
9623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
9643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
966d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
9673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
9683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
969e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
9703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
971e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Push(expr->constant_elements());
9723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (expr->depth() > 1) {
973e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
9743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
975e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
9763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
9793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
9813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
9823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* subexprs = expr->values();
9833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0, len = subexprs->length(); i < len; i++) {
9843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Expression* subexpr = subexprs->at(i);
9853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
9863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
9873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (subexpr->AsLiteral() != NULL ||
9883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        CompileTimeValue::IsCompileTimeValue(subexpr)) {
9893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      continue;
9903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
9913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
9933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(rax);
9943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
9953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
996e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(subexpr, kAccumulator);
9973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Store the subexpression value in the array's elements.
9993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(rbx, Operand(rsp, 0));  // Copy of array literal.
10003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
10013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1002e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ movq(FieldOperand(rbx, offset), result_register());
10033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Update the write barrier for the array store.
1005e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ RecordWrite(rbx, offset, result_register(), rcx);
10063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
10073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1008e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
1009e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ApplyTOS(context_);
1010e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
1011e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Apply(context_, rax);
10123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
10133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
10143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1016d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1018e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Literal* key = prop->key()->AsLiteral();
1019e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, key->handle());
1020e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1021e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Call(ic, RelocInfo::CODE_TARGET);
1022e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ nop();
1023e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1024e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1025e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1026d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1027e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1028e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1029e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Call(ic, RelocInfo::CODE_TARGET);
1030e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ nop();
1031e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1032e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1033e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1034d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitBinaryOp(Token::Value op,
1035e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     Expression::Context context) {
1036e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
1037e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  GenericBinaryOpStub stub(op,
1038e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_OVERWRITE,
1039e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_GENERIC_BINARY_FLAGS);
1040e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
1041e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context, rax);
1042e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1043e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1044e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1045d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var,
1046e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                               Expression::Context context) {
1047d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Three main cases: non-this global variables, lookup slots, and
1048d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // all other types of slots.  Left-hand-side parameters that rewrite
1049d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // to explicit property accesses do not reach here.
10503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(var != NULL);
10513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(var->is_global() || var->slot() != NULL);
1052d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Slot* slot = var->slot();
10533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (var->is_global()) {
1054d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT(!var->is_this());
1055d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Assignment to a global variable.  Use inline caching for the
1056d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // assignment.  Right-hand-side value is passed in rax, variable name in
10574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // rcx, and the global object in rdx.
10583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(rcx, var->name());
10594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ movq(rdx, CodeGenerator::GlobalObject());
10603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
10613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Call(ic, RelocInfo::CODE_TARGET);
10624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Apply(context, rax);
1063d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1064d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
1065d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ push(result_register());  // Value.
1066d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ push(rsi);  // Context.
1067d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ Push(var->name());
1068d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ CallRuntime(Runtime::kStoreContextSlot, 3);
1069d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Apply(context, rax);
1070d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else if (var->slot() != NULL) {
1072d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
1073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOCAL:
1074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
1075e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ movq(Operand(rbp, SlotOffset(slot)), result_register());
1076d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1077d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1078d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT: {
1079e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        MemOperand target = EmitSlotSearch(slot, rcx);
1080e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ movq(target, result_register());
1081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1082d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // RecordWrite may destroy all its register arguments.
1083e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ movq(rdx, result_register());
1084d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
1085e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ RecordWrite(rcx, offset, rdx, rbx);
1086d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
10873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
1088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1089d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP:
1090d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        UNREACHABLE();
1091d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
10923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1093e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Apply(context, result_register());
1094d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1095e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
1096e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Variables rewritten as properties are not treated as variables in
1097e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // assignments.
1098e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    UNREACHABLE();
10993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1103d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1104d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
1105d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
1106d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop != NULL);
1107d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop->key()->AsLiteral() != NULL);
11083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1109d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1110d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1111d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1112d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1113e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1114e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(Operand(rsp, kPointerSize));  // Receiver is now under value.
1115d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1116e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Move(rcx, prop->key()->AsLiteral()->handle());
11224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (expr->ends_initialization_block()) {
11234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ movq(rdx, Operand(rsp, 0));
11244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
11254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ pop(rdx);
11264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
1127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Call(ic, RelocInfo::CODE_TARGET);
1129e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ nop();
1130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(rax);  // Result of assignment, saved even if not needed.
1134d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(rsp, kPointerSize));  // Receiver is under value.
1135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1136d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(rax);
11374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    DropAndApply(1, context_, rax);
11384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
11394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Apply(context_, rax);
1140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1144d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
1146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1151e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1152e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Receiver is now under the key and value.
1153d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(rsp, 2 * kPointerSize));
1154d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1155e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1157d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1158e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1159e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Call(ic, RelocInfo::CODE_TARGET);
1162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This nop signals to the IC that there is no inlined code at the call
1163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // site for it to patch.
1164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ nop();
1165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(rax);  // Result of assignment, saved even if not needed.
1169e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Receiver is under the key and value.
1170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(rsp, 2 * kPointerSize));
1171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(rax);
1173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Receiver and key are still on stack.
1176e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  DropAndApply(2, context_, rax);
1177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1180d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) {
1181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Property");
1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* key = expr->key();
1183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Evaluate receiver.
1185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  VisitForValue(expr->obj(), kStack);
1186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (key->IsPropertyName()) {
1188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitNamedPropertyLoad(expr);
1189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Drop receiver left on the stack by IC.
1190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    DropAndApply(1, context_, rax);
1191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(expr->key(), kStack);
1193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitKeyedPropertyLoad(expr);
1194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Drop key and receiver left on the stack by IC.
1195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    DropAndApply(2, context_, rax);
1196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1200d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr,
1201e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       Handle<Object> ignored,
1202e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       RelocInfo::Mode mode) {
1203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the IC.
1204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
12053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
12063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
1207e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
12083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
12103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SetSourcePosition(expr->position());
12113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the IC initialization code.
1212e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
12133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
1214e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                                         in_loop);
1215e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Call(ic, mode);
1216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Restore context register.
1217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Discard the function left on TOS.
1219e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  DropAndApply(1, context_, rax);
1220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1223d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) {
1224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the call stub.
1225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
1227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
1228e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
1229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
1231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
1232e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE);
1233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ CallStub(&stub);
12343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore context register.
12353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
12363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Discard the function left on TOS.
1237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  DropAndApply(1, context_, rax);
1238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1241d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) {
1242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Call");
1243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* fun = expr->expression();
1244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Variable* var = fun->AsVariableProxy()->AsVariable();
1245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (var != NULL && var->is_possibly_eval()) {
1247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to the identifier 'eval'.
1248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    UNREACHABLE();
1249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (var != NULL && !var->is_this() && var->is_global()) {
1250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to a global variable.
1251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ Push(var->name());
1252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Push global object as receiver for the call IC lookup.
1253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(CodeGenerator::GlobalObject());
1254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
1255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (var != NULL && var->slot() != NULL &&
1256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block             var->slot()->type() == Slot::LOOKUP) {
1257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to a lookup slot.
1258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    UNREACHABLE();
1259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (fun->AsProperty() != NULL) {
1260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to an object property.
1261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Property* prop = fun->AsProperty();
1262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = prop->key()->AsLiteral();
1263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (key != NULL && key->handle()->IsSymbol()) {
1264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Call to a named property, use call IC.
1265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ Push(key->handle());
1266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->obj(), kStack);
1267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
1269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Call to a keyed property, use keyed load IC followed by function
1270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // call.
1271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->obj(), kStack);
1272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->key(), kStack);
1273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Record source code position for IC call.
1274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      SetSourcePosition(prop->position());
1275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ call(ic, RelocInfo::CODE_TARGET);
1277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // By emitting a nop we make sure that we do not have a "test rax,..."
1278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // instruction after the call it is treated specially by the LoadIC code.
1279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ nop();
1280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Drop key left on the stack by IC.
1281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
1282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Pop receiver.
1283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ pop(rbx);
1284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Push result (function).
1285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ push(rax);
1286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Push receiver object on stack.
1287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (prop->is_synthetic()) {
1288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ movq(rcx, CodeGenerator::GlobalObject());
1289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
1290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
1291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(rbx);
1292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      EmitCallWithStub(expr);
1294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
1296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to some other expression.  If the expression is an anonymous
1297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // function literal not called in a loop, mark it as one that should
1298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // also use the fast code generator.
1299d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    FunctionLiteral* lit = fun->AsFunctionLiteral();
1300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (lit != NULL &&
1301d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        lit->name()->Equals(Heap::empty_string()) &&
1302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        loop_depth() == 0) {
1303d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      lit->set_try_full_codegen(true);
1304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(fun, kStack);
1306d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load global receiver object.
1307d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ movq(rbx, CodeGenerator::GlobalObject());
1308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
1309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit function call.
1310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    EmitCallWithStub(expr);
1311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1315d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
1316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
1317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
1318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
1319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
1320d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push function on the stack.
1321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  VisitForValue(expr->expression(), kStack);
1322d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push global object (receiver).
1324d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ push(CodeGenerator::GlobalObject());
1325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1326d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
1327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
1329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
1330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
13313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
1334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
1335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
1336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Load function, arg_count into rdi and rax.
1338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Set(rax, arg_count);
1339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Function is in rsp[arg_count + 1].
1340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize));
1341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
1343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
1344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1345d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Replace function on TOS with result in rax, or pop it.
1346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  DropAndApply(1, context_, rax);
13473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
13483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1350d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
13513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ CallRuntime");
13523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* args = expr->arguments();
13533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
1355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Prepare for calling JS runtime function.
1356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ Push(expr->name());
1357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ movq(rax, CodeGenerator::GlobalObject());
1358d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
1359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
13603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Push the arguments ("left-to-right").
13623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
13633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
1364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
1365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1367d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
1368d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call the JS runtime function.
1369d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
1370d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                                           NOT_IN_LOOP);
1371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ call(ic, RelocInfo::CODE_TARGET);
1372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Restore context register.
1373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1374d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Discard the function left on TOS.
1375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    DropAndApply(1, context_, rax);
1376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(expr->function(), arg_count);
1378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Apply(context_, rax);
1379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1383d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
1385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
1386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
1387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
1388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (context_) {
1389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kUninitialized:
1390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
1391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kEffect:
1393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kValue:
1395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          switch (location_) {
1396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kAccumulator:
1397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex);
1398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
1399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kStack:
1400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ PushRoot(Heap::kUndefinedValueRootIndex);
1401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
1402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
1403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kTestValue:
1405d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Value is false so it's needed.
1406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          switch (location_) {
1407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kAccumulator:
1408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex);
1409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
1410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kStack:
1411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ PushRoot(Heap::kUndefinedValueRootIndex);
1412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
1413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
1414d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Fall through.
1415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case Expression::kTest:
1416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kValueTest:
1417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ jmp(false_label_);
1418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
1424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
1425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Label materialize_true, materialize_false, done;
1426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Initially assume a pure test context.  Notice that the labels are
1427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // swapped.
1428e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Label* if_true = false_label_;
1429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Label* if_false = true_label_;
1430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (context_) {
1431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kUninitialized:
1432d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
1433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kEffect:
1435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_true = &done;
1436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_false = &done;
1437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
1438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case Expression::kValue:
1439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_true = &materialize_false;
1440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_false = &materialize_true;
1441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kTest:
1443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kValueTest:
1445e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_false = &materialize_true;
1446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kTestValue:
1448e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_true = &materialize_false;
1449d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForControl(expr->expression(), if_true, if_false);
1452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Apply(context_, if_false, if_true);  // Labels swapped.
1453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
1457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
1458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      VariableProxy* proxy = expr->expression()->AsVariableProxy();
1459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (proxy != NULL &&
1460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          !proxy->var()->is_this() &&
1461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          proxy->var()->is_global()) {
1462d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        Comment cmnt(masm_, "Global variable");
1463d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(CodeGenerator::GlobalObject());
1464d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Move(rcx, proxy->name());
1465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Use a regular load, not a contextual load, to avoid a reference
1467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // error.
1468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Call(ic, RelocInfo::CODE_TARGET);
1469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ movq(Operand(rsp, 0), rax);
1470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else if (proxy != NULL &&
1471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                 proxy->var()->slot() != NULL &&
1472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                 proxy->var()->slot()->type() == Slot::LOOKUP) {
1473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(rsi);
1474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Push(proxy->name());
1475d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
1476d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(rax);
1477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
1478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // This expression cannot throw a reference error at the top level.
1479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(expr->expression(), kStack);
1480d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1481d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1482d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallRuntime(Runtime::kTypeof, 1);
1483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Apply(context_, rax);
1484d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1485d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1486d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1487d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Token::ADD: {
1488d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Comment cmt(masm_, "[ UnaryOperation (ADD)");
1489d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      VisitForValue(expr->expression(), kAccumulator);
1490d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Label no_conversion;
14914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Condition is_smi = masm_->CheckSmi(result_register());
1492d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ j(is_smi, &no_conversion);
1493d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ push(result_register());
1494d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
1495d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ bind(&no_conversion);
1496d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Apply(context_, result_register());
1497d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      break;
1498d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
1499d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
15004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::SUB: {
15014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (SUB)");
15024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      bool overwrite =
15034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          (expr->expression()->AsBinaryOperation() != NULL &&
15044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
15054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      GenericUnaryOpStub stub(Token::SUB, overwrite);
15064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // GenericUnaryOpStub expects the argument to be in the
15074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // accumulator register rax.
15084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      VisitForValue(expr->expression(), kAccumulator);
15094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
15104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Apply(context_, rax);
15114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
15124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
15134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
15144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::BIT_NOT: {
15154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
15164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      bool overwrite =
15174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          (expr->expression()->AsBinaryOperation() != NULL &&
15184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
15194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
15204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // GenericUnaryOpStub expects the argument to be in the
15214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // accumulator register rax.
15224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      VisitForValue(expr->expression(), kAccumulator);
15234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Avoid calling the stub for Smis.
15244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Label smi, done;
15254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Condition is_smi = masm_->CheckSmi(result_register());
15264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ j(is_smi, &smi);
15274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Non-smi: call stub leaving result in accumulator register.
15284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
15294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ jmp(&done);
15304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Perform operation directly on Smis.
15314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ bind(&smi);
15324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ SmiNot(result_register(), result_register());
15334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ bind(&done);
15344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Apply(context_, result_register());
15354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
15364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
15374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
1538d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
1539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
15403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
15413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
15423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1544d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
1545e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Comment cmnt(masm_, "[ CountOperation");
1546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1547e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Expression can only be a property, a global or a (parameter or local)
1548e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1550e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LhsKind assign_type = VARIABLE;
1551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
1552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In case of a property we use the uninitialized expression context
1553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // of the key to detect a named property.
1554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (prop != NULL) {
1555e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    assign_type =
1556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
1557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1558e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1559e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
1560e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
1561e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
1562e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Location saved_location = location_;
1563d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    location_ = kAccumulator;
1564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
1565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     Expression::kValue);
1566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    location_ = saved_location;
1567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else  {
1568e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
1569e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (expr->is_postfix() && context_ != Expression::kEffect) {
1570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Push(Smi::FromInt(0));
1571e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
1572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(prop->obj(), kStack);
1573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (assign_type == NAMED_PROPERTY) {
1574e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitNamedPropertyLoad(prop);
1575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
1576e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->key(), kStack);
1577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitKeyedPropertyLoad(prop);
1578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
1579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1581d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Call ToNumber only if operand is not a smi.
1582d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label no_conversion;
1583d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Condition is_smi;
1584d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  is_smi = masm_->CheckSmi(rax);
1585d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ j(is_smi, &no_conversion);
1586d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ push(rax);
1587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
1588d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&no_conversion);
1589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
1591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
1592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    switch (context_) {
1593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kUninitialized:
1594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        UNREACHABLE();
1595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kEffect:
1596e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Do not save result.
1597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        break;
1598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kValue:
1599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kTest:
1600e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kValueTest:
1601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kTestValue:
1602e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Save the result on the stack. If we have a named or keyed property
1603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // we store the result under the receiver that is currently on top
1604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // of the stack.
1605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        switch (assign_type) {
1606e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          case VARIABLE:
1607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            __ push(rax);
1608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            break;
1609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          case NAMED_PROPERTY:
1610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            __ movq(Operand(rsp, kPointerSize), rax);
1611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            break;
1612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          case KEYED_PROPERTY:
1613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            __ movq(Operand(rsp, 2 * kPointerSize), rax);
1614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            break;
1615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
1616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        break;
1617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
1618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1620d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Inline smi case if we are in a loop.
1621d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label stub_call, done;
1622d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (loop_depth() > 0) {
1623d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
1624d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiAddConstant(rax, rax, Smi::FromInt(1));
1625d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
1626d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiSubConstant(rax, rax, Smi::FromInt(1));
1627d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
1628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ j(overflow, &stub_call);
1629d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // We could eliminate this smi check if we split the code at
1630d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // the first smi check before calling ToNumber.
1631d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    is_smi = masm_->CheckSmi(rax);
1632d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ j(is_smi, &done);
1633d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ bind(&stub_call);
1634d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Call stub. Undo operation first.
1635d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
1636d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiSubConstant(rax, rax, Smi::FromInt(1));
1637d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
1638d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiAddConstant(rax, rax, Smi::FromInt(1));
1639d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
1640d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call stub for +1/-1.
1642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  GenericBinaryOpStub stub(expr->binary_op(),
1643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_OVERWRITE,
1644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_GENERIC_BINARY_FLAGS);
16454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  stub.GenerateCall(masm_, rax, Smi::FromInt(1));
1646d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
1647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in rax.
1649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
1650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case VARIABLE:
1651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
1652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               Expression::kEffect);
1654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // For all contexts except kEffect: We have the result on
1655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
1656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (context_ != Expression::kEffect) {
1657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          ApplyTOS(context_);
1658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
1659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
1660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               context_);
1662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
1663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
1664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
1665e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Move(rcx, prop->key()->AsLiteral()->handle());
16664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ pop(rdx);
1667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ call(ic, RelocInfo::CODE_TARGET);
1669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // This nop signals to the IC that there is no inlined code at the call
1670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // site for it to patch.
1671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ nop();
1672e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
1673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (context_ != Expression::kEffect) {
1674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          ApplyTOS(context_);
1675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
1676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
16774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        Apply(context_, rax);
1678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
1679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
1680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
1681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
1682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ call(ic, RelocInfo::CODE_TARGET);
1684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // This nop signals to the IC that there is no inlined code at the call
1685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // site for it to patch.
1686e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ nop();
1687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
1688e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ Drop(2);  // Result is on the stack under the key and the receiver.
1689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (context_ != Expression::kEffect) {
1690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          ApplyTOS(context_);
1691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
1692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
1693e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        DropAndApply(2, context_, rax);
1694e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
1695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
1696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
1697e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1700d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
1701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ BinaryOperation");
1702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
1703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::COMMA:
1704e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->left());
1705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Visit(expr->right());
1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::OR:
1709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::AND:
1710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      EmitLogicalOperation(expr);
1711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::ADD:
1714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::SUB:
1715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::DIV:
1716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::MOD:
1717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::MUL:
1718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::BIT_OR:
1719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::BIT_AND:
1720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::BIT_XOR:
1721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::SHL:
1722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::SHR:
1723e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::SAR:
1724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->left(), kStack);
1725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kAccumulator);
1726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitBinaryOp(expr->op(), context_);
1727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
1730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
17313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
17333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1735d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
1736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
1737e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
1739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
1740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label materialize_true, materialize_false, done;
1741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Initially assume we are in a test context.
1742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label* if_true = true_label_;
1743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label* if_false = false_label_;
1744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context_) {
1745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
1746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
1747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
1749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if_true = &done;
1750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if_false = &done;
1751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
1752e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
1753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if_true = &materialize_true;
1754e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if_false = &materialize_false;
1755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTest:
1757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValueTest:
1759e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if_true = &materialize_true;
1760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTestValue:
1762e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if_false = &materialize_false;
1763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
17643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  VisitForValue(expr->left(), kStack);
1767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
1768e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
1769e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kStack);
1770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
1771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CompareRoot(rax, Heap::kTrueValueRootIndex);
1772e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(equal, if_true);
1773e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
1774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
17753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1776d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
1777e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kStack);
1778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      InstanceofStub stub;
1779d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
1780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ testq(rax, rax);
1781e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(zero, if_true);  // The stub returns 0 for true.
1782e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
1783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
1787e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kAccumulator);
1788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Condition cc = no_condition;
1789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      bool strict = false;
1790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (expr->op()) {
1791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::EQ_STRICT:
1792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          strict = true;
1793e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Fall through.
1794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::EQ:
1795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = equal;
1796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rdx);
1797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LT:
1799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
1800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rdx);
1801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GT:
1803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Reverse left and right sizes to obtain ECMA-262 conversion order.
1804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
1805e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(rdx, result_register());
1806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rax);
1807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block         break;
1808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LTE:
1809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Reverse left and right sizes to obtain ECMA-262 conversion order.
1810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
1811e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(rdx, result_register());
1812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rax);
1813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GTE:
1815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
1816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rdx);
1817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::IN:
1819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::INSTANCEOF:
1820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default:
1821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
1822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // The comparison stub expects the smi vs. smi case to be handled
1825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // before it is called.
1826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Label slow_case;
1827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ JumpIfNotBothSmi(rax, rdx, &slow_case);
1828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ SmiCompare(rdx, rax);
1829e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(cc, if_true);
1830e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
1831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ bind(&slow_case);
1833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      CompareStub stub(cc, strict);
1834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
1835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ testq(rax, rax);
1836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(cc, if_true);
1837e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
1838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
18393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
18403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1841e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
1842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
1843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, if_true, if_false);
1844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1847d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
1848e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, rax);
1850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1853d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::result_register() { return rax; }
1854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1855e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1856d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::context_register() { return rsi; }
1857e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1858e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1859d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
1860e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(IsAligned(frame_offset, kPointerSize));
1861e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(Operand(rbp, frame_offset), value);
18623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
18633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1865d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
1866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(dst, CodeGenerator::ContextOperand(rsi, context_index));
1867e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1868e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1870e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ----------------------------------------------------------------------------
1871e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support.
1872e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1874d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() {
1875e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rdx));
1876e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rcx));
1877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Cook return address on top of stack (smi encoded Code* delta)
1878e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(rdx, Operand(rsp, 0));
1879e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, masm_->CodeObject());
1880e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ subq(rdx, rcx);
1881e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Integer32ToSmi(rdx, rdx);
1882e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(Operand(rsp, 0), rdx);
1883e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store result register while executing finally block.
1884e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
1885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1886e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1887e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1888d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() {
1889e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rdx));
1890e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rcx));
1891e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Restore result register from stack.
1892e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(result_register());
1893e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Uncook return address.
1894e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(rdx, Operand(rsp, 0));
1895e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ SmiToInteger32(rdx, rdx);
1896e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, masm_->CodeObject());
1897e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ addq(rdx, rcx);
1898e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(Operand(rsp, 0), rdx);
1899e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // And return.
1900e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ret(0);
1901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef __
1905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
19073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} }  // namespace v8::internal
1908