full-codegen-x64.cc revision f87a203d89e1bbb6708282e0b64dbd13d59b723d
14515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke// Copyright 2010 the V8 project authors. All rights reserved.
23ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Redistribution and use in source and binary forms, with or without
33ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// modification, are permitted provided that the following conditions are
43ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// met:
53ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
63ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//     * Redistributions of source code must retain the above copyright
73ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       notice, this list of conditions and the following disclaimer.
83ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//     * Redistributions in binary form must reproduce the above
93ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       copyright notice, this list of conditions and the following
103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       disclaimer in the documentation and/or other materials provided
113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       with the distribution.
123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//     * Neither the name of Google Inc. nor the names of its
133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       contributors may be used to endorse or promote products derived
143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       from this software without specific prior written permission.
153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "v8.h"
293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_X64)
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "code-stubs.h"
333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "codegen-inl.h"
34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h"
353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "debug.h"
36d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "full-codegen.h"
373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "parser.h"
386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "scopes.h"
393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 {
413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal {
423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_)
443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function.  On entry to the function the receiver
463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, with the
473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them.  The actual argument count matches the
483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function.
493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are:
513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rdi: the JS function object being called (ie, ourselves)
523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rsi: our context
533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rbp: our caller's frame pointer
543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rsp: stack pointer (pointing to return address)
553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame.  Please see JavaScriptFrameConstants in
573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-x64.h for its layout.
58756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::Generate(CompilationInfo* info) {
593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ASSERT(info_ == NULL);
603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  info_ = info;
613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  SetFunctionPosition(function());
626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comment cmnt(masm_, "[ function compiled by full code generator");
633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
64f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG
65f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (strlen(FLAG_stop_at) > 0 &&
66f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
67f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ int3();
68f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
69f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif
70756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(rbp);  // Caller's frame pointer.
71756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ movq(rbp, rsp);
72756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(rsi);  // Callee's context.
73756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(rdi);  // Callee's JS Function.
74756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
75756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  { Comment cmnt(masm_, "[ Allocate locals");
76756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    int locals_count = scope()->num_stack_slots();
77756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (locals_count == 1) {
78756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ PushRoot(Heap::kUndefinedValueRootIndex);
79756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else if (locals_count > 1) {
80756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
81756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      for (int i = 0; i < locals_count; i++) {
82756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ push(rdx);
83d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
84d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
85756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
86d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
87756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  bool function_in_register = true;
884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
89756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate a local context.
90756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
91756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (heap_slots > 0) {
92756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate local context");
93756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Argument to NewContext is the function, which is still in rdi.
94756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ push(rdi);
95756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
96756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      FastNewContextStub stub(heap_slots);
97756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ CallStub(&stub);
98756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
99756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ CallRuntime(Runtime::kNewContext, 1);
100756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
101756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    function_in_register = false;
102756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Context is returned in both rax and rsi.  It replaces the context
103756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // passed to us.  It's saved in the stack and kept live in rsi.
104756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
105756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
106756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Copy any necessary parameters into the context.
107756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    int num_parameters = scope()->num_parameters();
108756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (int i = 0; i < num_parameters; i++) {
1090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      Slot* slot = scope()->parameter(i)->AsSlot();
110756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      if (slot != NULL && slot->type() == Slot::CONTEXT) {
111756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
112756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick            (num_parameters - 1 - i) * kPointerSize;
113756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Load parameter from stack.
114756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ movq(rax, Operand(rbp, parameter_offset));
115756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Store it in the context.
116756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        int context_offset = Context::SlotOffset(slot->index());
117756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ movq(Operand(rsi, context_offset), rax);
118756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Update the write barrier. This clobbers all involved
119756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // registers, so we have use a third register to avoid
120756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // clobbering rsi.
121756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ movq(rcx, rsi);
122756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ RecordWrite(rcx, context_offset, rax, rbx);
123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
125756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
1263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
127756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate an arguments object.
1280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Variable* arguments = scope()->arguments();
129756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (arguments != NULL) {
130756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Arguments object must be allocated after the context object, in
131756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // case the "arguments" or ".arguments" variables are in the context.
132756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate arguments object");
133756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (function_in_register) {
134756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ push(rdi);
135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
136756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
138756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The receiver is just before the parameters on the caller's stack.
139756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    int offset = scope()->num_parameters() * kPointerSize;
140756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ lea(rdx,
141756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
142756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ push(rdx);
143756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ Push(Smi::FromInt(scope()->num_parameters()));
144756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Arguments to ArgumentsAccessStub:
145756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    //   function, receiver address, parameter count.
146756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The stub will rewrite receiver and parameter count if the previous
147756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // stack frame was an arguments adapter frame.
148756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
149756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
150756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Store new arguments object in both "arguments" and ".arguments" slots.
151756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ movq(rcx, rax);
1520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Move(arguments->AsSlot(), rax, rbx, rdx);
1530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot();
154756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Move(dot_arguments_slot, rcx, rbx, rdx);
155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
157e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  { Comment cmnt(masm_, "[ Declarations");
158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // For named function expressions, declare the function name as a
159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // constant.
160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (scope()->is_function_scope() && scope()->function() != NULL) {
161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      EmitDeclaration(scope()->function(), Variable::CONST, NULL);
162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Visit all the explicit declarations unless there is an illegal
164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // redeclaration.
165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (scope()->HasIllegalRedeclaration()) {
166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      scope()->VisitIllegalRedeclaration(this);
167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      VisitDeclarations(scope()->declarations());
169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
170e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ Stack check");
1730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    NearLabel ok;
1743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
1753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(above_equal, &ok);
1763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    StackCheckStub stub;
1773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CallStub(&stub);
1783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&ok);
1793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (FLAG_trace) {
1823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ CallRuntime(Runtime::kTraceEnter, 0);
1833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ Body");
186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    VisitStatements(function()->body());
188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(loop_depth() == 0);
1893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit a 'return undefined' in case control fell off the end of the body.
1933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    EmitReturnSequence();
195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() {
200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ jmp(&return_label_);
203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
2053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
2063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(rax);
2073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ CallRuntime(Runtime::kTraceExit, 1);
2083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG
210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Add a label for checking the size of the code used for returning.
211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Label check_exit_codesize;
212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    masm_->bind(&check_exit_codesize);
213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
214bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
2153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ RecordJSReturn();
2163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Do not use the leave instruction here because it is too short to
2173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // patch with the code required by the debugger.
2183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(rsp, rbp);
2193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ pop(rbp);
2203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    __ ret((scope()->num_parameters() + 1) * kPointerSize);
2213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT
2223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Add padding that will be overwritten by a debugger breakpoint.  We
2233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7
2243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // (3 + 1 + 3).
225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    const int kPadding = Assembler::kJSReturnSequenceLength - 7;
2263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    for (int i = 0; i < kPadding; ++i) {
2273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      masm_->int3();
2283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Check that the size of the code used for returning matches what is
230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // expected by the debugger.
231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_EQ(Assembler::kJSReturnSequenceLength,
232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
2333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#endif
2343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
2363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
23880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenFullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand(
23980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Token::Value op, Expression* left, Expression* right) {
24080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(ShouldInlineSmiCase(op));
24180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return kNoConstants;
24280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
24380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
24480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2450d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
2460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2490d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const {
2500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
2510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ movq(result_register(), slot_operand);
2520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
253e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2550d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
2560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
2570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(slot_operand);
258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2610d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Slot* slot) const {
2620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->Move(result_register(), slot);
2630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->DoTest(true_label_, false_label_, fall_through_);
2640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2670d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2710d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
2720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
2730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), index);
2740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2770d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
2780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
2790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ PushRoot(index);
2800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
2810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2830d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
2840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (index == Heap::kUndefinedValueRootIndex ||
2850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kNullValueRootIndex ||
2860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kFalseValueRootIndex) {
2870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ jmp(false_label_);
2880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (index == Heap::kTrueValueRootIndex) {
2890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ jmp(true_label_);
2900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
2910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ LoadRoot(result_register(), index);
2920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    codegen()->DoTest(true_label_, false_label_, fall_through_);
293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2970d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
2980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3010d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
3020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Handle<Object> lit) const {
3030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), lit);
3040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3070d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
3080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Push(lit);
3090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
3100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3120d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
3130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!lit->IsUndetectableObject());  // There are no undetectable literals.
3140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
3150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ jmp(false_label_);
3160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsTrue() || lit->IsJSObject()) {
3170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ jmp(true_label_);
3180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsString()) {
3190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (String::cast(*lit)->length() == 0) {
3200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ jmp(false_label_);
3210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
3220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ jmp(true_label_);
3230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
3240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsSmi()) {
3250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (Smi::cast(*lit)->value() == 0) {
3260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ jmp(false_label_);
3270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
3280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ jmp(true_label_);
3290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
3300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
3310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // For simplicity we always test the accumulator register.
3320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ Move(result_register(), lit);
3330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    codegen()->DoTest(true_label_, false_label_, fall_through_);
334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3380d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count,
3390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                   Register reg) const {
340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(count > 0);
3410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
3420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3450d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
3460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    int count,
3470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Register reg) const {
3480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
3490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
3500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
3510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3540d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count,
3550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                       Register reg) const {
3560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
3570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (count > 1) __ Drop(count - 1);
3580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ movq(Operand(rsp, 0), reg);
359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3620d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count,
3630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                 Register reg) const {
3640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
3650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
3660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
3670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
3680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->DoTest(true_label_, false_label_, fall_through_);
3690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3720d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
3730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            Label* materialize_false) const {
3740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT_EQ(materialize_true, materialize_false);
3750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
3760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3790d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
3800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
3810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
3820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel done;
3830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
3840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), Factory::true_value());
3850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ jmp(&done);
3860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
3870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), Factory::false_value());
3880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3920d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
3930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
3940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
3950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel done;
3960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
3970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Push(Factory::true_value());
3980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ jmp(&done);
3990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
4000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Push(Factory::false_value());
4010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
4020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4050d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true,
4060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                          Label* materialize_false) const {
4070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(materialize_false == false_label_);
4080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(materialize_true == true_label_);
4090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4120d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const {
4130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4160d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
4170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
4180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
4190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), value_root_index);
4200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4230d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const {
4240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
4250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
4260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ PushRoot(value_root_index);
4270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4300d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const {
4310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (flag) {
4320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (true_label_ != fall_through_) __ jmp(true_label_);
4330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
4340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (false_label_ != fall_through_) __ jmp(false_label_);
435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
43980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::DoTest(Label* if_true,
44080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* if_false,
44180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* fall_through) {
442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the inlined tests assumed by the stub.
443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex);
444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
445e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
446e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_true);
447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CompareRoot(result_register(), Heap::kFalseValueRootIndex);
448e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, kSmiTag);
450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ SmiCompare(result_register(), Smi::FromInt(0));
451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Condition is_smi = masm_->CheckSmi(result_register());
453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(is_smi, if_true);
454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call the ToBoolean stub for all other cases.
456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ToBooleanStub stub;
457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ testq(rax, rax);
460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
46180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The stub returns nonzero for true.
46280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(not_zero, if_true, if_false, fall_through);
46380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
46680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::Split(Condition cc,
46780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_true,
46880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_false,
46980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* fall_through) {
47080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (if_false == fall_through) {
47180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(cc, if_true);
47280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (if_true == fall_through) {
47380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(NegateCondition(cc), if_false);
47480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
47580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(cc, if_true);
47680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ jmp(if_false);
477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
481d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (slot->type()) {
483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::PARAMETER:
484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOCAL:
485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return Operand(rbp, SlotOffset(slot));
486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::CONTEXT: {
487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      int context_chain_length =
4883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          scope()->ContextChainLength(slot->var()->scope());
489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ LoadContext(scratch, context_chain_length);
49059151504615d929945dc59db37bf1166937748c6Steve Block      return ContextOperand(scratch, slot->index());
491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOOKUP:
493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
494d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  UNREACHABLE();
496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return Operand(rax, 0);
497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
500d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) {
501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(source, destination);
502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(destination, location);
503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
506d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst,
507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register src,
508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch1,
509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch2) {
510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(dst->type() != Slot::LOOKUP);  // Not yet implemented.
511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!scratch1.is(src) && !scratch2.is(src));
512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(dst, scratch1);
513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(location, src);
514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (dst->type() == Slot::CONTEXT) {
516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ RecordWrite(scratch1, offset, src, scratch2);
518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
520d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitDeclaration(Variable* variable,
523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Variable::Mode mode,
524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        FunctionLiteral* function) {
525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Declaration");
526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(variable != NULL);  // Must have been resolved.
5270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Slot* slot = variable->AsSlot();
528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = variable->AsProperty();
529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (slot != NULL) {
531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOCAL:
534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister);
537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
5380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForAccumulatorValue(function);
539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(Operand(rbp, SlotOffset(slot)), result_register());
540d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT:
544e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // We bypass the general EmitSlotSearch because we know more about
545e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // this specific context.
546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // The variable in the decl always resides in the current context.
548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (FLAG_debug_code) {
550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Check if we have the correct context pointer.
55159151504615d929945dc59db37bf1166937748c6Steve Block          __ movq(rbx, ContextOperand(rsi, Context::FCONTEXT_INDEX));
552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ cmpq(rbx, rsi);
553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Check(equal, "Unexpected declaration in current context.");
554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
55759151504615d929945dc59db37bf1166937748c6Steve Block          __ movq(ContextOperand(rsi, slot->index()), kScratchRegister);
558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // No write barrier since the hole value is in old space.
559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
5600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForAccumulatorValue(function);
56159151504615d929945dc59db37bf1166937748c6Steve Block          __ movq(ContextOperand(rsi, slot->index()), result_register());
562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          int offset = Context::SlotOffset(slot->index());
5634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(rbx, rsi);
5644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ RecordWrite(rbx, offset, result_register(), rcx);
565d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
566d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP: {
569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(rsi);
570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ Push(variable->name());
571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Declaration nodes are always introduced in one of two modes.
572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ASSERT(mode == Variable::VAR || mode == Variable::CONST);
573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY;
574d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Push(Smi::FromInt(attr));
575d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Push initial value, if any.
576d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Note: For variables we must not push an initial value (such as
577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // 'undefined') because we may have a (legal) redeclaration and we
578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // must not destroy the current value.
579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
580d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ PushRoot(Heap::kTheHoleValueRootIndex);
581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
5820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForStackValue(function);
583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else {
584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Push(Smi::FromInt(0));  // no initial value!
585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDeclareContextSlot, 4);
587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
591d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (prop != NULL) {
592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (function != NULL || mode == Variable::CONST) {
593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // We are declaring a function or constant that rewrites to a
594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // property.  Use (keyed) IC to set the initial value.
5950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(prop->obj());
596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (function != NULL) {
5970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(prop->key());
5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(function);
599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ pop(rcx);
600d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
6010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(prop->key());
602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ movq(rcx, result_register());
603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex);
604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(rdx);
606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
6080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) {
615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
619d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
6203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
6213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(rsi);  // The context is the first argument.
6223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(pairs);
6233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  __ Push(Smi::FromInt(is_eval() ? 1 : 0));
6243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kDeclareGlobals, 3);
6253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
6263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
6273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ SwitchStatement");
631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Breakable nested_statement(this, stmt);
632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Keep the switch value on the stack until a case matches.
6340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(stmt->tag());
635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<CaseClause*>* clauses = stmt->cases();
637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label next_test;  // Recycled for each test.
640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the tests with branches to their bodies.
641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The default is not a test, but remember it as final fall through.
644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (clause->is_default()) {
645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      default_clause = clause;
646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      continue;
647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case comparison");
650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&next_test);
651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    next_test.Unuse();
652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Compile the label expression.
6540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(clause->label());
655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
65680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Perform the comparison as if via '==='.
6570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ movq(rdx, Operand(rsp, 0));  // Switch value.
6580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
6590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (inline_smi_code) {
66080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label slow_case;
66180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ JumpIfNotBothSmi(rdx, rax, &slow_case);
66280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiCompare(rdx, rax);
66380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(not_equal, &next_test);
66480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ Drop(1);  // Switch value is no longer needed.
66580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ jmp(clause->body_target()->entry_label());
66680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&slow_case);
66780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
6690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    CompareFlags flags = inline_smi_code
6700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        ? NO_SMI_COMPARE_IN_STUB
6710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        : NO_COMPARE_FLAGS;
6720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    CompareStub stub(equal, true, flags);
673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ testq(rax, rax);
675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(not_equal, &next_test);
676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(clause->body_target()->entry_label());
678f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Discard the test value and jump to the default if present, otherwise to
681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the end of the statement.
682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&next_test);
683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(1);  // Switch value is no longer needed.
684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (default_clause == NULL) {
685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(nested_statement.break_target());
686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(default_clause->body_target()->entry_label());
688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the case bodies.
691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case body");
693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(clause->body_target()->entry_label());
695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitStatements(clause->statements());
696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(nested_statement.break_target());
699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ ForInStatement");
704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label loop, exit;
707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ForIn loop_statement(this, stmt);
708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  increment_loop_depth();
709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the object to enumerate over. Both SpiderMonkey and JSC
711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ignore null and undefined in contrast to the specification; see
712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ECMA-262 section 12.6.4.
7130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(stmt->enumerable());
714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareRoot(rax, Heap::kNullValueRootIndex);
717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the object to a JS object.
720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label convert, done_convert;
721f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, &convert);
722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx);
723f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(above_equal, &done_convert);
724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&convert);
725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);
726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done_convert);
728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);
729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
73059151504615d929945dc59db37bf1166937748c6Steve Block  // BUG(867): Check cache validity in generated code. This is a fast
73159151504615d929945dc59db37bf1166937748c6Steve Block  // case for the JSObject::IsSimpleEnum cache validity checks. If we
73259151504615d929945dc59db37bf1166937748c6Steve Block  // cannot guarantee cache validity, call the runtime system to check
73359151504615d929945dc59db37bf1166937748c6Steve Block  // cache validity or get the property names in a fixed array.
734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the set of properties to enumerate.
736f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);  // Duplicate the enumerable object on the stack.
737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If we got a map from the runtime call, we can do a fast
740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // modification check. Otherwise, we got a fixed array, and we have
741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // to do a slow check.
7420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel fixed_array;
743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 Heap::kMetaMapRootIndex);
745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &fixed_array);
746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a map in register rax. Get the enumeration cache from it.
748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rcx, FieldOperand(rax, Map::kInstanceDescriptorsOffset));
749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset));
750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
752f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Setup the four remaining stack slots.
753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);  // Map.
754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rdx);  // Enumeration cache.
755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset));
756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);  // Enumeration cache length (as smi).
757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(Smi::FromInt(0));  // Initial index.
758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a fixed array in register rax. Iterate through that.
761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&fixed_array);
762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(Smi::FromInt(0));  // Map (0) - force slow check.
763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);
764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset));
765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);  // Fixed array length (as smi).
766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(Smi::FromInt(0));  // Initial index.
767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for doing the condition check.
769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&loop);
770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, Operand(rsp, 0 * kPointerSize));  // Get the current index.
771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(rax, Operand(rsp, 1 * kPointerSize));  // Compare to the array length.
772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(above_equal, loop_statement.break_target());
773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the current entry of the array into register rbx.
775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, Operand(rsp, 2 * kPointerSize));
776f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2);
777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, FieldOperand(rbx,
778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.reg,
779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.scale,
780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            FixedArray::kHeaderSize));
781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the expected map from the stack or a zero map in the
783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // permanent slow case into register rdx.
784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rdx, Operand(rsp, 3 * kPointerSize));
785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the expected map still matches that of the enumerable.
787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If not, we have to filter the key.
7880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel update_each;
789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rcx, Operand(rsp, 4 * kPointerSize));
790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset));
791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &update_each);
792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the entry to a string or null if it isn't a property
794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // anymore. If the property has been removed while iterating, we
795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // just skip it.
796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rcx);  // Enumerable.
797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rbx);  // Current entry.
798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
799756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ SmiCompare(rax, Smi::FromInt(0));
800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, loop_statement.continue_target());
801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, rax);
802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the 'each' property or variable from the possibly filtered
804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // entry in register rbx.
805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&update_each);
806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(result_register(), rbx);
807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Perform the assignment as if via '='.
808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  EmitAssignment(stmt->each());
809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the body of the loop.
811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label stack_limit_hit, stack_check_done;
812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Visit(stmt->body());
813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ StackLimitCheck(&stack_limit_hit);
815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&stack_check_done);
816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for going to the next element by incrementing the
818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // index (smi) stored on top of the stack.
819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(loop_statement.continue_target());
820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1));
821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Slow case for the stack limit check.
824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StackCheckStub stack_check_stub;
825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&stack_limit_hit);
826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stack_check_stub);
827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&stack_check_done);
828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Remove the pointers stored on the stack.
830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(loop_statement.break_target());
831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ addq(rsp, Immediate(5 * kPointerSize));
832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Exit and decrement the loop depth.
834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  decrement_loop_depth();
836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
8373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Use the fast case closure allocation code that allocates in new
841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // space for nested functions that don't need literals cloning.
842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (scope()->is_function_scope() && info->num_literals() == 0) {
843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    FastNewClosureStub stub;
844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Push(info);
845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(rsi);
848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Push(info);
849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kNewClosure, 2);
850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
8510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
8523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
855d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
8563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ VariableProxy");
8570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitVariableLoad(expr->var());
858e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
859e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
860e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
86159151504615d929945dc59db37bf1166937748c6Steve Blockvoid FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
86259151504615d929945dc59db37bf1166937748c6Steve Block    Slot* slot,
86359151504615d929945dc59db37bf1166937748c6Steve Block    TypeofState typeof_state,
86459151504615d929945dc59db37bf1166937748c6Steve Block    Label* slow) {
86559151504615d929945dc59db37bf1166937748c6Steve Block  Register context = rsi;
86659151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = rdx;
86759151504615d929945dc59db37bf1166937748c6Steve Block
86859151504615d929945dc59db37bf1166937748c6Steve Block  Scope* s = scope();
86959151504615d929945dc59db37bf1166937748c6Steve Block  while (s != NULL) {
87059151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
87159151504615d929945dc59db37bf1166937748c6Steve Block      if (s->calls_eval()) {
87259151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
87359151504615d929945dc59db37bf1166937748c6Steve Block        __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
87459151504615d929945dc59db37bf1166937748c6Steve Block                Immediate(0));
87559151504615d929945dc59db37bf1166937748c6Steve Block        __ j(not_equal, slow);
87659151504615d929945dc59db37bf1166937748c6Steve Block      }
87759151504615d929945dc59db37bf1166937748c6Steve Block      // Load next context in chain.
87859151504615d929945dc59db37bf1166937748c6Steve Block      __ movq(temp, ContextOperand(context, Context::CLOSURE_INDEX));
87959151504615d929945dc59db37bf1166937748c6Steve Block      __ movq(temp, FieldOperand(temp, JSFunction::kContextOffset));
88059151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering rsi.
88159151504615d929945dc59db37bf1166937748c6Steve Block      context = temp;
88259151504615d929945dc59db37bf1166937748c6Steve Block    }
88359151504615d929945dc59db37bf1166937748c6Steve Block    // If no outer scope calls eval, we do not need to check more
88459151504615d929945dc59db37bf1166937748c6Steve Block    // context extensions.  If we have reached an eval scope, we check
88559151504615d929945dc59db37bf1166937748c6Steve Block    // all extensions from this point.
88659151504615d929945dc59db37bf1166937748c6Steve Block    if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break;
88759151504615d929945dc59db37bf1166937748c6Steve Block    s = s->outer_scope();
88859151504615d929945dc59db37bf1166937748c6Steve Block  }
88959151504615d929945dc59db37bf1166937748c6Steve Block
89059151504615d929945dc59db37bf1166937748c6Steve Block  if (s != NULL && s->is_eval_scope()) {
89159151504615d929945dc59db37bf1166937748c6Steve Block    // Loop up the context chain.  There is no frame effect so it is
89259151504615d929945dc59db37bf1166937748c6Steve Block    // safe to use raw labels here.
8930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    NearLabel next, fast;
89459151504615d929945dc59db37bf1166937748c6Steve Block    if (!context.is(temp)) {
89559151504615d929945dc59db37bf1166937748c6Steve Block      __ movq(temp, context);
89659151504615d929945dc59db37bf1166937748c6Steve Block    }
89759151504615d929945dc59db37bf1166937748c6Steve Block    // Load map for comparison into register, outside loop.
89859151504615d929945dc59db37bf1166937748c6Steve Block    __ LoadRoot(kScratchRegister, Heap::kGlobalContextMapRootIndex);
89959151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&next);
90059151504615d929945dc59db37bf1166937748c6Steve Block    // Terminate at global context.
90159151504615d929945dc59db37bf1166937748c6Steve Block    __ cmpq(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset));
90259151504615d929945dc59db37bf1166937748c6Steve Block    __ j(equal, &fast);
90359151504615d929945dc59db37bf1166937748c6Steve Block    // Check that extension is NULL.
90459151504615d929945dc59db37bf1166937748c6Steve Block    __ cmpq(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
90559151504615d929945dc59db37bf1166937748c6Steve Block    __ j(not_equal, slow);
90659151504615d929945dc59db37bf1166937748c6Steve Block    // Load next context in chain.
90759151504615d929945dc59db37bf1166937748c6Steve Block    __ movq(temp, ContextOperand(temp, Context::CLOSURE_INDEX));
90859151504615d929945dc59db37bf1166937748c6Steve Block    __ movq(temp, FieldOperand(temp, JSFunction::kContextOffset));
90959151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(&next);
91059151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&fast);
91159151504615d929945dc59db37bf1166937748c6Steve Block  }
91259151504615d929945dc59db37bf1166937748c6Steve Block
91359151504615d929945dc59db37bf1166937748c6Steve Block  // All extension objects were empty and it is safe to use a global
91459151504615d929945dc59db37bf1166937748c6Steve Block  // load IC call.
91559151504615d929945dc59db37bf1166937748c6Steve Block  __ movq(rax, CodeGenerator::GlobalObject());
91659151504615d929945dc59db37bf1166937748c6Steve Block  __ Move(rcx, slot->var()->name());
91759151504615d929945dc59db37bf1166937748c6Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
91859151504615d929945dc59db37bf1166937748c6Steve Block  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
91959151504615d929945dc59db37bf1166937748c6Steve Block      ? RelocInfo::CODE_TARGET
92059151504615d929945dc59db37bf1166937748c6Steve Block      : RelocInfo::CODE_TARGET_CONTEXT;
9210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, mode);
92259151504615d929945dc59db37bf1166937748c6Steve Block}
92359151504615d929945dc59db37bf1166937748c6Steve Block
92459151504615d929945dc59db37bf1166937748c6Steve Block
92559151504615d929945dc59db37bf1166937748c6Steve BlockMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
92659151504615d929945dc59db37bf1166937748c6Steve Block    Slot* slot,
92759151504615d929945dc59db37bf1166937748c6Steve Block    Label* slow) {
92859151504615d929945dc59db37bf1166937748c6Steve Block  ASSERT(slot->type() == Slot::CONTEXT);
92959151504615d929945dc59db37bf1166937748c6Steve Block  Register context = rsi;
93059151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = rbx;
93159151504615d929945dc59db37bf1166937748c6Steve Block
93259151504615d929945dc59db37bf1166937748c6Steve Block  for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
93359151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
93459151504615d929945dc59db37bf1166937748c6Steve Block      if (s->calls_eval()) {
93559151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
93659151504615d929945dc59db37bf1166937748c6Steve Block        __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
93759151504615d929945dc59db37bf1166937748c6Steve Block                Immediate(0));
93859151504615d929945dc59db37bf1166937748c6Steve Block        __ j(not_equal, slow);
93959151504615d929945dc59db37bf1166937748c6Steve Block      }
94059151504615d929945dc59db37bf1166937748c6Steve Block      __ movq(temp, ContextOperand(context, Context::CLOSURE_INDEX));
94159151504615d929945dc59db37bf1166937748c6Steve Block      __ movq(temp, FieldOperand(temp, JSFunction::kContextOffset));
94259151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering rsi.
94359151504615d929945dc59db37bf1166937748c6Steve Block      context = temp;
94459151504615d929945dc59db37bf1166937748c6Steve Block    }
94559151504615d929945dc59db37bf1166937748c6Steve Block  }
94659151504615d929945dc59db37bf1166937748c6Steve Block  // Check that last extension is NULL.
94759151504615d929945dc59db37bf1166937748c6Steve Block  __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
94859151504615d929945dc59db37bf1166937748c6Steve Block  __ j(not_equal, slow);
94959151504615d929945dc59db37bf1166937748c6Steve Block  __ movq(temp, ContextOperand(context, Context::FCONTEXT_INDEX));
95059151504615d929945dc59db37bf1166937748c6Steve Block  return ContextOperand(temp, slot->index());
95159151504615d929945dc59db37bf1166937748c6Steve Block}
95259151504615d929945dc59db37bf1166937748c6Steve Block
95359151504615d929945dc59db37bf1166937748c6Steve Block
95459151504615d929945dc59db37bf1166937748c6Steve Blockvoid FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
95559151504615d929945dc59db37bf1166937748c6Steve Block    Slot* slot,
95659151504615d929945dc59db37bf1166937748c6Steve Block    TypeofState typeof_state,
95759151504615d929945dc59db37bf1166937748c6Steve Block    Label* slow,
95859151504615d929945dc59db37bf1166937748c6Steve Block    Label* done) {
95959151504615d929945dc59db37bf1166937748c6Steve Block  // Generate fast-case code for variables that might be shadowed by
96059151504615d929945dc59db37bf1166937748c6Steve Block  // eval-introduced variables.  Eval is used a lot without
96159151504615d929945dc59db37bf1166937748c6Steve Block  // introducing variables.  In those cases, we do not want to
96259151504615d929945dc59db37bf1166937748c6Steve Block  // perform a runtime call for all variables in the scope
96359151504615d929945dc59db37bf1166937748c6Steve Block  // containing the eval.
96459151504615d929945dc59db37bf1166937748c6Steve Block  if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
96559151504615d929945dc59db37bf1166937748c6Steve Block    EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow);
96659151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(done);
96759151504615d929945dc59db37bf1166937748c6Steve Block  } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
9680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot();
96959151504615d929945dc59db37bf1166937748c6Steve Block    Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
97059151504615d929945dc59db37bf1166937748c6Steve Block    if (potential_slot != NULL) {
97159151504615d929945dc59db37bf1166937748c6Steve Block      // Generate fast case for locals that rewrite to slots.
97259151504615d929945dc59db37bf1166937748c6Steve Block      __ movq(rax,
97359151504615d929945dc59db37bf1166937748c6Steve Block              ContextSlotOperandCheckExtensions(potential_slot, slow));
97459151504615d929945dc59db37bf1166937748c6Steve Block      if (potential_slot->var()->mode() == Variable::CONST) {
97559151504615d929945dc59db37bf1166937748c6Steve Block        __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
97659151504615d929945dc59db37bf1166937748c6Steve Block        __ j(not_equal, done);
97759151504615d929945dc59db37bf1166937748c6Steve Block        __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
97859151504615d929945dc59db37bf1166937748c6Steve Block      }
97959151504615d929945dc59db37bf1166937748c6Steve Block      __ jmp(done);
98059151504615d929945dc59db37bf1166937748c6Steve Block    } else if (rewrite != NULL) {
98159151504615d929945dc59db37bf1166937748c6Steve Block      // Generate fast case for calls of an argument function.
98259151504615d929945dc59db37bf1166937748c6Steve Block      Property* property = rewrite->AsProperty();
98359151504615d929945dc59db37bf1166937748c6Steve Block      if (property != NULL) {
98459151504615d929945dc59db37bf1166937748c6Steve Block        VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
98559151504615d929945dc59db37bf1166937748c6Steve Block        Literal* key_literal = property->key()->AsLiteral();
98659151504615d929945dc59db37bf1166937748c6Steve Block        if (obj_proxy != NULL &&
98759151504615d929945dc59db37bf1166937748c6Steve Block            key_literal != NULL &&
98859151504615d929945dc59db37bf1166937748c6Steve Block            obj_proxy->IsArguments() &&
98959151504615d929945dc59db37bf1166937748c6Steve Block            key_literal->handle()->IsSmi()) {
99059151504615d929945dc59db37bf1166937748c6Steve Block          // Load arguments object if there are no eval-introduced
99159151504615d929945dc59db37bf1166937748c6Steve Block          // variables. Then load the argument from the arguments
99259151504615d929945dc59db37bf1166937748c6Steve Block          // object using keyed load.
99359151504615d929945dc59db37bf1166937748c6Steve Block          __ movq(rdx,
9940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                  ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
99559151504615d929945dc59db37bf1166937748c6Steve Block                                                    slow));
99659151504615d929945dc59db37bf1166937748c6Steve Block          __ Move(rax, key_literal->handle());
99759151504615d929945dc59db37bf1166937748c6Steve Block          Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
9980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitCallIC(ic, RelocInfo::CODE_TARGET);
99959151504615d929945dc59db37bf1166937748c6Steve Block          __ jmp(done);
100059151504615d929945dc59db37bf1166937748c6Steve Block        }
100159151504615d929945dc59db37bf1166937748c6Steve Block      }
100259151504615d929945dc59db37bf1166937748c6Steve Block    }
100359151504615d929945dc59db37bf1166937748c6Steve Block  }
100459151504615d929945dc59db37bf1166937748c6Steve Block}
100559151504615d929945dc59db37bf1166937748c6Steve Block
100659151504615d929945dc59db37bf1166937748c6Steve Block
10070d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EmitVariableLoad(Variable* var) {
1008d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Four cases: non-this global variables, lookup slots, all other
1009d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // types of slots, and parameters that rewrite to explicit property
1010d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // accesses on the arguments object.
10110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Slot* slot = var->AsSlot();
1012d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Property* property = var->AsProperty();
1013d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1014d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (var->is_global() && !var->is_this()) {
10153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Comment cmnt(masm_, "Global variable");
10163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Use inline caching. Variable name is passed in rcx and the global
10173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // object on the stack.
1018e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ Move(rcx, var->name());
10197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ movq(rax, CodeGenerator::GlobalObject());
10203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
10210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
10220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
1023d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1024d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
102559151504615d929945dc59db37bf1166937748c6Steve Block    Label done, slow;
102659151504615d929945dc59db37bf1166937748c6Steve Block
102759151504615d929945dc59db37bf1166937748c6Steve Block    // Generate code for loading from variables potentially shadowed
102859151504615d929945dc59db37bf1166937748c6Steve Block    // by eval-introduced variables.
102959151504615d929945dc59db37bf1166937748c6Steve Block    EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
103059151504615d929945dc59db37bf1166937748c6Steve Block
103159151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
1032d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Lookup slot");
1033d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ push(rsi);  // Context.
1034d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ Push(var->name());
1035d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
103659151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&done);
103759151504615d929945dc59db37bf1166937748c6Steve Block
10380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
1039d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1040d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL) {
1041d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1042d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            ? "Context slot"
1043d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            : "Stack slot");
1044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (var->mode() == Variable::CONST) {
1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Constants may be the hole value if they have not been initialized.
1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Unhole them.
10470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      NearLabel done;
1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      MemOperand slot_operand = EmitSlotSearch(slot, rax);
1049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ movq(rax, slot_operand);
1050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ j(not_equal, &done);
1052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ bind(&done);
10540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(rax);
1055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
10560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(slot);
1057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1058d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1059d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1060d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Rewritten parameter");
1061d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(property);
1062d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Rewritten parameter accesses are of the form "slot[literal]".
1063d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1064e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the object is in a slot.
1065e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1066e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT_NOT_NULL(object_var);
10670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* object_slot = object_var->AsSlot();
1068d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(object_slot);
1069d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1070d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the object.
1071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    MemOperand object_loc = EmitSlotSearch(object_slot, rax);
10727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ movq(rdx, object_loc);
1073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the key is a smi.
1075d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key_literal = property->key()->AsLiteral();
1076d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(key_literal);
1077d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(key_literal->handle()->IsSmi());
1078d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1079d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the key.
10807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ Move(rax, key_literal->handle());
1081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1082e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Do a keyed property load.
1083d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
10840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET);
10850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
10863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
10873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
10883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1090d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1091d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ RegExpLiteral");
1092bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label materialized;
10933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Registers will be used as follows:
10943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // rdi = JS function.
1095bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // rcx = literals array.
1096bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // rbx = regexp literal.
1097bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // rax = regexp literal clone.
10983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1099bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
11003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int literal_offset =
110180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1102bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(rbx, FieldOperand(rcx, literal_offset));
1103bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
1104bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(not_equal, &materialized);
1105bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
11063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Create regexp literal using runtime function
11073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Result will be in rax.
1108bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(rcx);
11093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(expr->pattern());
11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(expr->flags());
11123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1113bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(rbx, rax);
1114bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1115bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&materialized);
1116bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1117bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label allocated, runtime_allocate;
1118bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
1119bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ jmp(&allocated);
1120bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1121bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&runtime_allocate);
1122bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(rbx);
1123bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ Push(Smi::FromInt(size));
1124bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1125bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(rbx);
1126bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1127bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&allocated);
1128bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Copy the content into the newly allocated memory.
1129bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // (Unroll copy loop once for better throughput).
1130bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
1131bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(rdx, FieldOperand(rbx, i));
1132bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(rcx, FieldOperand(rbx, i + kPointerSize));
1133bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(FieldOperand(rax, i), rdx);
1134bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(FieldOperand(rax, i + kPointerSize), rcx);
1135bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1136bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if ((size % (2 * kPointerSize)) != 0) {
1137bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(rdx, FieldOperand(rbx, size - kPointerSize));
1138bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(FieldOperand(rax, size - kPointerSize), rdx);
1139bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
11400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
1141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1144d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
1146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1147e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
1148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
1149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Push(expr->constant_properties());
11506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(Smi::FromInt(expr->fast_elements() ? 1 : 0));
1151e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->depth() > 1) {
11526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
11533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
11546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
1155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1157e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
1158e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in rax.
1159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
1160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < expr->properties()->length(); i++) {
1162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectLiteral::Property* property = expr->properties()->at(i);
1163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
1164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = property->key();
1166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
1167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
1168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ push(rax);  // Save result on the stack
1169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
1170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
1172e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::CONSTANT:
1173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        UNREACHABLE();
1174e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1176e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
1178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (key->handle()->IsSymbol()) {
11790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForAccumulatorValue(value);
1180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Move(rcx, key->handle());
11814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ movq(rdx, Operand(rsp, 0));
1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
11830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitCallIC(ic, RelocInfo::CODE_TARGET);
1184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::PROTOTYPE:
1188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(rsp, 0));  // Duplicate receiver.
11890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(key);
11900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(value);
1191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kSetProperty, 3);
1192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::SETTER:
1194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::GETTER:
1195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(rsp, 0));  // Duplicate receiver.
11960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(key);
1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ Push(property->kind() == ObjectLiteral::Property::SETTER ?
1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                Smi::FromInt(1) :
1199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                Smi::FromInt(0));
12000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(value);
1201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDefineAccessor, 4);
1202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1205e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
12070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1208e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
12090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
12103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
12123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1214d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
12153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
1216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<Expression*>* subexprs = expr->values();
1218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int length = subexprs->length();
1219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
12203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
12223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
1223e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Push(expr->constant_elements());
1224756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) {
1225756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    FastCloneShallowArrayStub stub(
1226756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
1227756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
1228756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1);
1229756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (expr->depth() > 1) {
1230e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
1231756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
1232e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
1233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1234756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    FastCloneShallowArrayStub stub(
1235756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        FastCloneShallowArrayStub::CLONE_ELEMENTS, length);
1236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
12373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
12403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
12423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
1243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < length; i++) {
12443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Expression* subexpr = subexprs->at(i);
12453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
12463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
12473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (subexpr->AsLiteral() != NULL ||
12483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        CompileTimeValue::IsCompileTimeValue(subexpr)) {
12493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      continue;
12503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
12513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
12533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(rax);
12543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
12553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
12560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(subexpr);
12573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Store the subexpression value in the array's elements.
12593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(rbx, Operand(rsp, 0));  // Copy of array literal.
12603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
12613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ movq(FieldOperand(rbx, offset), result_register());
12633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Update the write barrier for the array store.
1265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ RecordWrite(rbx, offset, result_register(), rcx);
12663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
12690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
12710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
12723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
12743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1276402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1277402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Comment cmnt(masm_, "[ Assignment");
1278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // on the left-hand side.
1280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->target()->IsValidLeftHandSide()) {
1281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->target());
1282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1285402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Left-hand side can only be a property, a global or a (parameter or local)
1286402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1287402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1288402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LhsKind assign_type = VARIABLE;
128980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Property* property = expr->target()->AsProperty();
129080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (property != NULL) {
129180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    assign_type = (property->key()->IsPropertyName())
129280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? NAMED_PROPERTY
129380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : KEYED_PROPERTY;
1294402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1295402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1296402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate LHS expression.
1297402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1298402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1299402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Nothing to do here.
1300402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1301402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1302402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1303402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // We need the receiver both on the stack and in the accumulator.
13040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(property->obj());
1305402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1306402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
13070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
1308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1309402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1310402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (expr->is_compound()) {
13120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
13130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(property->key());
1314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ movq(rdx, Operand(rsp, 0));
1315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(rax);
1316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else {
13170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
13180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->key());
1319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
1320402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1321402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1322402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1323402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
13240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    { AccumulatorValueContext context(this);
13250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
13260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
13270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitVariableLoad(expr->target()->AsVariableProxy()->var());
13280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
13290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
13300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitNamedPropertyLoad(property);
13310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
13320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
13330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitKeyedPropertyLoad(property);
13340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
13350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
1336402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1337402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
133880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Token::Value op = expr->binary_op();
133980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ConstantOperand constant = ShouldInlineSmiCase(op)
134080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? GetConstantOperand(op, expr->target(), expr->value())
134180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : kNoConstants;
134280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    ASSERT(constant == kRightConstant || constant == kNoConstants);
134380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (constant == kNoConstants) {
134480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ push(rax);  // Left operand goes on the stack.
13450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->value());
134680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
1347402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
134880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
134980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? OVERWRITE_RIGHT
135080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : NO_OVERWRITE;
135180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    SetSourcePosition(expr->position() + 1);
13520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
135380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (ShouldInlineSmiCase(op)) {
135480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      EmitInlineSmiBinaryOp(expr,
135580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            op,
135680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            mode,
135780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            expr->target(),
135880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            expr->value(),
135980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            constant);
136080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    } else {
13610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitBinaryOp(op, mode);
136280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
136380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
13640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->value());
1365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1366402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1367402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Record source position before possible IC call.
1368402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  SetSourcePosition(expr->position());
1369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1370402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Store the value.
1371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1372402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1373402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
13740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             expr->op());
1375402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1376402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1377402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitNamedPropertyAssignment(expr);
1378402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1380402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitKeyedPropertyAssignment(expr);
1381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1383402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1384402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1385402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1386d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Literal* key = prop->key()->AsLiteral();
1389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, key->handle());
1390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
13910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1395d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
13980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
140280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
140380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Token::Value op,
140480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              OverwriteMode mode,
140580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Expression* left,
140680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Expression* right,
140780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              ConstantOperand constant) {
140880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(constant == kNoConstants);  // Only handled case.
140980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
141080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Do combined smi check of the operands. Left operand is on the
141180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // stack (popped into rdx). Right operand is in rax but moved into
141280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rcx to make the shifts easier.
141380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label done, stub_call, smi_case;
141480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ pop(rdx);
141580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movq(rcx, rax);
1416f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Condition smi = masm()->CheckBothSmi(rdx, rax);
141780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(smi, &smi_case);
141880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
141980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&stub_call);
142080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown());
142180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (stub.ArgsInRegistersSupported()) {
142280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    stub.GenerateCall(masm_, rdx, rcx);
142380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
142480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(rdx);
142580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(rcx);
142680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CallStub(&stub);
142780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
142880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(&done);
142980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
143080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&smi_case);
143180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
143280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SAR:
143380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiShiftArithmeticRight(rax, rdx, rcx);
143480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
143580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHL:
143680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiShiftLeft(rax, rdx, rcx);
143780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
143880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHR:
143980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiShiftLogicalRight(rax, rdx, rcx, &stub_call);
144080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
144180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::ADD:
144280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiAdd(rax, rdx, rcx, &stub_call);
144380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
144480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SUB:
144580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiSub(rax, rdx, rcx, &stub_call);
144680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
144780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::MUL:
144880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiMul(rax, rdx, rcx, &stub_call);
144980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
145080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_OR:
145180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiOr(rax, rdx, rcx);
145280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
145380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_AND:
145480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiAnd(rax, rdx, rcx);
145580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
145680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_XOR:
145780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiXor(rax, rdx, rcx);
145880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
145980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    default:
146080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      UNREACHABLE();
146180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
146280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
146380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
146480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&done);
14650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
146680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
146780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
146880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1469d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitBinaryOp(Token::Value op,
147080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                     OverwriteMode mode) {
147180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS);
147280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (stub.ArgsInRegistersSupported()) {
147380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ pop(rdx);
147480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    stub.GenerateCall(masm_, rdx, rax);
147580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
147680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(result_register());
147780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CallStub(&stub);
147880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
14790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
1480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitAssignment(Expression* expr) {
1484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw
1485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ReferenceError' on the left-hand side.
1486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->IsValidLeftHandSide()) {
1487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr);
1488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand side can only be a property, a global or a (parameter or local)
1492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  LhsKind assign_type = VARIABLE;
1495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = expr->AsProperty();
1496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (prop != NULL) {
1497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    assign_type = (prop->key()->IsPropertyName())
1498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ? NAMED_PROPERTY
1499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        : KEYED_PROPERTY;
1500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (assign_type) {
1503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case VARIABLE: {
1504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->AsVariableProxy()->var();
15050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EffectContext context(this);
15060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitVariableAssignment(var, Token::ASSIGN);
1507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case NAMED_PROPERTY: {
1510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(rax);  // Preserve value.
15110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
1512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ movq(rdx, rax);
1513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(rax);  // Restore value.
1514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ Move(rcx, prop->key()->AsLiteral()->handle());
1515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
15160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
1517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case KEYED_PROPERTY: {
1520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(rax);  // Preserve value.
15210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(prop->obj());
15220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->key());
15238defd9ff6930b4e24729971a61cf7469daf119beSteve Block      __ movq(rcx, rax);
15248defd9ff6930b4e24729971a61cf7469daf119beSteve Block      __ pop(rdx);
15258defd9ff6930b4e24729971a61cf7469daf119beSteve Block      __ pop(rax);
1526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
15270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
1528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1534d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var,
15350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                               Token::Value op) {
1536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand sides that rewrite to explicit property accesses do not reach
1537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // here.
15383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(var != NULL);
15390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(var->is_global() || var->AsSlot() != NULL);
1540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
15413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (var->is_global()) {
1542d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT(!var->is_this());
1543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Assignment to a global variable.  Use inline caching for the
1544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // assignment.  Right-hand-side value is passed in rax, variable name in
1545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // rcx, and the global object on the stack.
15463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(rcx, var->name());
15474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ movq(rdx, CodeGenerator::GlobalObject());
15483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
15490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET);
1550d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) {
1552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Perform the assignment for non-const variables and for initialization
1553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // of const variables.  Const assignments are simply skipped.
1554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Label done;
15550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* slot = var->AsSlot();
1556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
1557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
1558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      case Slot::LOCAL:
1559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Detect const reinitialization by checking for the hole value.
1561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ movq(rdx, Operand(rbp, SlotOffset(slot)));
1562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ j(not_equal, &done);
1564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment.
1566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ movq(Operand(rbp, SlotOffset(slot)), rax);
1567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT: {
1570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        MemOperand target = EmitSlotSearch(slot, rcx);
1571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Detect const reinitialization by checking for the hole value.
1573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ movq(rdx, target);
1574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ j(not_equal, &done);
1576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment and issue the write barrier.
1578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ movq(target, rax);
1579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The value of the assignment is in rax.  RecordWrite clobbers its
1580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // register arguments.
1581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ movq(rdx, rax);
1582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
1583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ RecordWrite(rcx, offset, rdx, rbx);
1584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
15853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
1586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP:
1588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Call the runtime for the assignment.  The runtime will ignore
1589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // const reinitialization.
1590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(rax);  // Value.
1591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(rsi);  // Context.
1592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ Push(var->name());
1593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (op == Token::INIT_CONST) {
1594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // The runtime will ignore const redeclaration.
1595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else {
1597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kStoreContextSlot, 3);
1598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
16003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&done);
16023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
16040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
16053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1608d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
1610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
1611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop != NULL);
1612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop->key()->AsLiteral() != NULL);
16133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(Operand(rsp, kPointerSize));  // Receiver is now under value.
1620d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Move(rcx, prop->key()->AsLiteral()->handle());
16274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (expr->ends_initialization_block()) {
16284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ movq(rdx, Operand(rsp, 0));
16294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
16304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ pop(rdx);
16314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
1632d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
16330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1634d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1635d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1636d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(rax);  // Result of assignment, saved even if not needed.
1638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(rsp, kPointerSize));  // Receiver is under value.
1639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1640d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(rax);
16410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->DropAndPlug(1, rax);
16424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
16430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
1644d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1647d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1648d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1649d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
1650d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1651d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1654d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Receiver is now under the key and value.
1657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(rsp, 2 * kPointerSize));
1658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1660d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1661d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(rcx);
1663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (expr->ends_initialization_block()) {
1664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movq(rdx, Operand(rsp, 0));  // Leave receiver on the stack for later.
1665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ pop(rdx);
1667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
16710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ pop(rdx);
1676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(rax);  // Result of assignment, saved even if not needed.
1677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(rdx);
1678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1679d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(rax);
1680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1681d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
16820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
1683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1686d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) {
1687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Property");
1688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* key = expr->key();
1689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (key->IsPropertyName()) {
16910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->obj());
1692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitNamedPropertyLoad(expr);
1693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
16940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(expr->obj());
16950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->key());
16967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ pop(rdx);
1697e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitKeyedPropertyLoad(expr);
1698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
16990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
1700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1703d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr,
1704402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                       Handle<Object> name,
1705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       RelocInfo::Mode mode) {
1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the IC.
1707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
17083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
17093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
17100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
17113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1712402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ Move(rcx, name);
1713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
17143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SetSourcePosition(expr->position());
17153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the IC initialization code.
1716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
17173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
1718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                                         in_loop);
17190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, mode);
1720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Restore context register.
1721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
17220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
1723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
17269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
17279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                            Expression* key,
17289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                            RelocInfo::Mode mode) {
17299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Code common for calls using the IC.
17309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ZoneList<Expression*>* args = expr->arguments();
17319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  int arg_count = args->length();
17329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  for (int i = 0; i < arg_count; i++) {
17330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
17349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
17350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(key);
17369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ movq(rcx, rax);
17379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Record source position for debugger.
17389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  SetSourcePosition(expr->position());
17399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Call the IC initialization code.
17409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
17419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count,
17429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                                              in_loop);
17430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, mode);
17449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Restore context register.
17459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
17460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
17479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
17489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
17499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1750d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) {
1751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the call stub.
1752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
1754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
17550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
1756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
1758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
1759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ CallStub(&stub);
17623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore context register.
17633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
17643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Discard the function left on TOS.
17650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->DropAndPlug(1, rax);
1766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1769d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) {
1770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Call");
1771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* fun = expr->expression();
1772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Variable* var = fun->AsVariableProxy()->AsVariable();
1773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (var != NULL && var->is_possibly_eval()) {
1775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // In a call to eval, we first call %ResolvePossiblyDirectEval to
1776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // resolve the function we need to call and the receiver of the
1777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // call.  The we call the resolved function using the given
1778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // arguments.
17790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(fun);
1780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ PushRoot(Heap::kUndefinedValueRootIndex);  // Reserved receiver slot.
1781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push the arguments.
1783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    ZoneList<Expression*>* args = expr->arguments();
1784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    int arg_count = args->length();
1785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    for (int i = 0; i < arg_count; i++) {
17860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(args->at(i));
1787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push copy of the function - found below the arguments.
1790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Operand(rsp, (arg_count + 1) * kPointerSize));
1791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push copy of the first argument or undefined if it doesn't exist.
1793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (arg_count > 0) {
1794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(Operand(rsp, arg_count * kPointerSize));
1795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
1796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ PushRoot(Heap::kUndefinedValueRootIndex);
1797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Push the receiver of the enclosing function and do runtime call.
1800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize));
1801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
1802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The runtime call returns a pair of values in rax (function) and
1804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // rdx (receiver). Touch up the stack with the right values.
1805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
1806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
1807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Record source position for debugger.
1809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    SetSourcePosition(expr->position());
1810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
1813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Restore context register.
1814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
18150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->DropAndPlug(1, rax);
1816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (var != NULL && !var->is_this() && var->is_global()) {
1817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to a global variable.
1818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Push global object as receiver for the call IC lookup.
1819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(CodeGenerator::GlobalObject());
1820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
18210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (var != NULL && var->AsSlot() != NULL &&
18220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen             var->AsSlot()->type() == Slot::LOOKUP) {
182359151504615d929945dc59db37bf1166937748c6Steve Block    // Call to a lookup slot (dynamically introduced variable).
182459151504615d929945dc59db37bf1166937748c6Steve Block    Label slow, done;
182559151504615d929945dc59db37bf1166937748c6Steve Block
182659151504615d929945dc59db37bf1166937748c6Steve Block    // Generate code for loading from variables potentially shadowed
182759151504615d929945dc59db37bf1166937748c6Steve Block    // by eval-introduced variables.
18280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitDynamicLoadFromSlotFastCase(var->AsSlot(),
182959151504615d929945dc59db37bf1166937748c6Steve Block                                    NOT_INSIDE_TYPEOF,
183059151504615d929945dc59db37bf1166937748c6Steve Block                                    &slow,
183159151504615d929945dc59db37bf1166937748c6Steve Block                                    &done);
183259151504615d929945dc59db37bf1166937748c6Steve Block
183359151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
183459151504615d929945dc59db37bf1166937748c6Steve Block    // Call the runtime to find the function to call (returned in rax)
183559151504615d929945dc59db37bf1166937748c6Steve Block    // and the object holding it (returned in rdx).
1836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(context_register());
1837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Push(var->name());
1838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
1839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(rax);  // Function.
1840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(rdx);  // Receiver.
184159151504615d929945dc59db37bf1166937748c6Steve Block
184259151504615d929945dc59db37bf1166937748c6Steve Block    // If fast case code has been generated, emit code to push the
184359151504615d929945dc59db37bf1166937748c6Steve Block    // function and receiver and have the slow path jump around this
184459151504615d929945dc59db37bf1166937748c6Steve Block    // code.
184559151504615d929945dc59db37bf1166937748c6Steve Block    if (done.is_linked()) {
18460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      NearLabel call;
184759151504615d929945dc59db37bf1166937748c6Steve Block      __ jmp(&call);
184859151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&done);
184959151504615d929945dc59db37bf1166937748c6Steve Block      // Push function.
185059151504615d929945dc59db37bf1166937748c6Steve Block      __ push(rax);
185159151504615d929945dc59db37bf1166937748c6Steve Block      // Push global receiver.
185259151504615d929945dc59db37bf1166937748c6Steve Block      __ movq(rbx, CodeGenerator::GlobalObject());
185359151504615d929945dc59db37bf1166937748c6Steve Block      __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
185459151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&call);
185559151504615d929945dc59db37bf1166937748c6Steve Block    }
185659151504615d929945dc59db37bf1166937748c6Steve Block
1857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitCallWithStub(expr);
185859151504615d929945dc59db37bf1166937748c6Steve Block
1859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (fun->AsProperty() != NULL) {
1860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to an object property.
1861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Property* prop = fun->AsProperty();
1862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = prop->key()->AsLiteral();
1863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (key != NULL && key->handle()->IsSymbol()) {
1864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Call to a named property, use call IC.
18650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(prop->obj());
1866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
18689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Call to a keyed property.
18699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // For a synthetic property use keyed load IC followed by function call,
18709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // for a regular property use KeyedCallIC.
18710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(prop->obj());
1872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (prop->is_synthetic()) {
18730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(prop->key());
18749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        __ movq(rdx, Operand(rsp, 0));
18759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // Record source code position for IC call.
18769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        SetSourcePosition(prop->position());
18779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
18780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        EmitCallIC(ic, RelocInfo::CODE_TARGET);
18799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // Pop receiver.
18809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        __ pop(rbx);
18819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // Push result (function).
18829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        __ push(rax);
18839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // Push receiver object on stack.
1884e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ movq(rcx, CodeGenerator::GlobalObject());
1885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
18869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        EmitCallWithStub(expr);
1887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
18889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
1889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
18913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
1892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to some other expression.  If the expression is an anonymous
1893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // function literal not called in a loop, mark it as one that should
1894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // also use the fast code generator.
1895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    FunctionLiteral* lit = fun->AsFunctionLiteral();
1896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (lit != NULL &&
1897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        lit->name()->Equals(Heap::empty_string()) &&
1898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        loop_depth() == 0) {
1899d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      lit->set_try_full_codegen(true);
1900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
19010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(fun);
1902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load global receiver object.
1903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ movq(rbx, CodeGenerator::GlobalObject());
1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
1905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit function call.
1906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    EmitCallWithStub(expr);
1907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1911d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
1912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
1913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
1914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
1915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
1916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
191780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Push constructor on the stack.  If it's not a function it's used as
191880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
191980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ignored.
19200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->expression());
1921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
1923d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
1925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
19260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
19273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
1930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
1931d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
1932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
193380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load function and argument count into rdi and rax.
1934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Set(rax, arg_count);
193580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movq(rdi, Operand(rsp, arg_count * kPointerSize));
1936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
1938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
19390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
19403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
19413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
1944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
1947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
195180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
19520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
19530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
1954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_true);
1956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
1957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
1959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
1963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
1966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
197080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
19710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
19720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
1973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1974f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax);
1975f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Split(non_negative_smi, if_true, if_false, fall_through);
1976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
1978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
1982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
1983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
1985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
198980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
19900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
19910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
1992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
1994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareRoot(rax, Heap::kNullValueRootIndex);
1995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
1997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Undetectable objects behave like undefined when tested with typeof.
1998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
1999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke           Immediate(1 << Map::kIsUndetectable));
2000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_zero, if_false);
2001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE));
2003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, if_false);
2004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE));
200580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(below_equal, if_true, if_false, fall_through);
2006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
20123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(args->length() == 1);
20133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
20153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label materialize_true, materialize_false;
20173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_true = NULL;
20183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_false = NULL;
201980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
20200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
20210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
20223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ JumpIfSmi(rax, if_false);
20243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx);
202580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(above_equal, if_true, if_false, fall_through);
20263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
20283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
20293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
2031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
2032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
203980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
20400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
20410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke           Immediate(1 << Map::kIsUndetectable));
204780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(not_zero, if_true, if_false, fall_through);
2048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2053756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2054756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    ZoneList<Expression*>* args) {
2055756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ASSERT(args->length() == 1);
2056756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
20570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2058756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2059756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label materialize_true, materialize_false;
2060756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_true = NULL;
2061756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_false = NULL;
206280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
20630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
20640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2065756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2066756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only
2067756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // used in a few functions in runtime.js which should not normally be hit by
2068756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // this compiler.
2069756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ jmp(if_false);
20700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2071756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2072756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2073756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
2075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
208280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
20830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
20840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
208880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
2095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
210280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
21030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
21040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
210880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
2115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2118f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
212280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
21230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
21240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
212880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
2136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
214180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
21420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
21430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the frame pointer for the calling frame.
2146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Skip the arguments adaptor frame if it exists.
2149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label check_frame_marker;
2150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset),
2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &check_frame_marker);
2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check the marker in the calling frame.
2156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&check_frame_marker);
2157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset),
2158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                Smi::FromInt(StackFrame::CONSTRUCT));
215980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
2166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the two objects into registers and perform the comparison.
21690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
21700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
2171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2172f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
217580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
21760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
21770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(rbx);
2180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(rax, rbx);
218180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2188f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
219080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ArgumentsAccessStub expects the key in rdx and the formal
219180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // parameter count in rax.
21920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rdx, rax);
2194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Move(rax, Smi::FromInt(scope()->num_parameters()));
2195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
21970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
22040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel exit;
2205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the number of formal parameters.
2206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Move(rax, Smi::FromInt(scope()->num_parameters()));
2207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the calling frame is an arguments adaptor frame.
2209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ SmiCompare(Operand(rbx, StandardFrameConstants::kContextOffset),
2211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Arguments adaptor case: Read the arguments length from the
2215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // adaptor frame.
2216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
2219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (FLAG_debug_code) __ AbortIfNotSmi(rax);
22200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
2225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, null, function, non_function_constructor;
2227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
22280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, we return null.
2231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, &null);
2232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check that the object is a JS object but take special care of JS
2234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // functions to make sure they have 'Function' as their class.
2235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rax);  // Map is now in rax.
2236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, &null);
2237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // As long as JS_FUNCTION_TYPE is the last instance type and it is
2239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
2240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // LAST_JS_OBJECT_TYPE.
2241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
2242f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
2243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpInstanceType(rax, JS_FUNCTION_TYPE);
2244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &function);
2245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the constructor in the map is a function.
2247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rax, Map::kConstructorOffset));
2248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &non_function_constructor);
2250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // rax now contains the constructor function. Grab the
2252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // instance class name from there.
2253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
2254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset));
2255f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Functions have class 'Function'.
2258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&function);
2259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Move(rax, Factory::function_class_symbol());
2260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Objects with a non-function constructor have class 'Object'.
2263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&non_function_constructor);
2264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Move(rax, Factory::Object_symbol());
2265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-JS objects have class null.
2268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&null);
2269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(rax, Heap::kNullValueRootIndex);
2270f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // All done.
2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
22740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
2279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Conditionally generate a log call.
2280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Args:
2281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   0 (literal string): The type of logging (corresponds to the flags).
2282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     This is used to determine whether or not to generate the log call.
2283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   1 (string): Format string.  Access the string at argument index 2
2284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     with '%2s' (see Logger::LogRuntime for all the formats).
2285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   2 (array): Arguments to the format string.
2286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 3);
2287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING
2288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
22890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(1));
22900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(2));
2291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLog, 2);
2292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2293f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif
2294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Finally, we're expected to leave a value on the top of the stack.
2295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
22960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
2301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label slow_allocate_heapnumber;
2304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label heapnumber_allocated;
2305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ AllocateHeapNumber(rbx, rcx, &slow_allocate_heapnumber);
2307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&heapnumber_allocated);
2308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&slow_allocate_heapnumber);
23103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Allocate a heap number.
23113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CallRuntime(Runtime::kNumberAlloc, 0);
2312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, rax);
2313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&heapnumber_allocated);
2315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Return a random uint32 number in rax.
2317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs.
2318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ PrepareCallCFunction(0);
2319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallCFunction(ExternalReference::random_uint32_function(), 0);
2320f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert 32 random bits in rax to 0.(32 random bits) in a double
2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // by computing:
2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rcx, Immediate(0x49800000));  // 1.0 x 2^20 as single.
2325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movd(xmm1, rcx);
2326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movd(xmm0, rax);
2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cvtss2sd(xmm1, xmm1);
2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ xorpd(xmm0, xmm1);
2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ subsd(xmm0, xmm1);
2330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0);
2331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, rbx);
23330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
2338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SubStringStub stub;
2340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
23410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
23420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
23430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
2344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
23450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
2350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  RegExpExecStub stub;
2352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 4);
23530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
23540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
23550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
23560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(3));
2357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
23580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
2363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));  // Load the object.
2366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
2368f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi return the object.
2369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, &done);
2370f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the object.
2371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_VALUE_TYPE, rbx);
2372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &done);
2373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rax, JSValue::kValueOffset));
2374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
23760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2380f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
2381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the runtime function.
2382f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
23830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
23840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
2385f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_pow, 2);
23860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2387f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2390f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
2391f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2392f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));  // Load the object.
23940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));  // Load the value.
239580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ pop(rbx);  // rax = value. rbx = object.
2396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
2398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, return the value.
2399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rbx, &done);
2400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the value.
2402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx);
2403f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &done);
2404f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Store the value.
2406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(FieldOperand(rbx, JSValue::kValueOffset), rax);
2407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the write barrier.  Save the value as it will be
2408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // overwritten by the write barrier code and is needed afterward.
2409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rdx, rax);
2410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ RecordWrite(rbx, JSValue::kValueOffset, rdx, rcx);
2411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2412f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
24130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
2418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 1);
2419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
24210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  NumberToStringStub stub;
2424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
24250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
2430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
24357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharFromCodeGenerator generator(rax, rbx);
24367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
24377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
2438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
24407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
2441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
24430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rbx);
24447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
24457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
24487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
24497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
24510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
24527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = rbx;
24547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = rax;
24557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch = rcx;
24567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = rdx;
24577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
24597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
24617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
24627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
24637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharCodeAtGenerator generator(object,
24647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      index,
24657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      scratch,
24667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      result,
24677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
24687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
24697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &index_out_of_range,
24707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      STRING_INDEX_IS_NUMBER);
24717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
2472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
24757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
24767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // NaN.
24777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kNanValueRootIndex);
24787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
24797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
24817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move the undefined value into the result register, which will
24827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // trigger conversion.
24837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
24847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
24857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
24877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
2488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
24900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
2491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
24957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
24967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
24980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
24997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = rbx;
25017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = rax;
25027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch1 = rcx;
25037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch2 = rdx;
25047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = rax;
25057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
25077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
25097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
25107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
25117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharAtGenerator generator(object,
25127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  index,
25137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  scratch1,
25147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  scratch2,
25157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  result,
25167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
25177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
25187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &index_out_of_range,
25197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  STRING_INDEX_IS_NUMBER);
25207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
25217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
25227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
25247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
25257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the empty string.
25267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kEmptyStringRootIndex);
25277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
25287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
25307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move smi zero into the result register, which will trigger
25317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // conversion.
25327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Move(result, Smi::FromInt(0));
25337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
25347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
25367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
25377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
25390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
2544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
25470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
2548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringAddStub stub(NO_STRING_ADD_FLAGS);
2550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
25510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
2556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
25590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
2560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringCompareStub stub;
2562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
25630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
2568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
2569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  TranscendentalCacheStub stub(TranscendentalCache::SIN);
2570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
25710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
25730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
2578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
2579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  TranscendentalCacheStub stub(TranscendentalCache::COS);
2580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
25810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
25830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the runtime function.
2589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
25900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_sqrt, 1);
25920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() >= 2);
2598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int arg_count = args->length() - 2;  // For receiver and function.
26000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));  // Receiver.
2601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < arg_count; i++) {
26020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i + 1));
2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
26040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(arg_count + 1));  // Function.
2605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // InvokeFunction requires function in rdi. Move it in there.
2607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!result_register().is(rdi)) __ movq(rdi, result_register());
2608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ParameterCount count(arg_count);
2609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeFunction(rdi, count, CALL_FUNCTION);
2610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
26110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
2616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
26170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
26180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
26190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
2620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kRegExpConstructResult, 3);
26210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
2626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
26270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
26280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
26290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
2630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kSwapElements, 3);
26310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
2636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_NE(NULL, args->at(0)->AsLiteral());
2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<FixedArray> jsfunction_result_caches(
2642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Top::global_context()->jsfunction_result_caches());
2643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (jsfunction_result_caches->length() <= cache_id) {
2644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Abort("Attempt to use undefined cache.");
2645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
26460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
2647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
2651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register key = rax;
2653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register cache = rbx;
2654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register tmp = rcx;
265559151504615d929945dc59db37bf1166937748c6Steve Block  __ movq(cache, ContextOperand(rsi, Context::GLOBAL_INDEX));
2656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(cache,
2657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          FieldOperand(cache, GlobalObject::kGlobalContextOffset));
2658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(cache,
265959151504615d929945dc59db37bf1166937748c6Steve Block          ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
2660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(cache,
2661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
2662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel done, not_found;
2664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // tmp now holds finger offset as a smi.
2665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
2666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
2667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SmiIndex index =
2668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2);
2669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(key, FieldOperand(cache,
2670f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.reg,
2671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.scale,
2672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            FixedArray::kHeaderSize));
2673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &not_found);
2674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(cache,
2675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.reg,
2676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.scale,
2677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            FixedArray::kHeaderSize + kPointerSize));
2678f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&not_found);
2681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call runtime to perform the lookup.
2682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(cache);
2683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(key);
2684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetFromCache, 2);
2685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
26870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2691bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
2692bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT_EQ(2, args->length());
2693bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2694bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register right = rax;
2695bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register left = rbx;
2696bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register tmp = rcx;
2697bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
26980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
26990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
2700bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(left);
2701bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
27020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel done, fail, ok;
2703bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmpq(left, right);
2704bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(equal, &ok);
2705bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Fail if either is a non-HeapObject.
2706bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Condition either_smi = masm()->CheckEitherSmi(left, right, tmp);
2707bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(either_smi, &fail);
2708bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(zero, &fail);
2709bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(tmp, FieldOperand(left, HeapObject::kMapOffset));
2710bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmpb(FieldOperand(tmp, Map::kInstanceTypeOffset),
2711bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch          Immediate(JS_REGEXP_TYPE));
2712bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(not_equal, &fail);
2713bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmpq(tmp, FieldOperand(right, HeapObject::kMapOffset));
2714bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(not_equal, &fail);
2715bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(tmp, FieldOperand(left, JSRegExp::kDataOffset));
2716bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmpq(tmp, FieldOperand(right, JSRegExp::kDataOffset));
2717bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(equal, &ok);
2718bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&fail);
2719bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ Move(rax, Factory::false_value());
2720bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ jmp(&done);
2721bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&ok);
2722bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ Move(rax, Factory::true_value());
2723bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&done);
2724bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
27250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2726bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
2727bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2728bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
272980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
273080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(args->length() == 1);
273180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
27320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
273380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
273480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
273580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
273680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
273780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
27380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
27390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
274080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
274180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ testl(FieldOperand(rax, String::kHashFieldOffset),
274280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           Immediate(String::kContainsCachedArrayIndexMask));
274380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(zero, if_true);
274480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(if_false);
274580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
27460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
274780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
274880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
274980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
275080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
275180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(args->length() == 1);
275280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
27530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
275480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
275580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movl(rax, FieldOperand(rax, String::kHashFieldOffset));
275680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(String::kHashShift >= kSmiTagSize);
275780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ IndexFromHash(rax, rax);
275880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
27590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
276080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
276180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
276280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2763d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
2764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<String> name = expr->name();
2765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (name->length() > 0 && name->Get(0) == '_') {
2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ InlineRuntimeCall");
2767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitInlineRuntimeCall(expr);
2768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ CallRuntime");
27723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* args = expr->arguments();
27733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
2775d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Prepare for calling JS runtime function.
2776d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ movq(rax, CodeGenerator::GlobalObject());
2777d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
2778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
27793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
27803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Push the arguments ("left-to-right").
27813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
27823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
27830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
2784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
2787402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Call the JS runtime function using a call IC.
2788402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ Move(rcx, expr->name());
2789402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2790402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
27910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET);
2792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Restore context register.
2793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
2795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(expr->function(), arg_count);
2796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
27970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2801d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
2803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Token::DELETE: {
2804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
2805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Property* prop = expr->expression()->AsProperty();
2806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
2807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (prop == NULL && var == NULL) {
2808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Result of deleting non-property, non-variable reference is true.
2809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The subexpression may have side effects.
2810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        VisitForEffect(expr->expression());
28110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(true);
2812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else if (var != NULL &&
2813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 !var->is_global() &&
28140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 var->AsSlot() != NULL &&
28150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 var->AsSlot()->type() != Slot::LOOKUP) {
2816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Result of deleting non-global, non-dynamic variables is false.
2817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The subexpression does not have side effects.
28180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(false);
2819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else {
2820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Property or variable reference.  Call the delete builtin with
2821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // object and property name as arguments.
2822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (prop != NULL) {
28230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForStackValue(prop->obj());
28240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForStackValue(prop->key());
2825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (var->is_global()) {
2826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(CodeGenerator::GlobalObject());
2827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ Push(var->name());
2828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else {
2829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Non-global variable.  Call the runtime to look up the context
2830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // where the variable was introduced.
2831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(context_register());
2832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ Push(var->name());
2833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ CallRuntime(Runtime::kLookupContext, 2);
2834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ push(rax);
2835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          __ Push(var->name());
2836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
2837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
28380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(rax);
2839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
2840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
2844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
2845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
28460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(Heap::kUndefinedValueRootIndex);
2847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
2851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label materialize_true, materialize_false;
2853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label* if_true = NULL;
2854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Label* if_false = NULL;
285580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label* fall_through = NULL;
2856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Notice that the labels are swapped.
28570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->PrepareTest(&materialize_true, &materialize_false,
28580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             &if_false, &if_true, &fall_through);
285980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      VisitForControl(expr->expression(), if_true, if_false, fall_through);
28600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(if_false, if_true);  // Labels swapped.
2861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
2865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
28660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      { StackValueContext context(this);
28670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForTypeofValue(expr->expression());
28680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
2869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallRuntime(Runtime::kTypeof, 1);
28700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(rax);
2871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2874d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Token::ADD: {
2875d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Comment cmt(masm_, "[ UnaryOperation (ADD)");
28760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->expression());
28770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      NearLabel no_conversion;
28784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Condition is_smi = masm_->CheckSmi(result_register());
2879d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ j(is_smi, &no_conversion);
2880d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ push(result_register());
2881d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
2882d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ bind(&no_conversion);
28830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(result_register());
2884d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      break;
2885d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
2886d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
28874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::SUB: {
28884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (SUB)");
288980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
2890ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke      UnaryOverwriteMode overwrite =
2891ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke          can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
28920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      GenericUnaryOpStub stub(Token::SUB, overwrite, NO_UNARY_FLAGS);
28934515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // GenericUnaryOpStub expects the argument to be in the
28944515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // accumulator register rax.
28950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->expression());
28964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
28970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(rax);
28984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
28994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
29004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
29014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::BIT_NOT: {
29024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
290380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // The generic unary operation stub expects the argument to be
290480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // in the accumulator register rax.
29050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->expression());
290680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label done;
29070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      bool inline_smi_case = ShouldInlineSmiCase(expr->op());
29080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (inline_smi_case) {
290980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Label call_stub;
291080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ JumpIfNotSmi(rax, &call_stub);
291180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ SmiNot(rax, rax);
291280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ jmp(&done);
291380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&call_stub);
291480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
291580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      bool overwrite = expr->expression()->ResultOverwriteAllowed();
291680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      UnaryOverwriteMode mode =
291780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
29180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      UnaryOpFlags flags = inline_smi_case
29190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          ? NO_UNARY_SMI_CODE_IN_STUB
29200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          : NO_UNARY_FLAGS;
29210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      GenericUnaryOpStub stub(Token::BIT_NOT, mode, flags);
29224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
29234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ bind(&done);
29240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(rax);
29254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
29264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
29274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
2928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
2929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
29303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
29313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
29323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
29333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2934d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
2935e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Comment cmnt(masm_, "[ CountOperation");
293680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
2937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand-sides are rewritten to have a 'throw
2939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ReferenceError' as the left-hand side.
2940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->expression()->IsValidLeftHandSide()) {
2941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->expression());
2942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
2943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Expression can only be a property, a global or a (parameter or local)
2946e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
2947e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
2948e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LhsKind assign_type = VARIABLE;
2949e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
2950e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In case of a property we use the uninitialized expression context
2951e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // of the key to detect a named property.
2952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (prop != NULL) {
2953e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    assign_type =
2954e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
2955e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2956e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
2958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
2959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
29600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
29610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitVariableLoad(expr->expression()->AsVariableProxy()->var());
2962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
2963e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
29640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (expr->is_postfix() && !context()->IsEffect()) {
2965e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Push(Smi::FromInt(0));
2966e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2967e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (assign_type == NAMED_PROPERTY) {
29680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
29697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(rax);  // Copy of receiver, needed for later store.
2970e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitNamedPropertyLoad(prop);
2971e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
29720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(prop->obj());
29730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->key());
29747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ movq(rdx, Operand(rsp, 0));  // Leave receiver on stack
29757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(rax);  // Copy of key, needed for later store.
2976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitKeyedPropertyLoad(prop);
2977e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2978e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2979e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2980d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Call ToNumber only if operand is not a smi.
29810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel no_conversion;
2982d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Condition is_smi;
2983d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  is_smi = masm_->CheckSmi(rax);
2984d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ j(is_smi, &no_conversion);
2985d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ push(rax);
2986e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
2987d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&no_conversion);
2988e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2989e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
2990e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
29910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (!context()->IsEffect()) {
29920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Save the result on the stack. If we have a named or keyed property
29930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // we store the result under the receiver that is currently on top
29940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // of the stack.
29950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
29960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
29970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ push(rax);
29980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
29990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
30000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ movq(Operand(rsp, kPointerSize), rax);
30010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
30020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
30030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ movq(Operand(rsp, 2 * kPointerSize), rax);
30040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
30050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
3006e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3007e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3008e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3009d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Inline smi case if we are in a loop.
3010d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label stub_call, done;
301180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (ShouldInlineSmiCase(expr->op())) {
3012d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
3013d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiAddConstant(rax, rax, Smi::FromInt(1));
3014d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
3015d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiSubConstant(rax, rax, Smi::FromInt(1));
3016d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3017d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ j(overflow, &stub_call);
3018d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // We could eliminate this smi check if we split the code at
3019d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // the first smi check before calling ToNumber.
3020d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    is_smi = masm_->CheckSmi(rax);
3021d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ j(is_smi, &done);
3022d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ bind(&stub_call);
3023d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Call stub. Undo operation first.
3024d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
3025d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiSubConstant(rax, rax, Smi::FromInt(1));
3026d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
3027d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiAddConstant(rax, rax, Smi::FromInt(1));
3028d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3029d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
3030e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call stub for +1/-1.
3031e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  GenericBinaryOpStub stub(expr->binary_op(),
3032e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_OVERWRITE,
3033e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NO_GENERIC_BINARY_FLAGS);
30344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  stub.GenerateCall(masm_, rax, Smi::FromInt(1));
3035d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
3036e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3037e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in rax.
3038e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
3039e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case VARIABLE:
3040e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
3041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
30420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        { EffectContext context(this);
30430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
30440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                 Token::ASSIGN);
30450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        }
3046e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // For all contexts except kEffect: We have the result on
3047e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
30480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
30490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3050e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3051e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
3052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
3053e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
30540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                               Token::ASSIGN);
3055e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3056e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
3057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
3058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Move(rcx, prop->key()->AsLiteral()->handle());
30594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ pop(rdx);
3060e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
30610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
3062e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
30630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
30640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3065e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3066e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
30670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(rax);
3068e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3069e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
3070e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
3072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(rcx);
3073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(rdx);
3074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
30750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
3076e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
30770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
30780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3079e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3080e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
30810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(rax);
3082e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3083e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
3084e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3085e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3086e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3087e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
30890d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
309080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  VariableProxy* proxy = expr->AsVariableProxy();
30910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!context()->IsEffect());
30920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!context()->IsTest());
30930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
309480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
309580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Comment cmnt(masm_, "Global variable");
309680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ Move(rcx, proxy->name());
309780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movq(rax, CodeGenerator::GlobalObject());
309880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
309980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Use a regular load, not a contextual load, to avoid a reference
310080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // error.
31010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET);
31020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
310380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (proxy != NULL &&
31040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen             proxy->var()->AsSlot() != NULL &&
31050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen             proxy->var()->AsSlot()->type() == Slot::LOOKUP) {
310659151504615d929945dc59db37bf1166937748c6Steve Block    Label done, slow;
310759151504615d929945dc59db37bf1166937748c6Steve Block
310859151504615d929945dc59db37bf1166937748c6Steve Block    // Generate code for loading from variables potentially shadowed
310959151504615d929945dc59db37bf1166937748c6Steve Block    // by eval-introduced variables.
31100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* slot = proxy->var()->AsSlot();
311159151504615d929945dc59db37bf1166937748c6Steve Block    EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
311259151504615d929945dc59db37bf1166937748c6Steve Block
311359151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
311480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(rsi);
311580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ Push(proxy->name());
311680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
311759151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&done);
311859151504615d929945dc59db37bf1166937748c6Steve Block
31190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
3120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
312180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // This expression cannot throw a reference error at the top level.
31220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Visit(expr);
312380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
312480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
312580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
312680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
312780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenbool FullCodeGenerator::TryLiteralCompare(Token::Value op,
312880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Expression* left,
312980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Expression* right,
313080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Label* if_true,
313180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Label* if_false,
313280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Label* fall_through) {
313380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (op != Token::EQ && op != Token::EQ_STRICT) return false;
313480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
313580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check for the pattern: typeof <expression> == <string literal>.
313680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Literal* right_literal = right->AsLiteral();
313780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (right_literal == NULL) return false;
313880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Handle<Object> right_literal_value = right_literal->handle();
313980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (!right_literal_value->IsString()) return false;
314080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  UnaryOperation* left_unary = left->AsUnaryOperation();
314180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
314280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Handle<String> check = Handle<String>::cast(right_literal_value);
314380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
31440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  { AccumulatorValueContext context(this);
31450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForTypeofValue(left_unary->expression());
31460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
31470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
314880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (check->Equals(Heap::number_symbol())) {
314980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Condition is_smi = masm_->CheckSmi(rax);
315080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(is_smi, if_true);
315180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
315280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
315380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
315480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::string_symbol())) {
315580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Condition is_smi = masm_->CheckSmi(rax);
315680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(is_smi, if_false);
315780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
315880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
315980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
316080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen             Immediate(1 << Map::kIsUndetectable));
316180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(not_zero, if_false);
316280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CmpInstanceType(rdx, FIRST_NONSTRING_TYPE);
316380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(below, if_true, if_false, fall_through);
316480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::boolean_symbol())) {
316580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
3166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
316780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kFalseValueRootIndex);
316880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
316980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::undefined_symbol())) {
317080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
3171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
317280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Condition is_smi = masm_->CheckSmi(rax);
317380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(is_smi, if_false);
317480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => true.
317580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
317680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
317780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen             Immediate(1 << Map::kIsUndetectable));
317880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(not_zero, if_true, if_false, fall_through);
317980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::function_symbol())) {
318080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Condition is_smi = masm_->CheckSmi(rax);
318180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(is_smi, if_false);
318280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx);
318380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_true);
318480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Regular expressions => 'function' (they are callable).
318580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CmpInstanceType(rdx, JS_REGEXP_TYPE);
318680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
318780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::object_symbol())) {
318880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Condition is_smi = masm_->CheckSmi(rax);
318980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(is_smi, if_false);
319080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kNullValueRootIndex);
319180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_true);
319280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Regular expressions => 'function', not 'object'.
319380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CmpObjectType(rax, JS_REGEXP_TYPE, rdx);
319480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_false);
319580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
319680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
3197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke             Immediate(1 << Map::kIsUndetectable));
319880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(not_zero, if_false);
319980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for JS objects => true.
320080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CmpInstanceType(rdx, FIRST_JS_OBJECT_TYPE);
320180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(below, if_false);
320280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CmpInstanceType(rdx, LAST_JS_OBJECT_TYPE);
320380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(below_equal, if_true, if_false, fall_through);
320480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
320580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (if_false != fall_through) __ jmp(if_false);
3206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
320780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
320880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return true;
3209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3212d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
3213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
321480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
3215e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3216e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
3217e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
3218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
322180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
32220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
32230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
322480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
322580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // First we try a fast inlined version of the compare when one of
322680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the operands is a literal.
322780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Token::Value op = expr->op();
322880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Expression* left = expr->left();
322980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Expression* right = expr->right();
323080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) {
32310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(if_true, if_false);
323280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return;
323380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
3234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
32350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->left());
323680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
3237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
32380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
3239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
3240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CompareRoot(rax, Heap::kTrueValueRootIndex);
324180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(equal, if_true, if_false, fall_through);
3242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
32433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
32450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
3246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      InstanceofStub stub;
3247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
3248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ testq(rax, rax);
324980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen       // The stub returns 0 for true.
325080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(zero, if_true, if_false, fall_through);
3251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
32550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->right());
3256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Condition cc = no_condition;
3257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      bool strict = false;
325880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      switch (op) {
3259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::EQ_STRICT:
3260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          strict = true;
3261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          // Fall through.
326280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        case Token::EQ:
3263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = equal;
3264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rdx);
3265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LT:
3267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
3268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rdx);
3269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GT:
3271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Reverse left and right sizes to obtain ECMA-262 conversion order.
3272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
3273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(rdx, result_register());
3274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rax);
3275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block         break;
3276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LTE:
3277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Reverse left and right sizes to obtain ECMA-262 conversion order.
3278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
3279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ movq(rdx, result_register());
3280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rax);
3281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GTE:
3283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
3284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(rdx);
3285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
3286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::IN:
3287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::INSTANCEOF:
3288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default:
3289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
3290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
3291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
32920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      bool inline_smi_code = ShouldInlineSmiCase(op);
32930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (inline_smi_code) {
329480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Label slow_case;
329580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ JumpIfNotBothSmi(rax, rdx, &slow_case);
329680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ SmiCompare(rdx, rax);
329780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Split(cc, if_true, if_false, NULL);
329880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&slow_case);
329980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
3300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
33010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      CompareFlags flags = inline_smi_code
33020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          ? NO_SMI_COMPARE_IN_STUB
33030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          : NO_COMPARE_FLAGS;
33040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      CompareStub stub(cc, strict, flags);
3305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
3306d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ testq(rax, rax);
330780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(cc, if_true, if_false, fall_through);
3308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
33093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
33103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
3312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
33130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
331780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) {
331880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Comment cmnt(masm_, "[ CompareToNull");
331980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
332080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
332180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
332280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
33230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
33240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
332580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
33260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(expr->expression());
332780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ CompareRoot(rax, Heap::kNullValueRootIndex);
332880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (expr->is_strict()) {
332980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
333080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
333180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_true);
333280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
333380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_true);
333480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Condition is_smi = masm_->CheckSmi(rax);
333580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(is_smi, if_false);
333680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // It can be an undetectable object.
333780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
333880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
333980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen             Immediate(1 << Map::kIsUndetectable));
334080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(not_zero, if_true, if_false, fall_through);
334180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
33420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
334380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
334480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
334580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3346d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
3347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
33480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3351d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
33520d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() {
33530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return rax;
33540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
3355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
33570d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() {
33580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return rsi;
33590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
33600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
33610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
33620d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) {
33630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(mode == RelocInfo::CODE_TARGET ||
33640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen         mode == RelocInfo::CODE_TARGET_CONTEXT);
33650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ call(ic, mode);
33660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
33670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // If we're calling a (keyed) load or store stub, we have to mark
33680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // the call as containing no inlined code so we will not attempt to
33690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // patch it.
33700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  switch (ic->kind()) {
33710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    case Code::LOAD_IC:
33720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    case Code::KEYED_LOAD_IC:
33730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    case Code::STORE_IC:
33740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    case Code::KEYED_STORE_IC:
33750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ nop();  // Signals no inlined code.
33760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      break;
33770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    default:
33780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Do nothing.
33790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      break;
33800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
33810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
3382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3384d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
3385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(IsAligned(frame_offset, kPointerSize));
3386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(Operand(rbp, frame_offset), value);
33873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
33883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
33893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3390d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
339159151504615d929945dc59db37bf1166937748c6Steve Block  __ movq(dst, ContextOperand(rsi, context_index));
3392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ----------------------------------------------------------------------------
3396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support.
3397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3399d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() {
3400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rdx));
3401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rcx));
3402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Cook return address on top of stack (smi encoded Code* delta)
3403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(rdx, Operand(rsp, 0));
3404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, masm_->CodeObject());
3405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ subq(rdx, rcx);
3406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Integer32ToSmi(rdx, rdx);
3407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(Operand(rsp, 0), rdx);
3408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store result register while executing finally block.
3409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
3410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3413d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() {
3414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rdx));
3415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rcx));
3416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Restore result register from stack.
3417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(result_register());
3418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Uncook return address.
3419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(rdx, Operand(rsp, 0));
3420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ SmiToInteger32(rdx, rdx);
3421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, masm_->CodeObject());
3422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ addq(rdx, rcx);
3423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(Operand(rsp, 0), rdx);
3424e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // And return.
3425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ret(0);
3426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef __
3430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
34323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} }  // namespace v8::internal
3433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
3435