full-codegen-x64.cc revision 402d937239b0e2fd11bf2f4fe972ad78aa9fd481
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.
543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ASSERT(info_ == NULL);
563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  info_ = info;
573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  SetFunctionPosition(function());
583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (mode == PRIMARY) {
604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ push(rbp);  // Caller's frame pointer.
614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ movq(rbp, rsp);
624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ push(rsi);  // Callee's context.
634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ push(rdi);  // Callee's JS Function.
644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    { Comment cmnt(masm_, "[ Allocate locals");
663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int locals_count = scope()->num_stack_slots();
674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      if (locals_count == 1) {
684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        __ PushRoot(Heap::kUndefinedValueRootIndex);
694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      } else if (locals_count > 1) {
704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        for (int i = 0; i < locals_count; i++) {
724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ push(rdx);
734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        }
74d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
75d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
76d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    bool function_in_register = true;
784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // Possibly allocate a local context.
803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if (scope()->num_heap_slots() > 0) {
814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmnt(masm_, "[ Allocate local context");
824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Argument to NewContext is the function, which is still in rdi.
834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ push(rdi);
844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallRuntime(Runtime::kNewContext, 1);
854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      function_in_register = false;
864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Context is returned in both rax and rsi.  It replaces the context
874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // passed to us.  It's saved in the stack and kept live in rsi.
884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Copy any necessary parameters into the context.
913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int num_parameters = scope()->num_parameters();
924515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      for (int i = 0; i < num_parameters; i++) {
933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        Slot* slot = scope()->parameter(i)->slot();
944515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        if (slot != NULL && slot->type() == Slot::CONTEXT) {
954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          int parameter_offset = StandardFrameConstants::kCallerSPOffset +
964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                     (num_parameters - 1 - i) * kPointerSize;
974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // Load parameter from stack.
984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(rax, Operand(rbp, parameter_offset));
994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // Store it in the context.
1004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          int context_offset = Context::SlotOffset(slot->index());
1014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(Operand(rsi, context_offset), rax);
1024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // Update the write barrier. This clobbers all involved
1034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // registers, so we have use a third register to avoid
1044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          // clobbering rsi.
1054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(rcx, rsi);
1064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ RecordWrite(rcx, context_offset, rax, rbx);
1074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        }
108d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // Possibly allocate an arguments object.
1123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    Variable* arguments = scope()->arguments()->AsVariable();
1134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (arguments != NULL) {
1144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Arguments object must be allocated after the context object, in
1154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // case the "arguments" or ".arguments" variables are in the context.
1164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmnt(masm_, "[ Allocate arguments object");
1174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      if (function_in_register) {
1184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        __ push(rdi);
1194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      } else {
1204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      }
1224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // The receiver is just before the parameters on the caller's stack.
1233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int offset = scope()->num_parameters() * kPointerSize;
1243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      __ lea(rdx,
1253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu             Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
1264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ push(rdx);
1273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      __ Push(Smi::FromInt(scope()->num_parameters()));
1284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Arguments to ArgumentsAccessStub:
1294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      //   function, receiver address, parameter count.
1304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // The stub will rewrite receiver and parameter count if the previous
1314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // stack frame was an arguments adapter frame.
1324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
1334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
1344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Store new arguments object in both "arguments" and ".arguments" slots.
1354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ movq(rcx, rax);
1364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Move(arguments->slot(), rax, rbx, rdx);
1374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Slot* dot_arguments_slot =
1383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          scope()->arguments_shadow()->AsVariable()->slot();
1394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Move(dot_arguments_slot, rcx, rbx, rdx);
140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
143e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  { Comment cmnt(masm_, "[ Declarations");
1443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    VisitDeclarations(scope()->declarations());
145e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
146e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ Stack check");
1483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label ok;
1493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
1503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(above_equal, &ok);
1513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    StackCheckStub stub;
1523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CallStub(&stub);
1533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&ok);
1543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (FLAG_trace) {
1573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CallRuntime(Runtime::kTraceEnter, 0);
1583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ Body");
161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    VisitStatements(function()->body());
163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit a 'return undefined' in case control fell off the end of the body.
1683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    EmitReturnSequence(function()->end_position());
170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
174d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitReturnSequence(int position) {
175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ jmp(&return_label_);
178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
1813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(rax);
1823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ CallRuntime(Runtime::kTraceExit, 1);
1833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG
185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Add a label for checking the size of the code used for returning.
186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Label check_exit_codesize;
187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    masm_->bind(&check_exit_codesize);
188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CodeGenerator::RecordPositions(masm_, position);
1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ RecordJSReturn();
1913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Do not use the leave instruction here because it is too short to
1923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // patch with the code required by the debugger.
1933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(rsp, rbp);
1943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ pop(rbp);
1953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    __ ret((scope()->num_parameters() + 1) * kPointerSize);
1963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT
1973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Add padding that will be overwritten by a debugger breakpoint.  We
1983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7
1993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // (3 + 1 + 3).
200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    const int kPadding = Assembler::kJSReturnSequenceLength - 7;
2013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    for (int i = 0; i < kPadding; ++i) {
2023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      masm_->int3();
2033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Check that the size of the code used for returning matches what is
205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // expected by the debugger.
206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_EQ(Assembler::kJSReturnSequenceLength,
207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
2083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#endif
2093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
2113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
213d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Register reg) {
214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
217e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
219e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Nothing to do.
220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValue:
223e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Move value into place.
224e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
225e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
226e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (!reg.is(result_register())) __ movq(result_register(), reg);
227e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
228e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
229e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(reg);
230e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
231e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTest:
235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // For simplicity we always test the accumulator register.
236e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!reg.is(result_register())) __ movq(result_register(), reg);
237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
239e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
241e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!reg.is(result_register())) __ movq(result_register(), reg);
243e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
256d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Slot* slot) {
257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Nothing to do.
262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue: {
264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      MemOperand slot_operand = EmitSlotSearch(slot, result_register());
265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(result_register(), slot_operand);
268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Memory operands can be pushed directly.
271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(slot_operand);
272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Move(result_register(), slot);
279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Move(result_register(), slot);
285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
298d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Literal* lit) {
299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Nothing to do.
304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Move(result_register(), lit->handle());
309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Push(lit->handle());
312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Move(result_register(), lit->handle());
318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Move(result_register(), lit->handle());
324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
337d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ApplyTOS(Expression::Context context) {
338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ pop(result_register());
358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
359e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
362d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTestValue:
363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(result_register(), Operand(rsp, 0));
369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
374d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
377d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DropAndApply(int count,
378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     Expression::Context context,
379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     Register reg) {
380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(count > 0);
381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!reg.is(rsp));
382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(count);
388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValue:
391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Drop(count);
394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (!reg.is(result_register())) __ movq(result_register(), reg);
395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (count > 1) __ Drop(count - 1);
398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(Operand(rsp, 0), reg);
399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(count);
405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!reg.is(result_register())) __ movq(result_register(), reg);
406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTestValue:
411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Drop(count);
414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (!reg.is(result_register())) __ movq(result_register(), reg);
415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if (count > 1) __ Drop(count - 1);
418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(result_register(), reg);
419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(Operand(rsp, 0), result_register());
420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      DoTest(context);
423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
428d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context,
429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                              Label* materialize_true,
430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                              Label* materialize_false) {
431e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT_EQ(materialize_true, materialize_false);
436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(materialize_true);
437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue: {
440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Label done;
441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_true);
444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Move(result_register(), Factory::true_value());
445e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(&done);
446e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_false);
447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Move(result_register(), Factory::false_value());
448e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_true);
451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Push(Factory::true_value());
452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(&done);
453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ bind(materialize_false);
454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Push(Factory::false_value());
455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(&done);
458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
461e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(materialize_true);
466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
468e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Move(result_register(), Factory::true_value());
469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
470e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Push(Factory::true_value());
472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
473e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
474e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(true_label_);
475e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(materialize_false);
479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Move(result_register(), Factory::false_value());
482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ Push(Factory::false_value());
485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(false_label_);
488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
490d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
492d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
493d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DoTest(Expression::Context context) {
494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // The value to test is in the accumulator.  If the value might be needed
495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // on the stack (value/test and test/value contexts with a stack location
496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // desired), then the value is already duplicated on the stack.
497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_NE(NULL, true_label_);
498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_NE(NULL, false_label_);
499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In value/test and test/value expression contexts with stack as the
501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // desired location, there is already an extra value on the stack.  Use a
502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // label to discard it if unneeded.
503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label discard;
504e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label* if_true = true_label_;
505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label* if_false = false_label_;
506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (context) {
507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_false = &discard;
519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
523e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
524e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
525e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
526e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_true = &discard;
528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the inlined tests assumed by the stub.
534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex);
535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_true);
538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CompareRoot(result_register(), Heap::kFalseValueRootIndex);
539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, kSmiTag);
541e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ SmiCompare(result_register(), Smi::FromInt(0));
542e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
543e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Condition is_smi = masm_->CheckSmi(result_register());
544e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(is_smi, if_true);
545e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save a copy of the value if it may be needed and isn't already saved.
547e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
548e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValue:
551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTest:
553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
555e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
558e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
559e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
560e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
561d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ push(result_register());
567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
568e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
569e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
571e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
574e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call the ToBoolean stub for all other cases.
575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ToBooleanStub stub;
576e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ testq(rax, rax);
579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // The stub returns nonzero for true.  Complete based on the context.
581e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context) {
582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kUninitialized:
583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kEffect:
584e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTest:
588e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(not_zero, true_label_);
589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(false_label_);
590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValueTest:
593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(zero, &discard);
596e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(true_label_);
598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
600e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(not_zero, true_label_);
601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ bind(&discard);
604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ jmp(false_label_);
606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kTestValue:
609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (location_) {
610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kAccumulator:
611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(not_zero, &discard);
612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ pop(result_register());
613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ jmp(false_label_);
614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case kStack:
616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ j(zero, false_label_);
617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
619d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ bind(&discard);
620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
621d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ jmp(true_label_);
622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
627d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (slot->type()) {
629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::PARAMETER:
630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOCAL:
631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return Operand(rbp, SlotOffset(slot));
632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::CONTEXT: {
633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      int context_chain_length =
6343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          scope()->ContextChainLength(slot->var()->scope());
635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ LoadContext(scratch, context_chain_length);
636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return CodeGenerator::ContextOperand(scratch, slot->index());
637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
638e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOOKUP:
639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
640d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  UNREACHABLE();
642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return Operand(rax, 0);
643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
644d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
646d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) {
647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(source, destination);
648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(destination, location);
649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
650d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
652d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst,
653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register src,
654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch1,
655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch2) {
656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(dst->type() != Slot::LOOKUP);  // Not yet implemented.
657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!scratch1.is(src) && !scratch2.is(src));
658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(dst, scratch1);
659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(location, src);
660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (dst->type() == Slot::CONTEXT) {
662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ RecordWrite(scratch1, offset, src, scratch2);
664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
666d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
668d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) {
669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Declaration");
670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Variable* var = decl->proxy()->var();
671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(var != NULL);  // Must have been resolved.
672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Slot* slot = var->slot();
673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = var->AsProperty();
674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (slot != NULL) {
676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
677e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOCAL:
679d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (decl->mode() == Variable::CONST) {
680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister);
682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else if (decl->fun() != NULL) {
683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          VisitForValue(decl->fun(), kAccumulator);
684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(Operand(rbp, SlotOffset(slot)), result_register());
685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT:
689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // We bypass the general EmitSlotSearch because we know more about
690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // this specific context.
691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // The variable in the decl always resides in the current context.
6933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        ASSERT_EQ(0, scope()->ContextChainLength(var->scope()));
694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (FLAG_debug_code) {
695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Check if we have the correct context pointer.
696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ movq(rbx,
697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                  CodeGenerator::ContextOperand(rsi, Context::FCONTEXT_INDEX));
698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ cmpq(rbx, rsi);
699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Check(equal, "Unexpected declaration in current context.");
700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (decl->mode() == Variable::CONST) {
702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ movq(CodeGenerator::ContextOperand(rsi, slot->index()),
704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                  kScratchRegister);
705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // No write barrier since the hole value is in old space.
706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else if (decl->fun() != NULL) {
707e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          VisitForValue(decl->fun(), kAccumulator);
708e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(CodeGenerator::ContextOperand(rsi, slot->index()),
709e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                  result_register());
710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          int offset = Context::SlotOffset(slot->index());
7114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(rbx, rsi);
7124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ RecordWrite(rbx, offset, result_register(), rcx);
713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP: {
717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(rsi);
718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Push(var->name());
719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Declaration nodes are always introduced in one of two modes.
720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT(decl->mode() == Variable::VAR ||
721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block               decl->mode() == Variable::CONST);
722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        PropertyAttributes attr =
723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            (decl->mode() == Variable::VAR) ? NONE : READ_ONLY;
724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Push(Smi::FromInt(attr));
725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Push initial value, if any.
726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Note: For variables we must not push an initial value (such as
727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // 'undefined') because we may have a (legal) redeclaration and we
728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // must not destroy the current value.
729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (decl->mode() == Variable::CONST) {
730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ PushRoot(Heap::kTheHoleValueRootIndex);
731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else if (decl->fun() != NULL) {
732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          VisitForValue(decl->fun(), kStack);
733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else {
734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Push(Smi::FromInt(0));  // no initial value!
735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDeclareContextSlot, 4);
737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (prop != NULL) {
742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (decl->fun() != NULL || decl->mode() == Variable::CONST) {
743d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // We are declaring a function or constant that rewrites to a
744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // property.  Use (keyed) IC to set the initial value.
745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->obj(), kStack);
746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->key(), kStack);
747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (decl->fun() != NULL) {
749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(decl->fun(), kAccumulator);
750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex);
752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ call(ic, RelocInfo::CODE_TARGET);
756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Absence of a test rax instruction following the call
757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // indicates that none of the load was inlined.
758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ nop();
759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Value in rax is ignored (declarations are statements).  Receiver
761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // and key on stack are discarded.
762e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(2);
763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
768d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
7693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
7703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(rsi);  // The context is the first argument.
7713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(pairs);
7723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  __ Push(Smi::FromInt(is_eval() ? 1 : 0));
7733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kDeclareGlobals, 3);
7743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
7753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
7763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
778d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
7793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ FunctionLiteral");
7803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Build the function boilerplate and instantiate it.
782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<JSFunction> boilerplate =
7833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      Compiler::BuildBoilerplate(expr, script(), this);
7843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (HasStackOverflow()) return;
7853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(boilerplate->IsBoilerplate());
7873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Create a new closure.
7893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(rsi);
7903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(boilerplate);
7913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kNewClosure, 2);
792e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, rax);
7933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
7943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
796d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
7973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ VariableProxy");
798e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  EmitVariableLoad(expr->var(), context_);
799e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
800e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
801e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
802d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableLoad(Variable* var,
803e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Expression::Context context) {
804d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Four cases: non-this global variables, lookup slots, all other
805d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // types of slots, and parameters that rewrite to explicit property
806d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // accesses on the arguments object.
807d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Slot* slot = var->slot();
808d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Property* property = var->AsProperty();
809d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
810d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (var->is_global() && !var->is_this()) {
8113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Comment cmnt(masm_, "Global variable");
8123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Use inline caching. Variable name is passed in rcx and the global
8133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // object on the stack.
8143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ push(CodeGenerator::GlobalObject());
815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ Move(rcx, var->name());
8163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
8173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
8183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // A test rax instruction following the call is used by the IC to
8193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // indicate that the inobject property case was inlined.  Ensure there
8203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is no test rax instruction here.
821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ nop();
822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    DropAndApply(1, context, rax);
823d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
824d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
825d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Lookup slot");
826d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ push(rsi);  // Context.
827d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ Push(var->name());
828d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
829d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Apply(context, rax);
830d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
831d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL) {
832d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
833d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            ? "Context slot"
834d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            : "Stack slot");
835e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Apply(context, slot);
836d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
838d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Rewritten parameter");
839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(property);
840d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Rewritten parameter accesses are of the form "slot[literal]".
841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the object is in a slot.
843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT_NOT_NULL(object_var);
845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Slot* object_slot = object_var->slot();
846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(object_slot);
847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the object.
849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    MemOperand object_loc = EmitSlotSearch(object_slot, rax);
850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(object_loc);
851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
852e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the key is a smi.
853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key_literal = property->key()->AsLiteral();
854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(key_literal);
855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(key_literal->handle()->IsSmi());
856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the key.
858e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ Push(key_literal->handle());
859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
860e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Do a keyed property load.
861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ call(ic, RelocInfo::CODE_TARGET);
863e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Notice: We must not have a "test rax, ..." instruction after the
864e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // call. It is treated specially by the LoadIC code.
865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ nop();
866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Drop key and object left on the stack by IC, and push the result.
867e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    DropAndApply(2, context, rax);
8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
872d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ RegExpLiteral");
8743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label done;
8753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Registers will be used as follows:
8763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // rdi = JS function.
8773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // rbx = literals array.
8783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // rax = regexp literal.
8793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
8803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int literal_offset =
8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rax, FieldOperand(rbx, literal_offset));
8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &done);
8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Create regexp literal using runtime function
8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Result will be in rax.
8883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(rbx);
8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
8903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(expr->pattern());
8913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(expr->flags());
8923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
8933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&done);
894e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, rax);
895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
898d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
901e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Push(expr->constant_properties());
904e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->depth() > 1) {
905e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateObjectLiteral, 3);
9063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
907e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3);
908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
910e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
911e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in rax.
912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < expr->properties()->length(); i++) {
915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectLiteral::Property* property = expr->properties()->at(i);
916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = property->key();
919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
920d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ push(rax);  // Save result on the stack
922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
923d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::CONSTANT:
926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        UNREACHABLE();
927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
931d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (key->handle()->IsSymbol()) {
932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          VisitForValue(value, kAccumulator);
933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Move(rcx, key->handle());
9344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(rdx, Operand(rsp, 0));
935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ call(ic, RelocInfo::CODE_TARGET);
937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ nop();
938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
939d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::PROTOTYPE:
942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(rsp, 0));  // Duplicate receiver.
943e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(key, kStack);
944e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(value, kStack);
945d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kSetProperty, 3);
946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
947e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::SETTER:
948d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::GETTER:
949e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(rsp, 0));  // Duplicate receiver.
950e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(key, kStack);
951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Push(property->kind() == ObjectLiteral::Property::SETTER ?
952d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                Smi::FromInt(1) :
953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                Smi::FromInt(0));
954e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(value, kStack);
955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDefineAccessor, 4);
956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
960e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
961e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ApplyTOS(context_);
962e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
963e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Apply(context_, rax);
9643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
9663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
968d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
9693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
9703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
971e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
9723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
973e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Push(expr->constant_elements());
9743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (expr->depth() > 1) {
975e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
9763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
977e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
9783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
9813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
9833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
9843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* subexprs = expr->values();
9853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0, len = subexprs->length(); i < len; i++) {
9863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Expression* subexpr = subexprs->at(i);
9873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
9883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
9893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (subexpr->AsLiteral() != NULL ||
9903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        CompileTimeValue::IsCompileTimeValue(subexpr)) {
9913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      continue;
9923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
9933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
9953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(rax);
9963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
9973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
998e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(subexpr, kAccumulator);
9993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Store the subexpression value in the array's elements.
10013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(rbx, Operand(rsp, 0));  // Copy of array literal.
10023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
10033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1004e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ movq(FieldOperand(rbx, offset), result_register());
10053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Update the write barrier for the array store.
1007e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ RecordWrite(rbx, offset, result_register(), rcx);
10083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
10093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1010e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
1011e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ApplyTOS(context_);
1012e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
1013e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Apply(context_, rax);
10143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
10153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
10163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1018402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1019402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Comment cmnt(masm_, "[ Assignment");
1020402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ASSERT(expr->op() != Token::INIT_CONST);
1021402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Left-hand side can only be a property, a global or a (parameter or local)
1022402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1023402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1024402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LhsKind assign_type = VARIABLE;
1025402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Property* prop = expr->target()->AsProperty();
1026402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (prop != NULL) {
1027402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    assign_type =
1028402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
1029402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1030402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1031402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate LHS expression.
1032402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1033402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1034402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Nothing to do here.
1035402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1036402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1037402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1038402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // We need the receiver both on the stack and in the accumulator.
1039402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        VisitForValue(prop->obj(), kAccumulator);
1040402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1041402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
1042402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        VisitForValue(prop->obj(), kStack);
1043402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1044402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1045402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1046402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      VisitForValue(prop->obj(), kStack);
1047402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      VisitForValue(prop->key(), kStack);
1048402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1049402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1050402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1051402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // If we have a compound assignment: Get value of LHS expression and
1052402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // store in on top of the stack.
1053402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
1054402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Location saved_location = location_;
1055402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = kStack;
1056402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    switch (assign_type) {
1057402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      case VARIABLE:
1058402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        EmitVariableLoad(expr->target()->AsVariableProxy()->var(),
1059402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                         Expression::kValue);
1060402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        break;
1061402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      case NAMED_PROPERTY:
1062402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        EmitNamedPropertyLoad(prop);
1063402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1064402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        break;
1065402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      case KEYED_PROPERTY:
1066402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        EmitKeyedPropertyLoad(prop);
1067402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1068402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        break;
1069402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1070402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = saved_location;
1071402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1072402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1073402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate RHS expression.
1074402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Expression* rhs = expr->value();
1075402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  VisitForValue(rhs, kAccumulator);
1076402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1077402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // If we have a compound assignment: Apply operator.
1078402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
1079402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Location saved_location = location_;
1080402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = kAccumulator;
1081402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    EmitBinaryOp(expr->binary_op(), Expression::kValue);
1082402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    location_ = saved_location;
1083402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1084402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1085402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Record source position before possible IC call.
1086402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  SetSourcePosition(expr->position());
1087402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1088402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Store the value.
1089402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1090402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1091402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1092402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                             context_);
1093402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1094402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1095402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitNamedPropertyAssignment(expr);
1096402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1097402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1098402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitKeyedPropertyAssignment(expr);
1099402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1100402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1101402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1102402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1103402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1104d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1105e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1106e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Literal* key = prop->key()->AsLiteral();
1107e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, key->handle());
1108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1109e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Call(ic, RelocInfo::CODE_TARGET);
1110e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ nop();
1111e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1112e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1113e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1114d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1115e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1116e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1117e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Call(ic, RelocInfo::CODE_TARGET);
1118e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ nop();
1119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1122d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitBinaryOp(Token::Value op,
1123e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     Expression::Context context) {
1124e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
1125e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  GenericBinaryOpStub stub(op,
1126e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_OVERWRITE,
1127e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_GENERIC_BINARY_FLAGS);
1128e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
1129e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context, rax);
1130e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1131e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1132e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1133d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var,
1134e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                               Expression::Context context) {
1135d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Three main cases: non-this global variables, lookup slots, and
1136d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // all other types of slots.  Left-hand-side parameters that rewrite
1137d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // to explicit property accesses do not reach here.
11383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(var != NULL);
11393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(var->is_global() || var->slot() != NULL);
1140d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Slot* slot = var->slot();
11413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (var->is_global()) {
1142d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT(!var->is_this());
1143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Assignment to a global variable.  Use inline caching for the
1144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // assignment.  Right-hand-side value is passed in rax, variable name in
11454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // rcx, and the global object in rdx.
11463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(rcx, var->name());
11474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ movq(rdx, CodeGenerator::GlobalObject());
11483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
11493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Call(ic, RelocInfo::CODE_TARGET);
11504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Apply(context, rax);
1151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1152d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
1153d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ push(result_register());  // Value.
1154d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ push(rsi);  // Context.
1155d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ Push(var->name());
1156d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ CallRuntime(Runtime::kStoreContextSlot, 3);
1157d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Apply(context, rax);
1158d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1159e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else if (var->slot() != NULL) {
1160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
1161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOCAL:
1162e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
1163e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ movq(Operand(rbp, SlotOffset(slot)), result_register());
1164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT: {
1167e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        MemOperand target = EmitSlotSearch(slot, rcx);
1168e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ movq(target, result_register());
1169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // RecordWrite may destroy all its register arguments.
1171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ movq(rdx, result_register());
1172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
1173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ RecordWrite(rcx, offset, rdx, rbx);
1174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
11753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
1176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP:
1178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        UNREACHABLE();
1179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
11803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1181e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Apply(context, result_register());
1182d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1183e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
1184e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Variables rewritten as properties are not treated as variables in
1185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // assignments.
1186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    UNREACHABLE();
11873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1191d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
1193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
1194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop != NULL);
1195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop->key()->AsLiteral() != NULL);
11963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1201e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1202e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(Operand(rsp, kPointerSize));  // Receiver is now under value.
1203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1204e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1207e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1208e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Move(rcx, prop->key()->AsLiteral()->handle());
12104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (expr->ends_initialization_block()) {
12114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ movq(rdx, Operand(rsp, 0));
12124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
12134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ pop(rdx);
12144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
1215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Call(ic, RelocInfo::CODE_TARGET);
1217e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ nop();
1218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(rax);  // Result of assignment, saved even if not needed.
1222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(rsp, kPointerSize));  // Receiver is under value.
1223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(rax);
12254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    DropAndApply(1, context_, rax);
12264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
12274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Apply(context_, rax);
1228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1232d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
1234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1239e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Receiver is now under the key and value.
1241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(rsp, 2 * kPointerSize));
1242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1243e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Call(ic, RelocInfo::CODE_TARGET);
1250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This nop signals to the IC that there is no inlined code at the call
1251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // site for it to patch.
1252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ nop();
1253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(rax);  // Result of assignment, saved even if not needed.
1257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Receiver is under the key and value.
1258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(rsp, 2 * kPointerSize));
1259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(rax);
1261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Receiver and key are still on stack.
1264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  DropAndApply(2, context_, rax);
1265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1268d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) {
1269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Property");
1270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* key = expr->key();
1271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Evaluate receiver.
1273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  VisitForValue(expr->obj(), kStack);
1274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (key->IsPropertyName()) {
1276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitNamedPropertyLoad(expr);
1277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Drop receiver left on the stack by IC.
1278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    DropAndApply(1, context_, rax);
1279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(expr->key(), kStack);
1281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitKeyedPropertyLoad(expr);
1282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Drop key and receiver left on the stack by IC.
1283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    DropAndApply(2, context_, rax);
1284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1288d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr,
1289402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                       Handle<Object> name,
1290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       RelocInfo::Mode mode) {
1291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the IC.
1292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
12933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
12943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
1295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
12963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1297402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ Move(rcx, name);
1298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
12993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SetSourcePosition(expr->position());
13003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the IC initialization code.
1301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
13023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
1303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                                         in_loop);
1304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Call(ic, mode);
1305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Restore context register.
1306d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1307402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Apply(context_, rax);
1308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1311d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) {
1312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the call stub.
1313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
1315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
1316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
1317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
1319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
1320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE);
1321d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ CallStub(&stub);
13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore context register.
13233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
13243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Discard the function left on TOS.
1325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  DropAndApply(1, context_, rax);
1326d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1329d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) {
1330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Call");
1331d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* fun = expr->expression();
1332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Variable* var = fun->AsVariableProxy()->AsVariable();
1333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (var != NULL && var->is_possibly_eval()) {
1335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to the identifier 'eval'.
1336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    UNREACHABLE();
1337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (var != NULL && !var->is_this() && var->is_global()) {
1338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to a global variable.
1339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Push global object as receiver for the call IC lookup.
1340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(CodeGenerator::GlobalObject());
1341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
1342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (var != NULL && var->slot() != NULL &&
1343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block             var->slot()->type() == Slot::LOOKUP) {
1344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to a lookup slot.
1345d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    UNREACHABLE();
1346d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (fun->AsProperty() != NULL) {
1347d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to an object property.
1348d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Property* prop = fun->AsProperty();
1349d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = prop->key()->AsLiteral();
1350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (key != NULL && key->handle()->IsSymbol()) {
1351d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Call to a named property, use call IC.
1352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->obj(), kStack);
1353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
1355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Call to a keyed property, use keyed load IC followed by function
1356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // call.
1357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->obj(), kStack);
1358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->key(), kStack);
1359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Record source code position for IC call.
1360d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      SetSourcePosition(prop->position());
1361d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1362d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ call(ic, RelocInfo::CODE_TARGET);
1363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // By emitting a nop we make sure that we do not have a "test rax,..."
1364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // instruction after the call it is treated specially by the LoadIC code.
1365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ nop();
1366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Drop key left on the stack by IC.
1367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Drop(1);
1368d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Pop receiver.
1369d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ pop(rbx);
1370d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Push result (function).
1371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ push(rax);
1372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Push receiver object on stack.
1373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (prop->is_synthetic()) {
1374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ movq(rcx, CodeGenerator::GlobalObject());
1375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
1376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
1377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(rbx);
1378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      EmitCallWithStub(expr);
1380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
13813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
1382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to some other expression.  If the expression is an anonymous
1383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // function literal not called in a loop, mark it as one that should
1384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // also use the fast code generator.
1385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    FunctionLiteral* lit = fun->AsFunctionLiteral();
1386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (lit != NULL &&
1387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        lit->name()->Equals(Heap::empty_string()) &&
1388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        loop_depth() == 0) {
1389d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      lit->set_try_full_codegen(true);
1390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(fun, kStack);
1392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load global receiver object.
1393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ movq(rbx, CodeGenerator::GlobalObject());
1394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
1395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit function call.
1396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    EmitCallWithStub(expr);
1397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1398d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1399d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1401d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
1402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
1403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
1404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
1405d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
1406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push function on the stack.
1407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  VisitForValue(expr->expression(), kStack);
1408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push global object (receiver).
1410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ push(CodeGenerator::GlobalObject());
1411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1412d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
1413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1414d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
1415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
1416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
14173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
1420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
1421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
1422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Load function, arg_count into rdi and rax.
1424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Set(rax, arg_count);
1425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Function is in rsp[arg_count + 1].
1426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize));
1427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
1429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
1430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Replace function on TOS with result in rax, or pop it.
1432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  DropAndApply(1, context_, rax);
14333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
14343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1436d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
14373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ CallRuntime");
14383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* args = expr->arguments();
14393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
1441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Prepare for calling JS runtime function.
1442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ movq(rax, CodeGenerator::GlobalObject());
1443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
1444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
14453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Push the arguments ("left-to-right").
14473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
14483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
1449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(args->at(i), kStack);
1450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
1453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Call the JS runtime function using a call IC.
1454402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ Move(rcx, expr->name());
1455402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
1457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ call(ic, RelocInfo::CODE_TARGET);
1458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Restore context register.
1459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(expr->function(), arg_count);
1462d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1463402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Apply(context_, rax);
1464d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1467d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
1469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
1470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
1471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
1472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (context_) {
1473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kUninitialized:
1474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
1475d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1476d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kEffect:
1477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kValue:
1479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          switch (location_) {
1480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kAccumulator:
1481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex);
1482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
1483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kStack:
1484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ PushRoot(Heap::kUndefinedValueRootIndex);
1485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
1486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
1487d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1488d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kTestValue:
1489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Value is false so it's needed.
1490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          switch (location_) {
1491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kAccumulator:
1492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex);
1493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
1494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case kStack:
1495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              __ PushRoot(Heap::kUndefinedValueRootIndex);
1496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke              break;
1497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
1498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Fall through.
1499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case Expression::kTest:
1500d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kValueTest:
1501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ jmp(false_label_);
1502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
1508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
1509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Label materialize_true, materialize_false, done;
1510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Initially assume a pure test context.  Notice that the labels are
1511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // swapped.
1512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Label* if_true = false_label_;
1513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Label* if_false = true_label_;
1514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      switch (context_) {
1515d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kUninitialized:
1516d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
1517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kEffect:
1519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_true = &done;
1520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_false = &done;
1521e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          break;
1522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        case Expression::kValue:
1523e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_true = &materialize_false;
1524e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_false = &materialize_true;
1525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kTest:
1527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kValueTest:
1529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_false = &materialize_true;
1530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Expression::kTestValue:
1532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          if_true = &materialize_false;
1533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForControl(expr->expression(), if_true, if_false);
1536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Apply(context_, if_false, if_true);  // Labels swapped.
1537d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1538d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1540d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
1541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
1542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      VariableProxy* proxy = expr->expression()->AsVariableProxy();
1543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (proxy != NULL &&
1544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          !proxy->var()->is_this() &&
1545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          proxy->var()->is_global()) {
1546d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        Comment cmnt(masm_, "Global variable");
1547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(CodeGenerator::GlobalObject());
1548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Move(rcx, proxy->name());
1549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Use a regular load, not a contextual load, to avoid a reference
1551d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // error.
1552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Call(ic, RelocInfo::CODE_TARGET);
1553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ movq(Operand(rsp, 0), rax);
1554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else if (proxy != NULL &&
1555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                 proxy->var()->slot() != NULL &&
1556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                 proxy->var()->slot()->type() == Slot::LOOKUP) {
1557d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(rsi);
1558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Push(proxy->name());
1559d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
1560d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(rax);
1561d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
1562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // This expression cannot throw a reference error at the top level.
1563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        VisitForValue(expr->expression(), kStack);
1564d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1565d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1566d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallRuntime(Runtime::kTypeof, 1);
1567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Apply(context_, rax);
1568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1571d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Token::ADD: {
1572d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Comment cmt(masm_, "[ UnaryOperation (ADD)");
1573d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      VisitForValue(expr->expression(), kAccumulator);
1574d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Label no_conversion;
15754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Condition is_smi = masm_->CheckSmi(result_register());
1576d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ j(is_smi, &no_conversion);
1577d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ push(result_register());
1578d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
1579d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ bind(&no_conversion);
1580d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Apply(context_, result_register());
1581d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      break;
1582d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
1583d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
15844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::SUB: {
15854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (SUB)");
15864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      bool overwrite =
15874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          (expr->expression()->AsBinaryOperation() != NULL &&
15884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
15894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      GenericUnaryOpStub stub(Token::SUB, overwrite);
15904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // GenericUnaryOpStub expects the argument to be in the
15914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // accumulator register rax.
15924515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      VisitForValue(expr->expression(), kAccumulator);
15934515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
15944515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Apply(context_, rax);
15954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
15964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
15974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
15984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::BIT_NOT: {
15994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
16004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      bool overwrite =
16014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          (expr->expression()->AsBinaryOperation() != NULL &&
16024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
16034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
16044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // GenericUnaryOpStub expects the argument to be in the
16054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // accumulator register rax.
16064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      VisitForValue(expr->expression(), kAccumulator);
16074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Avoid calling the stub for Smis.
16084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Label smi, done;
16094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Condition is_smi = masm_->CheckSmi(result_register());
16104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ j(is_smi, &smi);
16114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Non-smi: call stub leaving result in accumulator register.
16124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
16134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ jmp(&done);
16144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // Perform operation directly on Smis.
16154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ bind(&smi);
16164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ SmiNot(result_register(), result_register());
16174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ bind(&done);
16184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Apply(context_, result_register());
16194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
16204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
16214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
1622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
1623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
16243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
16253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
1629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Comment cmnt(masm_, "[ CountOperation");
1630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Expression can only be a property, a global or a (parameter or local)
1632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LhsKind assign_type = VARIABLE;
1635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
1636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In case of a property we use the uninitialized expression context
1637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // of the key to detect a named property.
1638e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (prop != NULL) {
1639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    assign_type =
1640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
1641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
1644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
1645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
1646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Location saved_location = location_;
1647d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    location_ = kAccumulator;
1648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
1649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     Expression::kValue);
1650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    location_ = saved_location;
1651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else  {
1652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
1653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (expr->is_postfix() && context_ != Expression::kEffect) {
1654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Push(Smi::FromInt(0));
1655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
1656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    VisitForValue(prop->obj(), kStack);
1657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (assign_type == NAMED_PROPERTY) {
1658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitNamedPropertyLoad(prop);
1659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
1660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(prop->key(), kStack);
1661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitKeyedPropertyLoad(prop);
1662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
1663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1665d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Call ToNumber only if operand is not a smi.
1666d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label no_conversion;
1667d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Condition is_smi;
1668d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  is_smi = masm_->CheckSmi(rax);
1669d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ j(is_smi, &no_conversion);
1670d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ push(rax);
1671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
1672d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&no_conversion);
1673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
1675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
1676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    switch (context_) {
1677e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kUninitialized:
1678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        UNREACHABLE();
1679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kEffect:
1680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Do not save result.
1681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        break;
1682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kValue:
1683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kTest:
1684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kValueTest:
1685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Expression::kTestValue:
1686e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Save the result on the stack. If we have a named or keyed property
1687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // we store the result under the receiver that is currently on top
1688e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // of the stack.
1689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        switch (assign_type) {
1690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          case VARIABLE:
1691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            __ push(rax);
1692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            break;
1693e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          case NAMED_PROPERTY:
1694e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            __ movq(Operand(rsp, kPointerSize), rax);
1695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            break;
1696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          case KEYED_PROPERTY:
1697e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            __ movq(Operand(rsp, 2 * kPointerSize), rax);
1698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            break;
1699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
1700e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        break;
1701e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
1702e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1704d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Inline smi case if we are in a loop.
1705d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label stub_call, done;
1706d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (loop_depth() > 0) {
1707d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
1708d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiAddConstant(rax, rax, Smi::FromInt(1));
1709d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
1710d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiSubConstant(rax, rax, Smi::FromInt(1));
1711d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
1712d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ j(overflow, &stub_call);
1713d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // We could eliminate this smi check if we split the code at
1714d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // the first smi check before calling ToNumber.
1715d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    is_smi = masm_->CheckSmi(rax);
1716d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ j(is_smi, &done);
1717d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ bind(&stub_call);
1718d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Call stub. Undo operation first.
1719d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
1720d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiSubConstant(rax, rax, Smi::FromInt(1));
1721d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
1722d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiAddConstant(rax, rax, Smi::FromInt(1));
1723d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
1724d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call stub for +1/-1.
1726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  GenericBinaryOpStub stub(expr->binary_op(),
1727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_OVERWRITE,
1728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_GENERIC_BINARY_FLAGS);
17294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  stub.GenerateCall(masm_, rax, Smi::FromInt(1));
1730d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
1731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in rax.
1733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
1734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case VARIABLE:
1735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
1736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1737e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               Expression::kEffect);
1738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // For all contexts except kEffect: We have the result on
1739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
1740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (context_ != Expression::kEffect) {
1741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          ApplyTOS(context_);
1742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
1743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
1744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               context_);
1746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
1747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
1748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
1749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Move(rcx, prop->key()->AsLiteral()->handle());
17504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ pop(rdx);
1751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1752e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ call(ic, RelocInfo::CODE_TARGET);
1753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // This nop signals to the IC that there is no inlined code at the call
1754e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // site for it to patch.
1755e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ nop();
1756e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
1757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (context_ != Expression::kEffect) {
1758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          ApplyTOS(context_);
1759e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
1760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
17614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        Apply(context_, rax);
1762e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
1763e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
1764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
1765e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
1766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1767e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ call(ic, RelocInfo::CODE_TARGET);
1768e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // This nop signals to the IC that there is no inlined code at the call
1769e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // site for it to patch.
1770e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ nop();
1771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
1772e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ Drop(2);  // Result is on the stack under the key and the receiver.
1773e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (context_ != Expression::kEffect) {
1774e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          ApplyTOS(context_);
1775e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
1776e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
1777e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        DropAndApply(2, context_, rax);
1778e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
1779e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
1780e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
1781e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1782e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1783e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1784d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
1785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ BinaryOperation");
1786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
1787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::COMMA:
1788e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->left());
1789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Visit(expr->right());
1790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::OR:
1793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::AND:
1794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      EmitLogicalOperation(expr);
1795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::ADD:
1798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::SUB:
1799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::DIV:
1800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::MOD:
1801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::MUL:
1802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::BIT_OR:
1803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::BIT_AND:
1804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::BIT_XOR:
1805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::SHL:
1806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::SHR:
1807e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::SAR:
1808e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->left(), kStack);
1809e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kAccumulator);
1810e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitBinaryOp(expr->op(), context_);
1811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
1814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
18153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
18173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1819d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
1820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
1821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
1823e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
1824e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label materialize_true, materialize_false, done;
1825e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Initially assume we are in a test context.
1826e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label* if_true = true_label_;
1827e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Label* if_false = false_label_;
1828e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (context_) {
1829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kUninitialized:
1830d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
1831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kEffect:
1833e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if_true = &done;
1834e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if_false = &done;
1835e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
1836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Expression::kValue:
1837e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if_true = &materialize_true;
1838e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if_false = &materialize_false;
1839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTest:
1841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kValueTest:
1843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if_true = &materialize_true;
1844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Expression::kTestValue:
1846e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if_false = &materialize_false;
1847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
18483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  VisitForValue(expr->left(), kStack);
1851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
1852e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
1853e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kStack);
1854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
1855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CompareRoot(rax, Heap::kTrueValueRootIndex);
1856e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(equal, if_true);
1857e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
1858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
18593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
1861e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kStack);
1862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      InstanceofStub stub;
1863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
1864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ testq(rax, rax);
1865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(zero, if_true);  // The stub returns 0 for true.
1866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
1867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
1871e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForValue(expr->right(), kAccumulator);
1872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Condition cc = no_condition;
1873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      bool strict = false;
1874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (expr->op()) {
1875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::EQ_STRICT:
1876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          strict = true;
1877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Fall through.
1878d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::EQ:
1879d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = equal;
1880d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rdx);
1881d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LT:
1883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
1884d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rdx);
1885d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1886d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GT:
1887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Reverse left and right sizes to obtain ECMA-262 conversion order.
1888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
1889e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(rdx, result_register());
1890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rax);
1891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block         break;
1892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LTE:
1893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Reverse left and right sizes to obtain ECMA-262 conversion order.
1894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
1895e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(rdx, result_register());
1896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rax);
1897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GTE:
1899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
1900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rdx);
1901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::IN:
1903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::INSTANCEOF:
1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default:
1905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
1906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // The comparison stub expects the smi vs. smi case to be handled
1909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // before it is called.
1910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Label slow_case;
1911d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ JumpIfNotBothSmi(rax, rdx, &slow_case);
1912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ SmiCompare(rdx, rax);
1913e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(cc, if_true);
1914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
1915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ bind(&slow_case);
1917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      CompareStub stub(cc, strict);
1918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
1919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ testq(rax, rax);
1920e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ j(cc, if_true);
1921e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ jmp(if_false);
1922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
19233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
19243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
1926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
1927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, if_true, if_false);
1928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1931d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
1932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1933e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Apply(context_, rax);
1934e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1937d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::result_register() { return rax; }
1938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1940d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::context_register() { return rsi; }
1941e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1943d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
1944e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(IsAligned(frame_offset, kPointerSize));
1945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(Operand(rbp, frame_offset), value);
19463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
19473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1949d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
1950e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(dst, CodeGenerator::ContextOperand(rsi, context_index));
1951e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1953e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1954e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ----------------------------------------------------------------------------
1955e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support.
1956e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1958d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() {
1959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rdx));
1960e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rcx));
1961e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Cook return address on top of stack (smi encoded Code* delta)
1962e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(rdx, Operand(rsp, 0));
1963e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, masm_->CodeObject());
1964e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ subq(rdx, rcx);
1965e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Integer32ToSmi(rdx, rdx);
1966e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(Operand(rsp, 0), rdx);
1967e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store result register while executing finally block.
1968e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
1969e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1970e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1971e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1972d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() {
1973e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rdx));
1974e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rcx));
1975e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Restore result register from stack.
1976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(result_register());
1977e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Uncook return address.
1978e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(rdx, Operand(rsp, 0));
1979e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ SmiToInteger32(rdx, rdx);
1980e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, masm_->CodeObject());
1981e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ addq(rdx, rcx);
1982e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(Operand(rsp, 0), rdx);
1983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // And return.
1984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ret(0);
1985d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1986d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1987d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1988d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef __
1989d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1990d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
19913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} }  // namespace v8::internal
1992