13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 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"
338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.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"
398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#include "stub-cache.h"
403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 {
423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal {
433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_)
453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass JumpPatchSite BASE_EMBEDDED {
481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
49589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    info_emitted_ = false;
521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ~JumpPatchSite() {
561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(patch_site_.is_bound() == info_emitted_);
571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
59257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitJumpIfNotSmi(Register reg,
60257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        Label* target,
61257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        Label::Distance near_jump = Label::kFar) {
621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ testb(reg, Immediate(kSmiTagMask));
63257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EmitJump(not_carry, target, near_jump);   // Always taken before patched.
641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
66257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitJumpIfSmi(Register reg,
67257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     Label* target,
68257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     Label::Distance near_jump = Label::kFar) {
691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ testb(reg, Immediate(kSmiTagMask));
70257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EmitJump(carry, target, near_jump);  // Never taken before patched.
711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EmitPatchInfo() {
743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (patch_site_.is_bound()) {
753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(is_int8(delta_to_patch_site));
773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ testl(rax, Immediate(delta_to_patch_site));
781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      info_emitted_ = true;
801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ nop();  // Signals no inlined code.
833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // jc will be patched with jz, jnc will become jnz.
88257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitJump(Condition cc, Label* target, Label::Distance near_jump) {
891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(!patch_site_.is_bound() && !info_emitted_);
901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(cc == carry || cc == not_carry);
911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&patch_site_);
92257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(cc, target, near_jump);
931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  MacroAssembler* masm_;
961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Label patch_site_;
971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool info_emitted_;
991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
1001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
1011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint FullCodeGenerator::self_optimization_header_size() {
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return 20;
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function.  On entry to the function the receiver
1093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, with the
1103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them.  The actual argument count matches the
1113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function.
1123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
1133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are:
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   o rdi: the JS function object being called (i.e. ourselves)
1153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rsi: our context
1163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rbp: our caller's frame pointer
1173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rsp: stack pointer (pointing to return address)
1183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
1193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame.  Please see JavaScriptFrameConstants in
1203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-x64.h for its layout.
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::Generate() {
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompilationInfo* info = info_;
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  handler_table_ =
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
1253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  SetFunctionPosition(function());
1266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comment cmnt(masm_, "[ function compiled by full code generator");
1273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We can optionally optimize based on counters rather than statistical
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // sampling.
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (info->ShouldSelfOptimize()) {
1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_trace_opt_verbose) {
1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrintF("[adding self-optimization header to %s]\n",
1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             *info->function()->debug_name()->ToCString());
1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    has_self_optimization_header_ = true;
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MaybeObject* maybe_cell = isolate()->heap()->AllocateJSGlobalPropertyCell(
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Smi::FromInt(Compiler::kCallsUntilPrimitiveOpt));
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JSGlobalPropertyCell* cell;
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (maybe_cell->To(&cell)) {
1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rax, Handle<JSGlobalPropertyCell>(cell),
1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              RelocInfo::EMBEDDED_OBJECT);
1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ SmiAddConstant(FieldOperand(rax, JSGlobalPropertyCell::kValueOffset),
1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Smi::FromInt(-1));
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> compile_stub(
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          isolate()->builtins()->builtin(Builtins::kLazyRecompile));
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(zero, compile_stub, RelocInfo::CODE_TARGET);
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(masm_->pc_offset() == self_optimization_header_size());
1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
151f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG
152f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (strlen(FLAG_stop_at) > 0 &&
153f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
154f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ int3();
155f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
156f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif
157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Strict mode functions and builtins need to replace the receiver
1593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // with undefined when called as functions (without an explicit
1603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // receiver object). rcx is zero for method calls and non-zero for
1613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // function calls.
1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!info->is_classic_mode() || info->is_native()) {
163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label ok;
164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ testq(rcx, rcx);
165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(zero, &ok, Label::kNear);
166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // +1 for return address.
1673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize;
168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ movq(Operand(rsp, receiver_offset), kScratchRegister);
170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&ok);
171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Open a frame scope to indicate that there is a frame on the stack.  The
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // MANUAL indicates that the scope shouldn't actually generate code to set up
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the frame (that is done below).
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameScope frame_scope(masm_, StackFrame::MANUAL);
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
178756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(rbp);  // Caller's frame pointer.
179756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ movq(rbp, rsp);
180756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(rsi);  // Callee's context.
181756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(rdi);  // Callee's JS Function.
182756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
183756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  { Comment cmnt(masm_, "[ Allocate locals");
1843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int locals_count = info->scope()->num_stack_slots();
185756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (locals_count == 1) {
186756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ PushRoot(Heap::kUndefinedValueRootIndex);
187756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else if (locals_count > 1) {
188756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
189756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      for (int i = 0; i < locals_count; i++) {
190756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ push(rdx);
191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
193756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
195756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  bool function_in_register = true;
1964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
197756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate a local context.
1983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
199756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (heap_slots > 0) {
200756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate local context");
201756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Argument to NewContext is the function, which is still in rdi.
202756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ push(rdi);
203756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
204756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      FastNewContextStub stub(heap_slots);
205756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ CallStub(&stub);
206756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
2073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ CallRuntime(Runtime::kNewFunctionContext, 1);
208756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
209756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    function_in_register = false;
210756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Context is returned in both rax and rsi.  It replaces the context
211756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // passed to us.  It's saved in the stack and kept live in rsi.
212756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
213756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
214756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Copy any necessary parameters into the context.
2153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int num_parameters = info->scope()->num_parameters();
216756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (int i = 0; i < num_parameters; i++) {
217589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Variable* var = scope()->parameter(i);
218589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (var->IsContextSlot()) {
219756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
220756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick            (num_parameters - 1 - i) * kPointerSize;
221756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Load parameter from stack.
222756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ movq(rax, Operand(rbp, parameter_offset));
223756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Store it in the context.
224589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        int context_offset = Context::SlotOffset(var->index());
225756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ movq(Operand(rsi, context_offset), rax);
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Update the write barrier.  This clobbers rax and rbx.
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ RecordWriteContextSlot(
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            rsi, context_offset, rax, rbx, kDontSaveFPRegs);
229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
231756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
2323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
233756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate an arguments object.
2340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Variable* arguments = scope()->arguments();
235756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (arguments != NULL) {
236756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Arguments object must be allocated after the context object, in
237756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // case the "arguments" or ".arguments" variables are in the context.
238756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate arguments object");
239756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (function_in_register) {
240756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ push(rdi);
241756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
242756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
244756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The receiver is just before the parameters on the caller's stack.
2453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int num_parameters = info->scope()->num_parameters();
2463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int offset = num_parameters * kPointerSize;
247756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ lea(rdx,
248756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
249756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ push(rdx);
2503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ Push(Smi::FromInt(num_parameters));
251756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Arguments to ArgumentsAccessStub:
252756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    //   function, receiver address, parameter count.
253756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The stub will rewrite receiver and parameter count if the previous
254756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // stack frame was an arguments adapter frame.
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ArgumentsAccessStub::Type type;
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!is_classic_mode()) {
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      type = ArgumentsAccessStub::NEW_STRICT;
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (function()->has_duplicate_parameters()) {
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      type = ArgumentsAccessStub::NEW_NON_STRICT_FAST;
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ArgumentsAccessStub stub(type);
264756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
26544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
266589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SetVar(arguments, rax, rbx, rdx);
267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace) {
270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ CallRuntime(Runtime::kTraceEnter, 0);
271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Visit the declarations and body unless there is an illegal
274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // redeclaration.
275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (scope()->HasIllegalRedeclaration()) {
276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Comment cmnt(masm_, "[ Declarations");
277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    scope()->VisitIllegalRedeclaration(this);
278589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
280589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    { Comment cmnt(masm_, "[ Declarations");
282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // For named function expressions, declare the function name as a
283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // constant.
284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (scope()->is_function_scope() && scope()->function() != NULL) {
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VariableProxy* proxy = scope()->function();
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(proxy->var()->mode() == CONST ||
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               proxy->var()->mode() == CONST_HARMONY);
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(proxy->var()->location() != Variable::UNALLOCATED);
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        EmitDeclaration(proxy, proxy->var()->mode(), NULL);
290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      VisitDeclarations(scope()->declarations());
292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    { Comment cmnt(masm_, "[ Stack check");
295589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS);
296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label ok;
297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ j(above_equal, &ok, Label::kNear);
299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      StackCheckStub stub;
300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ CallStub(&stub);
301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ bind(&ok);
302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    { Comment cmnt(masm_, "[ Body");
305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(loop_depth() == 0);
306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      VisitStatements(function()->body());
307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(loop_depth() == 0);
308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
3093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
3103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Always emit a 'return undefined' in case control fell off the end of
312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the body.
3133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
3143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
3157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    EmitReturnSequence();
316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
320db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdochvoid FullCodeGenerator::ClearAccumulator() {
3219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ Set(rax, 0);
322db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch}
323db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
324db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStackCheck(IterationStatement* stmt,
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Label* back_edge_target) {
327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Comment cmnt(masm_, "[ Stack check");
328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label ok;
329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &ok, Label::kNear);
331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StackCheckStub stub;
332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CallStub(&stub);
333086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Record a mapping of this PC offset to the OSR id.  This is used to find
334086aeeaae12517475c22695a200be45495516549Ben Murdoch  // the AST id from the unoptimized code in order to use it as a key into
335086aeeaae12517475c22695a200be45495516549Ben Murdoch  // the deoptimization input data found in the optimized code.
336086aeeaae12517475c22695a200be45495516549Ben Murdoch  RecordStackCheck(stmt->OsrEntryId());
337086aeeaae12517475c22695a200be45495516549Ben Murdoch
338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Loop stack checks can be patched to perform on-stack replacement. In
339e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // order to decide whether or not to perform OSR we embed the loop depth
340e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // in a test instruction after the call so we can extract it from the OSR
341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // builtin.
342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(loop_depth() > 0);
343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ testl(rax, Immediate(Min(loop_depth(), Code::kMaxLoopNestingMarker)));
344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&ok);
346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
347086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Record a mapping of the OSR id to this PC.  This is used if the OSR
348086aeeaae12517475c22695a200be45495516549Ben Murdoch  // entry becomes the target of a bailout.  We don't expect it to be, but
349086aeeaae12517475c22695a200be45495516549Ben Murdoch  // we want it to work if it is.
350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() {
355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ jmp(&return_label_);
358d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
3603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
3613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(rax);
3623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ CallRuntime(Runtime::kTraceExit, 1);
3633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG
365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Add a label for checking the size of the code used for returning.
366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Label check_exit_codesize;
367d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    masm_->bind(&check_exit_codesize);
368d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
369bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
3703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ RecordJSReturn();
3713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Do not use the leave instruction here because it is too short to
3723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // patch with the code required by the debugger.
3733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(rsp, rbp);
3743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ pop(rbp);
3751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize;
3771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Ret(arguments_bytes, rcx);
3781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT
3803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Add padding that will be overwritten by a debugger breakpoint.  We
3811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // have just generated at least 7 bytes: "movq rsp, rbp; pop rbp; ret k"
3823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // (3 + 1 + 3).
383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    const int kPadding = Assembler::kJSReturnSequenceLength - 7;
3843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    for (int i = 0; i < kPadding; ++i) {
3853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      masm_->int3();
3863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
3871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check that the size of the code used for returning is large enough
3881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // for the debugger's requirements.
3891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(Assembler::kJSReturnSequenceLength <=
3901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
3913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#endif
3923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
3933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
3943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
396589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EffectContext::Plug(Variable* var) const {
397589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
3980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
401589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
402589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
403589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  codegen()->GetVar(result_register(), var);
4040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
407589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
408589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
409589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand operand = codegen()->VarOperand(var, result_register());
410589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ push(operand);
411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
412d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
414589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::TestContext::Plug(Variable* var) const {
415589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  codegen()->GetVar(result_register(), var);
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
4173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  codegen()->DoTest(this);
4180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4210d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4250d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
4260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
4270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), index);
4280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4310d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
4320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
4330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ PushRoot(index);
4340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4370d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
4420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (index == Heap::kUndefinedValueRootIndex ||
4430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kNullValueRootIndex ||
4440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kFalseValueRootIndex) {
445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (false_label_ != fall_through_) __ jmp(false_label_);
4460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (index == Heap::kTrueValueRootIndex) {
447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (true_label_ != fall_through_) __ jmp(true_label_);
4480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
4490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ LoadRoot(result_register(), index);
4503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    codegen()->DoTest(this);
451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4550d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
4560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4590d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
4600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Handle<Object> lit) const {
4610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), lit);
4620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4650d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
4660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Push(lit);
4670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4700d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
4750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!lit->IsUndetectableObject());  // There are no undetectable literals.
4760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (false_label_ != fall_through_) __ jmp(false_label_);
4780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsTrue() || lit->IsJSObject()) {
479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (true_label_ != fall_through_) __ jmp(true_label_);
4800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsString()) {
4810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (String::cast(*lit)->length() == 0) {
482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (false_label_ != fall_through_) __ jmp(false_label_);
4830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ jmp(true_label_);
4850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
4860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsSmi()) {
4870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (Smi::cast(*lit)->value() == 0) {
488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (false_label_ != fall_through_) __ jmp(false_label_);
4890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ jmp(true_label_);
4910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
4920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
4930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // For simplicity we always test the accumulator register.
4940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ Move(result_register(), lit);
4953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    codegen()->DoTest(this);
496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5000d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count,
5010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                   Register reg) const {
502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(count > 0);
5030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5070d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
5080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    int count,
5090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Register reg) const {
5100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
5110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
5120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
5130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5160d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count,
5170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                       Register reg) const {
5180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
5190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (count > 1) __ Drop(count - 1);
5200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ movq(Operand(rsp, 0), reg);
521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5240d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count,
5250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                 Register reg) const {
5260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
5270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
5280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
5290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
5313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  codegen()->DoTest(this);
5320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5350d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
5360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            Label* materialize_false) const {
537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(materialize_true == materialize_false);
5380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
5390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5420d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
5430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
5440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
5460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
54744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(result_register(), isolate()->factory()->true_value());
548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&done, Label::kNear);
5490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
55044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(result_register(), isolate()->factory()->false_value());
5510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5550d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
5560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
5570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
5590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
56044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Push(isolate()->factory()->true_value());
561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&done, Label::kNear);
5620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
56344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Push(isolate()->factory()->false_value());
5640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
5650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5680d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true,
5690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                          Label* materialize_false) const {
5700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(materialize_true == true_label_);
571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(materialize_false == false_label_);
5720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5750d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const {
5760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5790d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
5800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
5810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
5820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), value_root_index);
5830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5860d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const {
5870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
5880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
5890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ PushRoot(value_root_index);
5900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5930d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const {
5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
595086aeeaae12517475c22695a200be45495516549Ben Murdoch                                          true,
596086aeeaae12517475c22695a200be45495516549Ben Murdoch                                          true_label_,
597086aeeaae12517475c22695a200be45495516549Ben Murdoch                                          false_label_);
5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (flag) {
5990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (true_label_ != fall_through_) __ jmp(true_label_);
6000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
6010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (false_label_ != fall_through_) __ jmp(false_label_);
602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
6063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::DoTest(Expression* condition,
6073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               Label* if_true,
60880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* if_false,
60980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* fall_through) {
6103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ToBooleanStub stub(result_register());
611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
6133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ testq(result_register(), result_register());
61480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The stub returns nonzero for true.
61580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(not_zero, if_true, if_false, fall_through);
61680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
61980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::Split(Condition cc,
62080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_true,
62180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_false,
62280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* fall_through) {
62380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (if_false == fall_through) {
62480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(cc, if_true);
62580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (if_true == fall_through) {
62680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(NegateCondition(cc), if_false);
62780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
62880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(cc, if_true);
62980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ jmp(if_false);
630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
634589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) {
635589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsStackAllocated());
636589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Offset is negative because higher indexes are at lower addresses.
637589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int offset = -var->index() * kPointerSize;
638589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Adjust by a (parameter or local) base offset.
639589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsParameter()) {
640589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
641589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else {
642589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    offset += JavaScriptFrameConstants::kLocal0Offset;
643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
644589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return Operand(rbp, offset);
645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
647d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
648589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
649589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
650589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsContextSlot()) {
651589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    int context_chain_length = scope()->ContextChainLength(var->scope());
652589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ LoadContext(scratch, context_chain_length);
653589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return ContextOperand(scratch, var->index());
654589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else {
655589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return StackOperand(var);
656589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
660589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) {
661589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
662589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand location = VarOperand(var, dest);
663589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ movq(dest, location);
664589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
665589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
666589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
667589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::SetVar(Variable* var,
668589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register src,
669589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register scratch0,
670589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register scratch1) {
671589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
672589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(!scratch0.is(src));
673589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(!scratch0.is(scratch1));
674589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(!scratch1.is(src));
675589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand location = VarOperand(var, scratch0);
676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(location, src);
6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
679589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsContextSlot()) {
680589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    int offset = Context::SlotOffset(var->index());
6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     bool should_normalize,
688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_true,
689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_false) {
690086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Only prepare for bailouts before splits if we're in a test
691086aeeaae12517475c22695a200be45495516549Ben Murdoch  // context. Otherwise, we let the Visit function deal with the
692086aeeaae12517475c22695a200be45495516549Ben Murdoch  // preparation to avoid preparing with the same AST id twice.
693086aeeaae12517475c22695a200be45495516549Ben Murdoch  if (!context()->IsTest() || !info_->IsOptimizable()) return;
694086aeeaae12517475c22695a200be45495516549Ben Murdoch
695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label skip;
696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (should_normalize) __ jmp(&skip, Label::kNear);
6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailout(expr, TOS_REG);
698086aeeaae12517475c22695a200be45495516549Ben Murdoch  if (should_normalize) {
699086aeeaae12517475c22695a200be45495516549Ben Murdoch    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
700086aeeaae12517475c22695a200be45495516549Ben Murdoch    Split(equal, if_true, if_false, NULL);
701086aeeaae12517475c22695a200be45495516549Ben Murdoch    __ bind(&skip);
702086aeeaae12517475c22695a200be45495516549Ben Murdoch  }
703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
706589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        VariableMode mode,
7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        FunctionLiteral* function) {
709589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // If it was not possible to allocate the variable at compile time, we
710589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // need to "declare" it at runtime to make sure it actually exists in the
711589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // local context.
712589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Variable* variable = proxy->var();
7133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool binding_needs_init = (function == NULL) &&
7143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (mode == CONST || mode == CONST_HARMONY || mode == LET);
715589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (variable->location()) {
716589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::UNALLOCATED:
7173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ++global_count_;
718589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
719589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
720589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::PARAMETER:
721589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOCAL:
72269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (function != NULL) {
723589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Comment cmnt(masm_, "[ Declaration");
72469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        VisitForAccumulatorValue(function);
725589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ movq(StackOperand(variable), result_register());
7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (binding_needs_init) {
727589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Comment cmnt(masm_, "[ Declaration");
72869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
729589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ movq(StackOperand(variable), kScratchRegister);
730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
73169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
733589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::CONTEXT:
73469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // The variable in the decl always resides in the current function
73569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // context.
73669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
73769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (FLAG_debug_code) {
73869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // Check that we're not inside a with or catch context.
73969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ movq(rbx, FieldOperand(rsi, HeapObject::kMapOffset));
74069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ CompareRoot(rbx, Heap::kWithContextMapRootIndex);
74169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ Check(not_equal, "Declaration in with context.");
74269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
74369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ Check(not_equal, "Declaration in catch context.");
7441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
74569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (function != NULL) {
746589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Comment cmnt(masm_, "[ Declaration");
74769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        VisitForAccumulatorValue(function);
748589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ movq(ContextOperand(rsi, variable->index()), result_register());
749589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        int offset = Context::SlotOffset(variable->index());
7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We know that we have written a function, which is not a smi.
7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ RecordWriteContextSlot(rsi,
7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  offset,
7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  result_register(),
7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  rcx,
7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  kDontSaveFPRegs,
7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  EMIT_REMEMBERED_SET,
7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  OMIT_SMI_CHECK);
758589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (binding_needs_init) {
760589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Comment cmnt(masm_, "[ Declaration");
76169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
762589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ movq(ContextOperand(rsi, variable->index()), kScratchRegister);
76369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // No write barrier since the hole value is in old space.
764589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
76569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
76669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
768589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOOKUP: {
769589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Comment cmnt(masm_, "[ Declaration");
77069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ push(rsi);
77169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ Push(variable->name());
7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Declaration nodes are always introduced in one of four modes.
7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(mode == VAR ||
7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             mode == CONST ||
7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             mode == CONST_HARMONY ||
7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             mode == LET);
7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PropertyAttributes attr =
7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          (mode == CONST || mode == CONST_HARMONY) ? READ_ONLY : NONE;
77969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ Push(Smi::FromInt(attr));
78069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // Push initial value, if any.
78169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // Note: For variables we must not push an initial value (such as
78269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // 'undefined') because we may have a (legal) redeclaration and we
78369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // must not destroy the current value.
78469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (function != NULL) {
78569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        VisitForStackValue(function);
7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (binding_needs_init) {
78769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ PushRoot(Heap::kTheHoleValueRootIndex);
78869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      } else {
789589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ Push(Smi::FromInt(0));  // Indicates no initial value.
79069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
79169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ CallRuntime(Runtime::kDeclareContextSlot, 4);
79269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
798d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
7993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
8003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(rsi);  // The context is the first argument.
8013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(pairs);
802589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ Push(Smi::FromInt(DeclareGlobalsFlags()));
803589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ CallRuntime(Runtime::kDeclareGlobals, 3);
8043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
8053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ SwitchStatement");
810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Breakable nested_statement(this, stmt);
811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
812086aeeaae12517475c22695a200be45495516549Ben Murdoch
813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Keep the switch value on the stack until a case matches.
8140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(stmt->tag());
815086aeeaae12517475c22695a200be45495516549Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<CaseClause*>* clauses = stmt->cases();
818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label next_test;  // Recycled for each test.
821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the tests with branches to their bodies.
822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
8248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    clause->body_target()->Unuse();
8251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The default is not a test, but remember it as final fall through.
827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (clause->is_default()) {
828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      default_clause = clause;
829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      continue;
830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case comparison");
833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&next_test);
834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    next_test.Unuse();
835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Compile the label expression.
8370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(clause->label());
838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
83980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Perform the comparison as if via '==='.
8400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ movq(rdx, Operand(rsp, 0));  // Switch value.
8410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
8421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    JumpPatchSite patch_site(masm_);
8430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (inline_smi_code) {
844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label slow_case;
8451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movq(rcx, rdx);
8461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ or_(rcx, rax);
847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
8481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ cmpq(rdx, rax);
85080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(not_equal, &next_test);
85180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ Drop(1);  // Switch value is no longer needed.
8528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      __ jmp(clause->body_target());
85380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&slow_case);
85480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
8561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Record position before stub call for type feedback.
8571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    SetSourcePosition(clause->position());
8581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
8593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ call(ic, RelocInfo::CODE_TARGET, clause->CompareId());
8603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    patch_site.EmitPatchInfo();
8611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ testq(rax, rax);
863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(not_equal, &next_test);
864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
8658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ jmp(clause->body_target());
866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Discard the test value and jump to the default if present, otherwise to
869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the end of the statement.
870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&next_test);
871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(1);  // Switch value is no longer needed.
872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (default_clause == NULL) {
87369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ jmp(nested_statement.break_label());
874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
8758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ jmp(default_clause->body_target());
876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the case bodies.
879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case body");
881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
8828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ bind(clause->body_target());
88344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitStatements(clause->statements());
885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
88769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(nested_statement.break_label());
888086aeeaae12517475c22695a200be45495516549Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ ForInStatement");
894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label loop, exit;
897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ForIn loop_statement(this, stmt);
898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  increment_loop_depth();
899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the object to enumerate over. Both SpiderMonkey and JSC
901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ignore null and undefined in contrast to the specification; see
902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ECMA-262 section 12.6.4.
9030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(stmt->enumerable());
904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register null_value = rdi;
907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ LoadRoot(null_value, Heap::kNullValueRootIndex);
908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmpq(rax, null_value);
909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the object to a JS object.
914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label convert, done_convert;
915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, &convert);
9163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(above_equal, &done_convert);
918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&convert);
919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);
920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done_convert);
922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);
923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for proxies.
9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label call_runtime;
9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx);
9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(below_equal, &call_runtime);
9293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
930e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check cache validity in generated code. This is a fast case for
931e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
932e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // guarantee cache validity, call the runtime system to check cache
933e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // validity or get the property names in a fixed array.
9343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckEnumCache(null_value, &call_runtime);
935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
936e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // The enum cache is valid.  Load the map of the object being
937e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // iterated over and use the cache for the iteration.
938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label use_cache;
939e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&use_cache, Label::kNear);
941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the set of properties to enumerate.
943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&call_runtime);
944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);  // Duplicate the enumerable object on the stack.
945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If we got a map from the runtime call, we can do a fast
948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // modification check. Otherwise, we got a fixed array, and we have
949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // to do a slow check.
950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fixed_array;
951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 Heap::kMetaMapRootIndex);
953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &fixed_array, Label::kNear);
954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a map in register rax. Get the enumeration cache from it.
956e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&use_cache);
957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadInstanceDescriptors(rax, rcx);
958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset));
959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
9613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the four remaining stack slots.
962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);  // Map.
963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rdx);  // Enumeration cache.
964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset));
965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);  // Enumeration cache length (as smi).
966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(Smi::FromInt(0));  // Initial index.
967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a fixed array in register rax. Iterate through that.
9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label non_proxy;
971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&fixed_array);
9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSGlobalPropertyCell> cell =
9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->factory()->NewJSGlobalPropertyCell(
9753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Handle<Object>(
9763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker)));
9773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordTypeFeedbackCell(stmt->PrepareId(), cell);
9783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(rbx, cell);
9793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
9803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker));
9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(rbx, Smi::FromInt(1));  // Smi indicates slow check
9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rcx, Operand(rsp, 0 * kPointerSize));  // Get enumerated object
9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
9853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx);
9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(above, &non_proxy);
9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(rbx, Smi::FromInt(0));  // Zero indicates proxy
9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&non_proxy);
9893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(rbx);  // Smi
9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(rax);  // Array
991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset));
992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rax);  // Fixed array length (as smi).
993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(Smi::FromInt(0));  // Initial index.
994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for doing the condition check.
9963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&loop);
998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, Operand(rsp, 0 * kPointerSize));  // Get the current index.
999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(rax, Operand(rsp, 1 * kPointerSize));  // Compare to the array length.
100069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ j(above_equal, loop_statement.break_label());
1001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the current entry of the array into register rbx.
1003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, Operand(rsp, 2 * kPointerSize));
1004f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2);
1005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, FieldOperand(rbx,
1006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.reg,
1007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.scale,
1008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            FixedArray::kHeaderSize));
1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the expected map from the stack or a smi in the
1011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // permanent slow case into register rdx.
1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rdx, Operand(rsp, 3 * kPointerSize));
1013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the expected map still matches that of the enumerable.
10153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If not, we may have to filter the key.
1016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label update_each;
1017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rcx, Operand(rsp, 4 * kPointerSize));
1018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset));
1019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &update_each, Label::kNear);
1020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For proxies, no filtering is done.
10223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rdx, Smi::FromInt(0));
10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(equal, &update_each, Label::kNear);
10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the entry to a string or null if it isn't a property
1027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // anymore. If the property has been removed while iterating, we
1028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // just skip it.
1029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rcx);  // Enumerable.
1030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rbx);  // Current entry.
1031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
103244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Cmp(rax, Smi::FromInt(0));
103369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ j(equal, loop_statement.continue_label());
1034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, rax);
1035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the 'each' property or variable from the possibly filtered
1037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // entry in register rbx.
1038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&update_each);
1039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(result_register(), rbx);
1040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Perform the assignment as if via '='.
1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { EffectContext context(this);
10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAssignment(stmt->each());
1043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the body of the loop.
1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Visit(stmt->body());
1047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for going to the next element by incrementing the
1049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // index (smi) stored on top of the stack.
105069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.continue_label());
1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1));
1052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitStackCheck(stmt, &loop);
1054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ jmp(&loop);
1055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Remove the pointers stored on the stack.
105769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.break_label());
1058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ addq(rsp, Immediate(5 * kPointerSize));
1059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Exit and decrement the loop depth.
10613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
1063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  decrement_loop_depth();
1064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
10653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
10688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                       bool pretenure) {
1069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Use the fast case closure allocation code that allocates in new
1070e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // space for nested functions that don't need literals cloning. If
1071e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // we're running with the --always-opt or the --prepare-always-opt
1072e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // flag, we need to use the runtime function so that the new function
1073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // we are creating here gets a chance to have its code optimized and
1074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // doesn't just get a copy of the existing unoptimized code.
1075e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!FLAG_always_opt &&
1076e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      !FLAG_prepare_always_opt &&
107744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      !pretenure &&
1078e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      scope()->is_function_scope() &&
107944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      info->num_literals() == 0) {
10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastNewClosureStub stub(info->language_mode());
1081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Push(info);
1082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
1083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(rsi);
1085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Push(info);
108644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Push(pretenure
108744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            ? isolate()->factory()->true_value()
108844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            : isolate()->factory()->false_value());
10898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ CallRuntime(Runtime::kNewClosure, 3);
1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
10910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
10923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
10933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1095d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
10963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ VariableProxy");
10973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  EmitVariableLoad(expr);
1098e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1099e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1101589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
1102589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                      TypeofState typeof_state,
1103589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                      Label* slow) {
110459151504615d929945dc59db37bf1166937748c6Steve Block  Register context = rsi;
110559151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = rdx;
110659151504615d929945dc59db37bf1166937748c6Steve Block
110759151504615d929945dc59db37bf1166937748c6Steve Block  Scope* s = scope();
110859151504615d929945dc59db37bf1166937748c6Steve Block  while (s != NULL) {
110959151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (s->calls_non_strict_eval()) {
111159151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
111259151504615d929945dc59db37bf1166937748c6Steve Block        __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
111359151504615d929945dc59db37bf1166937748c6Steve Block                Immediate(0));
111459151504615d929945dc59db37bf1166937748c6Steve Block        __ j(not_equal, slow);
111559151504615d929945dc59db37bf1166937748c6Steve Block      }
111659151504615d929945dc59db37bf1166937748c6Steve Block      // Load next context in chain.
11173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
111859151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering rsi.
111959151504615d929945dc59db37bf1166937748c6Steve Block      context = temp;
112059151504615d929945dc59db37bf1166937748c6Steve Block    }
112159151504615d929945dc59db37bf1166937748c6Steve Block    // If no outer scope calls eval, we do not need to check more
112259151504615d929945dc59db37bf1166937748c6Steve Block    // context extensions.  If we have reached an eval scope, we check
112359151504615d929945dc59db37bf1166937748c6Steve Block    // all extensions from this point.
11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break;
112559151504615d929945dc59db37bf1166937748c6Steve Block    s = s->outer_scope();
112659151504615d929945dc59db37bf1166937748c6Steve Block  }
112759151504615d929945dc59db37bf1166937748c6Steve Block
112859151504615d929945dc59db37bf1166937748c6Steve Block  if (s != NULL && s->is_eval_scope()) {
112959151504615d929945dc59db37bf1166937748c6Steve Block    // Loop up the context chain.  There is no frame effect so it is
113059151504615d929945dc59db37bf1166937748c6Steve Block    // safe to use raw labels here.
1131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label next, fast;
113259151504615d929945dc59db37bf1166937748c6Steve Block    if (!context.is(temp)) {
113359151504615d929945dc59db37bf1166937748c6Steve Block      __ movq(temp, context);
113459151504615d929945dc59db37bf1166937748c6Steve Block    }
113559151504615d929945dc59db37bf1166937748c6Steve Block    // Load map for comparison into register, outside loop.
113659151504615d929945dc59db37bf1166937748c6Steve Block    __ LoadRoot(kScratchRegister, Heap::kGlobalContextMapRootIndex);
113759151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&next);
113859151504615d929945dc59db37bf1166937748c6Steve Block    // Terminate at global context.
113959151504615d929945dc59db37bf1166937748c6Steve Block    __ cmpq(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset));
1140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(equal, &fast, Label::kNear);
114159151504615d929945dc59db37bf1166937748c6Steve Block    // Check that extension is NULL.
114259151504615d929945dc59db37bf1166937748c6Steve Block    __ cmpq(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
114359151504615d929945dc59db37bf1166937748c6Steve Block    __ j(not_equal, slow);
114459151504615d929945dc59db37bf1166937748c6Steve Block    // Load next context in chain.
11453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ movq(temp, ContextOperand(temp, Context::PREVIOUS_INDEX));
114659151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(&next);
114759151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&fast);
114859151504615d929945dc59db37bf1166937748c6Steve Block  }
114959151504615d929945dc59db37bf1166937748c6Steve Block
115059151504615d929945dc59db37bf1166937748c6Steve Block  // All extension objects were empty and it is safe to use a global
115159151504615d929945dc59db37bf1166937748c6Steve Block  // load IC call.
11528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ movq(rax, GlobalObjectOperand());
1153589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ Move(rcx, var->name());
115444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
115559151504615d929945dc59db37bf1166937748c6Steve Block  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
115659151504615d929945dc59db37bf1166937748c6Steve Block      ? RelocInfo::CODE_TARGET
115759151504615d929945dc59db37bf1166937748c6Steve Block      : RelocInfo::CODE_TARGET_CONTEXT;
11583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ call(ic, mode);
115959151504615d929945dc59db37bf1166937748c6Steve Block}
116059151504615d929945dc59db37bf1166937748c6Steve Block
116159151504615d929945dc59db37bf1166937748c6Steve Block
1162589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1163589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                                Label* slow) {
1164589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsContextSlot());
116559151504615d929945dc59db37bf1166937748c6Steve Block  Register context = rsi;
116659151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = rbx;
116759151504615d929945dc59db37bf1166937748c6Steve Block
1168589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
116959151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (s->calls_non_strict_eval()) {
117159151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
117259151504615d929945dc59db37bf1166937748c6Steve Block        __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
117359151504615d929945dc59db37bf1166937748c6Steve Block                Immediate(0));
117459151504615d929945dc59db37bf1166937748c6Steve Block        __ j(not_equal, slow);
117559151504615d929945dc59db37bf1166937748c6Steve Block      }
11763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
117759151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering rsi.
117859151504615d929945dc59db37bf1166937748c6Steve Block      context = temp;
117959151504615d929945dc59db37bf1166937748c6Steve Block    }
118059151504615d929945dc59db37bf1166937748c6Steve Block  }
118159151504615d929945dc59db37bf1166937748c6Steve Block  // Check that last extension is NULL.
118259151504615d929945dc59db37bf1166937748c6Steve Block  __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
118359151504615d929945dc59db37bf1166937748c6Steve Block  __ j(not_equal, slow);
1184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // This function is used only for loads, not stores, so it's safe to
1186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // return an rsi-based operand (the write barrier cannot be allowed to
1187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // destroy the rsi register).
1188589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return ContextOperand(context, var->index());
118959151504615d929945dc59db37bf1166937748c6Steve Block}
119059151504615d929945dc59db37bf1166937748c6Steve Block
119159151504615d929945dc59db37bf1166937748c6Steve Block
1192589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
1193589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                  TypeofState typeof_state,
1194589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                  Label* slow,
1195589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                  Label* done) {
119659151504615d929945dc59db37bf1166937748c6Steve Block  // Generate fast-case code for variables that might be shadowed by
119759151504615d929945dc59db37bf1166937748c6Steve Block  // eval-introduced variables.  Eval is used a lot without
119859151504615d929945dc59db37bf1166937748c6Steve Block  // introducing variables.  In those cases, we do not want to
119959151504615d929945dc59db37bf1166937748c6Steve Block  // perform a runtime call for all variables in the scope
120059151504615d929945dc59db37bf1166937748c6Steve Block  // containing the eval.
12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (var->mode() == DYNAMIC_GLOBAL) {
1202589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
120359151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(done);
12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (var->mode() == DYNAMIC_LOCAL) {
1205589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Variable* local = var->local_if_not_shadowed();
1206589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ movq(rax, ContextSlotOperandCheckExtensions(local, slow));
12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (local->mode() == CONST ||
12083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        local->mode() == CONST_HARMONY ||
12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        local->mode() == LET) {
1210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1211589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ j(not_equal, done);
12123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (local->mode() == CONST) {
12133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {  // LET || CONST_HARMONY
12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Push(var->name());
12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CallRuntime(Runtime::kThrowReferenceError, 1);
12173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
121859151504615d929945dc59db37bf1166937748c6Steve Block    }
1219589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ jmp(done);
122059151504615d929945dc59db37bf1166937748c6Steve Block  }
122159151504615d929945dc59db37bf1166937748c6Steve Block}
122259151504615d929945dc59db37bf1166937748c6Steve Block
122359151504615d929945dc59db37bf1166937748c6Steve Block
12243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
12253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Record position before possible IC call.
12263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SetSourcePosition(proxy->position());
12273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Variable* var = proxy->var();
12283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1229589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Three cases: global variables, lookup variables, and all other types of
1230589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // variables.
1231589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (var->location()) {
1232589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::UNALLOCATED: {
1233589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Comment cmnt(masm_, "Global variable");
1234589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Use inline caching. Variable name is passed in rcx and the global
1235589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // object on the stack.
1236589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ Move(rcx, var->name());
1237589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ movq(rax, GlobalObjectOperand());
1238589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1239589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1240589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      context()->Plug(rax);
1241589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1242589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
124359151504615d929945dc59db37bf1166937748c6Steve Block
1244589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::PARAMETER:
1245589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOCAL:
1246589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::CONTEXT: {
1247589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot");
12483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (var->binding_needs_init()) {
12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // var->scope() may be NULL when the proxy is located in eval code and
12503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // refers to a potential outside binding. Currently those bindings are
12513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // always looked up dynamically, i.e. in that case
12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //     var->location() == LOOKUP.
12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // always holds.
12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(var->scope() != NULL);
12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Check if the binding really needs an initialization check. The check
12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // can be skipped in the following situation: we have a LET or CONST
12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // binding in harmony mode, both the Variable and the VariableProxy have
12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // the same declaration scope (i.e. they are both in global code, in the
12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // same function or in the same eval code) and the VariableProxy is in
12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // the source physically located after the initializer of the variable.
12623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
12633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We cannot skip any initialization checks for CONST in non-harmony
12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // mode because const variables may be declared but never initialized:
12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //   if (false) { const x; }; var y = x;
12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The condition on the declaration scopes is a conservative check for
12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // nested functions that access a binding and are called before the
12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // binding is initialized:
12703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //   function() { f(); let x = 1; function f() { x = 2; } }
12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bool skip_init_check;
12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          skip_init_check = false;
12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Check that we always have valid source position.
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ASSERT(proxy->position() != RelocInfo::kNoPosition);
12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          skip_init_check = var->mode() != CONST &&
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              var->initializer_position() < proxy->position();
12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!skip_init_check) {
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Let and const need a read barrier.
12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Label done;
12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          GetVar(rax, var);
12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ j(not_equal, &done, Label::kNear);
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (var->mode() == LET || var->mode() == CONST_HARMONY) {
12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // Throw a reference error when using an uninitialized let/const
12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // binding in harmony mode.
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ Push(var->name());
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ CallRuntime(Runtime::kThrowReferenceError, 1);
12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else {
12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // Uninitalized const bindings outside of harmony mode are unholed.
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ASSERT(var->mode() == CONST);
12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ bind(&done);
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          context()->Plug(rax);
13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          break;
1302589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        }
1303589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      context()->Plug(var);
1305589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1306589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
1307d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1308589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOOKUP: {
1309589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Label done, slow;
1310589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Generate code for loading from variables potentially shadowed
1311589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // by eval-introduced variables.
1312589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
1313589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ bind(&slow);
1314589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Comment cmnt(masm_, "Lookup slot");
1315589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(rsi);  // Context.
131669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ Push(var->name());
1317589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CallRuntime(Runtime::kLoadContextSlot, 2);
131869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ bind(&done);
131969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      context()->Plug(rax);
1320589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
13243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1326d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ RegExpLiteral");
1328bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label materialized;
13293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Registers will be used as follows:
13303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // rdi = JS function.
1331bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // rcx = literals array.
1332bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // rbx = regexp literal.
1333bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // rax = regexp literal clone.
13343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1335bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
13363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int literal_offset =
133780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1338bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(rbx, FieldOperand(rcx, literal_offset));
1339bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
1340589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ j(not_equal, &materialized, Label::kNear);
1341bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
13423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Create regexp literal using runtime function
13433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Result will be in rax.
1344bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(rcx);
13453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
13463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(expr->pattern());
13473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(expr->flags());
13483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1349bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(rbx, rax);
1350bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1351bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&materialized);
1352bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1353bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label allocated, runtime_allocate;
1354bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
1355bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ jmp(&allocated);
1356bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1357bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&runtime_allocate);
1358bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(rbx);
1359bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ Push(Smi::FromInt(size));
1360bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1361bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(rbx);
1362bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1363bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&allocated);
1364bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Copy the content into the newly allocated memory.
1365bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // (Unroll copy loop once for better throughput).
1366bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
1367bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(rdx, FieldOperand(rbx, i));
1368bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(rcx, FieldOperand(rbx, i + kPointerSize));
1369bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(FieldOperand(rax, i), rdx);
1370bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(FieldOperand(rax, i + kPointerSize), rcx);
1371bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1372bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if ((size % (2 * kPointerSize)) != 0) {
1373bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(rdx, FieldOperand(rbx, size - kPointerSize));
1374bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ movq(FieldOperand(rax, size - kPointerSize), rdx);
1375bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
13760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
1377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAccessor(Expression* expression) {
13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expression == NULL) {
13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ PushRoot(Heap::kNullValueRootIndex);
13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForStackValue(expression);
13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1389d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
13913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> constant_properties = expr->constant_properties();
1392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
1394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(constant_properties);
139644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int flags = expr->fast_elements()
139744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? ObjectLiteral::kFastElements
139844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : ObjectLiteral::kNoFlags;
139944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  flags |= expr->has_function()
140044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? ObjectLiteral::kHasFunction
140144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : ObjectLiteral::kNoFlags;
140244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Push(Smi::FromInt(flags));
14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int properties_count = constant_properties->length() / 2;
1404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->depth() > 1) {
14056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (flags != ObjectLiteral::kFastElements ||
14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
140885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastCloneShallowObjectStub stub(properties_count);
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
1412d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
1415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in rax.
1416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
1417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
14183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Mark all computed expressions that are bound to a key that
14193e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // is shadowed by a later occurrence of the same key. For the
14203e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // marked expressions, no store code is emitted.
14213e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  expr->CalculateEmitStore();
14223e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AccessorTable accessor_table(isolate()->zone());
1424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < expr->properties()->length(); i++) {
1425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectLiteral::Property* property = expr->properties()->at(i);
1426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
1427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = property->key();
1429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
1430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
1431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ push(rax);  // Save result on the stack
1432d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
1433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
1435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::CONSTANT:
1436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        UNREACHABLE();
1437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
1441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (key->handle()->IsSymbol()) {
14423e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          if (property->emit_store()) {
1443053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block            VisitForAccumulatorValue(value);
1444053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block            __ Move(rcx, key->handle());
1445053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block            __ movq(rdx, Operand(rsp, 0));
14463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<Code> ic = is_classic_mode()
14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                ? isolate()->builtins()->StoreIC_Initialize()
14483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                : isolate()->builtins()->StoreIC_Initialize_Strict();
14493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            __ call(ic, RelocInfo::CODE_TARGET, key->id());
1450086aeeaae12517475c22695a200be45495516549Ben Murdoch            PrepareForBailoutForId(key->id(), NO_REGISTERS);
1451053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block          } else {
1452053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block            VisitForEffect(value);
14533e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          }
1454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::PROTOTYPE:
1458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(rsp, 0));  // Duplicate receiver.
14590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(key);
14600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(value);
14613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        if (property->emit_store()) {
1462e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ Push(Smi::FromInt(NONE));    // PropertyAttributes
1463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ CallRuntime(Runtime::kSetProperty, 4);
14643e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        } else {
14653e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          __ Drop(3);
14663e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        }
1467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
146885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      case ObjectLiteral::Property::GETTER:
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        accessor_table.lookup(key)->second->getter = value;
14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case ObjectLiteral::Property::SETTER:
14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        accessor_table.lookup(key)->second->setter = value;
1473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1475d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Emit code to define accessors, using only a single call to the runtime for
14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // each pair of corresponding getters and setters.
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (AccessorTable::Iterator it = accessor_table.begin();
14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       it != accessor_table.end();
14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       ++it) {
14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(Operand(rsp, 0));  // Duplicate receiver.
14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForStackValue(it->first);
14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAccessor(it->second->getter);
14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAccessor(it->second->setter);
14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Push(Smi::FromInt(NONE));
14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
14883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
149044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (expr->has_function()) {
149144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(result_saved);
149244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ push(Operand(rsp, 0));
149344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
149444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
149544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
14970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
14990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
15003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
15013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
15023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1504d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
15053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
1506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<Expression*>* subexprs = expr->values();
1508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int length = subexprs->length();
15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> constant_elements = expr->constant_elements();
15103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(2, constant_elements->length());
15113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsKind constant_elements_kind =
15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
15133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_constant_fast_elements = constant_elements_kind == FAST_ELEMENTS;
15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArrayBase> constant_elements_values(
15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FixedArrayBase::cast(constant_elements->get(1)));
1516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
15173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
15193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(constant_elements);
15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Heap* heap = isolate()->heap();
15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (has_constant_fast_elements &&
15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      constant_elements_values->map() == heap->fixed_cow_array_map()) {
15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If the elements are already FAST_ELEMENTS, the boilerplate cannot
15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // change, so it's possible to specialize the stub in advance.
15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), 1);
1527756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    FastCloneShallowArrayStub stub(
15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS,
15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        length);
1530756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
1531756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (expr->depth() > 1) {
1532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
1533756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
1534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
1535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(constant_elements_kind == FAST_ELEMENTS ||
15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           constant_elements_kind == FAST_SMI_ONLY_ELEMENTS ||
15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FLAG_smi_only_arrays);
15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If the elements are already FAST_ELEMENTS, the boilerplate cannot
15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // change, so it's possible to specialize the stub in advance.
15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastCloneShallowArrayStub::Mode mode = has_constant_fast_elements
15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ? FastCloneShallowArrayStub::CLONE_ELEMENTS
15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS;
15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastCloneShallowArrayStub stub(mode, length);
1545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
15463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
15473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
15493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
15513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
1552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < length; i++) {
15533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Expression* subexpr = subexprs->at(i);
15543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
15553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
15563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (subexpr->AsLiteral() != NULL ||
15573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        CompileTimeValue::IsCompileTimeValue(subexpr)) {
15583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      continue;
15593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
15603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
15623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(rax);
15633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
15643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
15650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(subexpr);
15663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (constant_elements_kind == FAST_ELEMENTS) {
15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Fast-case array literal with ElementsKind of FAST_ELEMENTS, they cannot
15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // transition and don't need to call the runtime stub.
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int offset = FixedArray::kHeaderSize + (i * kPointerSize);
15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rbx, Operand(rsp, 0));  // Copy of array literal.
15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the subexpression value in the array's elements.
15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(FieldOperand(rbx, offset), result_register());
15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Update the write barrier for the array store.
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWriteField(rbx, offset, result_register(), rcx,
15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          kDontSaveFPRegs,
15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          EMIT_REMEMBERED_SET,
15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          INLINE_SMI_CHECK);
15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the subexpression value in the array's elements.
15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rbx, Operand(rsp, 0));  // Copy of array literal.
15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rdi, FieldOperand(rbx, JSObject::kMapOffset));
15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Move(rcx, Smi::FromInt(i));
15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Move(rdx, Smi::FromInt(expr->literal_index()));
15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StoreArrayLiteralElementStub stub;
15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CallStub(&stub);
15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1589086aeeaae12517475c22695a200be45495516549Ben Murdoch
1590086aeeaae12517475c22695a200be45495516549Ben Murdoch    PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
15913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
15923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
15940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
15960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
15973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
15983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
15993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1601402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Comment cmnt(masm_, "[ Assignment");
1603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // on the left-hand side.
1605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->target()->IsValidLeftHandSide()) {
1606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->target());
1607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1610402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Left-hand side can only be a property, a global or a (parameter or local)
16113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot.
1612402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1613402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LhsKind assign_type = VARIABLE;
161480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Property* property = expr->target()->AsProperty();
161580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (property != NULL) {
161680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    assign_type = (property->key()->IsPropertyName())
161780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? NAMED_PROPERTY
161880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : KEYED_PROPERTY;
1619402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1620402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1621402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate LHS expression.
1622402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1623402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1624402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Nothing to do here.
1625402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1626402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1627402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1628402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // We need the receiver both on the stack and in the accumulator.
16290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(property->obj());
1630402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1631402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
16320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
1633402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1634402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1635086aeeaae12517475c22695a200be45495516549Ben Murdoch    case KEYED_PROPERTY: {
1636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (expr->is_compound()) {
16373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->obj());
16383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForAccumulatorValue(property->key());
1639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ movq(rdx, Operand(rsp, 0));
1640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(rax);
1641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else {
16423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->obj());
16433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->key());
1644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
1645402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1646086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
1647402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1648402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
16498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // For compound assignments we need another deoptimization point after the
16508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // variable/property load.
1651402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
16520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    { AccumulatorValueContext context(this);
16530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
16540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
16553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          EmitVariableLoad(expr->target()->AsVariableProxy());
16568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          PrepareForBailout(expr->target(), TOS_REG);
16570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
16580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
16590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitNamedPropertyLoad(property);
16608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
16610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
16620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
16630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitKeyedPropertyLoad(property);
16648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
16650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
16660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
1667402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1668402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
166980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Token::Value op = expr->binary_op();
1670e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ push(rax);  // Left operand goes on the stack.
1671e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    VisitForAccumulatorValue(expr->value());
1672402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
167380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
167480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? OVERWRITE_RIGHT
167580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : NO_OVERWRITE;
167680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    SetSourcePosition(expr->position() + 1);
16770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
167880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (ShouldInlineSmiCase(op)) {
1679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitInlineSmiBinaryOp(expr->binary_operation(),
168080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            op,
168180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            mode,
168280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            expr->target(),
1683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                            expr->value());
168480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    } else {
1685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitBinaryOp(expr->binary_operation(), op, mode);
168680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
1687086aeeaae12517475c22695a200be45495516549Ben Murdoch    // Deoptimization point in case the binary operation may have side effects.
1688086aeeaae12517475c22695a200be45495516549Ben Murdoch    PrepareForBailout(expr->binary_operation(), TOS_REG);
168980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
16900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->value());
1691402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1692402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1693402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Record source position before possible IC call.
1694402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  SetSourcePosition(expr->position());
1695402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1696402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Store the value.
1697402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1698402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1699402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
17000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             expr->op());
1701086aeeaae12517475c22695a200be45495516549Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      context()->Plug(rax);
1703402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1704402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1705402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitNamedPropertyAssignment(expr);
1706402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1707402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1708402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitKeyedPropertyAssignment(expr);
1709402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1710402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1711402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1712402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1713402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1714d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1715e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Literal* key = prop->key()->AsLiteral();
1717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, key->handle());
171844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
17193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ call(ic, RelocInfo::CODE_TARGET, prop->id());
1720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1721e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1722e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1723d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
172544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
17263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ call(ic, RelocInfo::CODE_TARGET, prop->id());
1727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1729e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
173180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Token::Value op,
173280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              OverwriteMode mode,
173380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Expression* left,
1734e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              Expression* right) {
173580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Do combined smi check of the operands. Left operand is on the
173680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // stack (popped into rdx). Right operand is in rax but moved into
173780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rcx to make the shifts easier.
1738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done, stub_call, smi_case;
173980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ pop(rdx);
174080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movq(rcx, rax);
17411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ or_(rax, rdx);
17421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  JumpPatchSite patch_site(masm_);
1743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear);
174480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
174580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&stub_call);
17461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movq(rax, rcx);
1747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpStub stub(op, mode);
17483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
17493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
1750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&done, Label::kNear);
175180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
175280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&smi_case);
175380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
175480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SAR:
175580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiShiftArithmeticRight(rax, rdx, rcx);
175680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
175780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHL:
175880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiShiftLeft(rax, rdx, rcx);
175980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
176080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHR:
176180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiShiftLogicalRight(rax, rdx, rcx, &stub_call);
176280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
176380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::ADD:
176480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiAdd(rax, rdx, rcx, &stub_call);
176580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
176680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SUB:
176780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiSub(rax, rdx, rcx, &stub_call);
176880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
176980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::MUL:
177080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiMul(rax, rdx, rcx, &stub_call);
177180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
177280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_OR:
177380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiOr(rax, rdx, rcx);
177480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
177580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_AND:
177680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiAnd(rax, rdx, rcx);
177780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
177880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_XOR:
177980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiXor(rax, rdx, rcx);
178080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
178180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    default:
178280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      UNREACHABLE();
178380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
178480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
178580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
178680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&done);
17870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
178880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
178980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
179080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
1792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Token::Value op,
179380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                     OverwriteMode mode) {
17941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ pop(rdx);
1795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpStub stub(op, mode);
17963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
17973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
17983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
17990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
1800e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1801e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1802e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
18033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr) {
1804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw
1805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ReferenceError' on the left-hand side.
1806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->IsValidLeftHandSide()) {
1807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr);
1808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand side can only be a property, a global or a (parameter or local)
18123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot.
1813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  LhsKind assign_type = VARIABLE;
1815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = expr->AsProperty();
1816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (prop != NULL) {
1817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    assign_type = (prop->key()->IsPropertyName())
1818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ? NAMED_PROPERTY
1819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        : KEYED_PROPERTY;
1820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (assign_type) {
1823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case VARIABLE: {
1824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->AsVariableProxy()->var();
18250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EffectContext context(this);
18260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitVariableAssignment(var, Token::ASSIGN);
1827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case NAMED_PROPERTY: {
1830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(rax);  // Preserve value.
18310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
1832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ movq(rdx, rax);
1833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(rax);  // Restore value.
1834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ Move(rcx, prop->key()->AsLiteral()->handle());
18353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> ic = is_classic_mode()
18363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? isolate()->builtins()->StoreIC_Initialize()
18373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          : isolate()->builtins()->StoreIC_Initialize_Strict();
18383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ call(ic);
1839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case KEYED_PROPERTY: {
1842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(rax);  // Preserve value.
18433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForStackValue(prop->obj());
18443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForAccumulatorValue(prop->key());
18453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ movq(rcx, rax);
18463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ pop(rdx);
1847e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ pop(rax);  // Restore value.
18483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> ic = is_classic_mode()
18493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? isolate()->builtins()->KeyedStoreIC_Initialize()
18503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
18513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ call(ic);
1852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(rax);
1856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1859d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var,
18600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                               Token::Value op) {
1861589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsUnallocated()) {
1862589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Global var, const, or let.
18633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(rcx, var->name());
18648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ movq(rdx, GlobalObjectOperand());
18653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic = is_classic_mode()
18663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ? isolate()->builtins()->StoreIC_Initialize()
18673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : isolate()->builtins()->StoreIC_Initialize_Strict();
18683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1869e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (op == Token::INIT_CONST) {
1870589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Const initializers need a write barrier.
1871589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ASSERT(!var->IsParameter());  // No const parameters.
1872589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (var->IsStackLocal()) {
1873589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Label skip;
1874589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ movq(rdx, StackOperand(var));
1875589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1876589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ j(not_equal, &skip);
1877589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ movq(StackOperand(var), rax);
1878589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ bind(&skip);
1879589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else {
1880589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ASSERT(var->IsContextSlot() || var->IsLookupSlot());
1881589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Like var declarations, const declarations are hoisted to function
1882589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // scope.  However, unlike var initializers, const initializers are
1883589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // able to drill a hole to that function context, even from inside a
1884589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // 'with' context.  We thus bypass the normal static scope lookup for
1885589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // var->IsContextSlot().
1886589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(rax);
1887589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(rsi);
1888589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ Push(var->name());
1889589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1890e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1891e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
18923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (var->mode() == LET && op != Token::INIT_LET) {
1893589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Non-initializing assignment to let variable needs a write barrier.
1894589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (var->IsLookupSlot()) {
1895589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(rax);  // Value.
1896589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(rsi);  // Context.
1897589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ Push(var->name());
18983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Push(Smi::FromInt(language_mode()));
1899589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CallRuntime(Runtime::kStoreContextSlot, 4);
1900589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else {
1901589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ASSERT(var->IsStackAllocated() || var->IsContextSlot());
1902589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Label assign;
1903589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      MemOperand location = VarOperand(var, rcx);
1904589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ movq(rdx, location);
1905589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1906589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ j(not_equal, &assign, Label::kNear);
1907589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ Push(var->name());
1908589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CallRuntime(Runtime::kThrowReferenceError, 1);
1909589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ bind(&assign);
1910589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ movq(location, rax);
1911589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (var->IsContextSlot()) {
191269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ movq(rdx, rax);
19133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ RecordWriteContextSlot(
19143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
191569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
191669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
1917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
19183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
19193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Assignment to var or initializing assignment to let/const
19203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // in harmony mode.
1921589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (var->IsStackAllocated() || var->IsContextSlot()) {
1922589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      MemOperand location = VarOperand(var, rcx);
1923589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (FLAG_debug_code && op == Token::INIT_LET) {
1924589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // Check for an uninitialized let binding.
1925589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ movq(rdx, location);
1926589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1927589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ Check(equal, "Let binding re-initialization.");
1928589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
1929589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Perform the assignment.
1930589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ movq(location, rax);
1931589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (var->IsContextSlot()) {
1932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ movq(rdx, rax);
19333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ RecordWriteContextSlot(
19343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
19353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
1936589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else {
1937589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ASSERT(var->IsLookupSlot());
1938589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(rax);  // Value.
1939589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(rsi);  // Context.
1940589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ Push(var->name());
19413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Push(Smi::FromInt(language_mode()));
1942589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CallRuntime(Runtime::kStoreContextSlot, 4);
19433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
19443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1945589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Non-initializing assignments to consts are ignored.
19463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
19473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1949d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
1951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
1952d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop != NULL);
1953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop->key()->AsLiteral() != NULL);
19543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1960e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(Operand(rsp, kPointerSize));  // Receiver is now under value.
1961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1962e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1963d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1964d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1965e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1966e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1967d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Move(rcx, prop->key()->AsLiteral()->handle());
19684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (expr->ends_initialization_block()) {
19694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ movq(rdx, Operand(rsp, 0));
19704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
19714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ pop(rdx);
19724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
19733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic = is_classic_mode()
19743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? isolate()->builtins()->StoreIC_Initialize()
19753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : isolate()->builtins()->StoreIC_Initialize_Strict();
19763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ call(ic, RelocInfo::CODE_TARGET, expr->id());
1977d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1978d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1979d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1980d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(rax);  // Result of assignment, saved even if not needed.
1981d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(rsp, kPointerSize));  // Receiver is under value.
1982d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1983d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(rax);
1984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ Drop(1);
1985d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1986086aeeaae12517475c22695a200be45495516549Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(rax);
1988d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1989d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1990d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1991d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1992d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
1993d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1994d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1995d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1996d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1997d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1998e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1999e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Receiver is now under the key and value.
2000d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(rsp, 2 * kPointerSize));
2001d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
2002e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
2003d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2004d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(rcx);
2006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (expr->ends_initialization_block()) {
2007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movq(rdx, Operand(rsp, 0));  // Leave receiver on the stack for later.
2008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
2009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ pop(rdx);
2010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2011e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
2012e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
20133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic = is_classic_mode()
20143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? isolate()->builtins()->KeyedStoreIC_Initialize()
20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
20163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ call(ic, RelocInfo::CODE_TARGET, expr->id());
2017d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2018d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
2019d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
2020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ pop(rdx);
2021d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(rax);  // Result of assignment, saved even if not needed.
2022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(rdx);
2023d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
2024d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(rax);
2025d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2026d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2027086aeeaae12517475c22695a200be45495516549Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
20280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2029d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2030d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2031d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2032d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) {
2033d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Property");
2034d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* key = expr->key();
2035d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2036e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (key->IsPropertyName()) {
20370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->obj());
2038e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitNamedPropertyLoad(expr);
2039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    context()->Plug(rax);
2040d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
20410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(expr->obj());
20420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->key());
20437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ pop(rdx);
2044e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitKeyedPropertyLoad(expr);
2045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    context()->Plug(rax);
2046d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2047d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2048d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2049d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2050d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr,
2051402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                       Handle<Object> name,
2052e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       RelocInfo::Mode mode) {
2053d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the IC.
2054d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
20553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
2056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { PreservePositionScope scope(masm()->positions_recorder());
20573e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
20583e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
20593e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
20603e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    __ Move(rcx, name);
20613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2062d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
2063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
20643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the IC initialization code.
206544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic =
2066589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
20673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ call(ic, mode, expr->id());
2068086aeeaae12517475c22695a200be45495516549Ben Murdoch  RecordJSReturnSite(expr);
2069d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Restore context register.
2070d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
20710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2072d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2074d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
20759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Expression* key) {
20778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the key.
20788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForAccumulatorValue(key);
20798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Swap the name of the function and the receiver on the stack to follow
20818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // the calling convention for call ICs.
20828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ pop(rcx);
20838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(rax);
20848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(rcx);
20858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the arguments.
20879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ZoneList<Expression*>* args = expr->arguments();
20889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  int arg_count = args->length();
2089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { PreservePositionScope scope(masm()->positions_recorder());
20903e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
20913e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
20923e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
20939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
20949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Record source position for debugger.
2095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
20969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Call the IC initialization code.
209744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic =
2098589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
20998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize));  // Key.
21003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ call(ic, RelocInfo::CODE_TARGET, expr->id());
2101086aeeaae12517475c22695a200be45495516549Ben Murdoch  RecordJSReturnSite(expr);
21029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Restore context register.
21039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
21048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  context()->DropAndPlug(1, rax);  // Drop the key still on the stack.
21059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
21069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
21079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
2109d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the call stub.
2110d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2111d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
2112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { PreservePositionScope scope(masm()->positions_recorder());
21133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
21143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
21153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
2118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
2119589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  CallFunctionStub stub(arg_count, flags);
21203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ CallStub(&stub);
2122086aeeaae12517475c22695a200be45495516549Ben Murdoch  RecordJSReturnSite(expr);
21233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore context register.
21243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
21253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Discard the function left on TOS.
21260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->DropAndPlug(1, rax);
2127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
21303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Push copy of the first argument or undefined if it doesn't exist.
2132e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (arg_count > 0) {
2133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ push(Operand(rsp, arg_count * kPointerSize));
2134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
2135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ PushRoot(Heap::kUndefinedValueRootIndex);
2136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Push the receiver of the enclosing function and do runtime call.
21393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ push(Operand(rbp, (2 + info_->scope()->num_parameters()) * kPointerSize));
2140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
21413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the language mode.
21423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(Smi::FromInt(language_mode()));
21433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the start position of the scope the calls resides in.
21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(Smi::FromInt(scope()->start_position()));
2146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
21473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do the runtime call.
21483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
2149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2152d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) {
2153086aeeaae12517475c22695a200be45495516549Ben Murdoch#ifdef DEBUG
2154086aeeaae12517475c22695a200be45495516549Ben Murdoch  // We want to verify that RecordJSReturnSite gets called on all paths
2155086aeeaae12517475c22695a200be45495516549Ben Murdoch  // through this function.  Avoid early returns.
2156086aeeaae12517475c22695a200be45495516549Ben Murdoch  expr->return_is_recorded_ = false;
2157086aeeaae12517475c22695a200be45495516549Ben Murdoch#endif
2158086aeeaae12517475c22695a200be45495516549Ben Murdoch
2159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Call");
2160589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Expression* callee = expr->expression();
2161589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  VariableProxy* proxy = callee->AsVariableProxy();
2162589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Property* property = callee->AsProperty();
2163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2164589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (proxy != NULL && proxy->var()->is_possibly_eval()) {
2165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // In a call to eval, we first call %ResolvePossiblyDirectEval to
2166589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // resolve the function we need to call and the receiver of the call.
2167589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Then we call the resolved function using the given arguments.
2168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    ZoneList<Expression*>* args = expr->arguments();
2169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    int arg_count = args->length();
2170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope pos_scope(masm()->positions_recorder());
2171589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VisitForStackValue(callee);
21723e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ PushRoot(Heap::kUndefinedValueRootIndex);  // Reserved receiver slot.
2173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21743e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Push the arguments.
21753e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      for (int i = 0; i < arg_count; i++) {
21763e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        VisitForStackValue(args->at(i));
21773e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      }
2178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2179589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Push a copy of the function (found below the arguments) and resolve
2180589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // eval.
2181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ push(Operand(rsp, (arg_count + 1) * kPointerSize));
21823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitResolvePossiblyDirectEval(arg_count);
2183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // The runtime call returns a pair of values in rax (function) and
21853e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // rdx (receiver). Touch up the stack with the right values.
21863e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
21873e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
21883e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Record source position for debugger.
2190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetSourcePosition(expr->position());
2191589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT);
21923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
2194086aeeaae12517475c22695a200be45495516549Ben Murdoch    RecordJSReturnSite(expr);
2195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Restore context register.
2196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
21970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->DropAndPlug(1, rax);
2198589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
2199589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Call to a global variable.  Push global object as receiver for the
2200589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // call IC lookup.
22018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ push(GlobalObjectOperand());
2202589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
2203589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
220459151504615d929945dc59db37bf1166937748c6Steve Block    // Call to a lookup slot (dynamically introduced variable).
220559151504615d929945dc59db37bf1166937748c6Steve Block    Label slow, done;
220659151504615d929945dc59db37bf1166937748c6Steve Block
2207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope scope(masm()->positions_recorder());
2208589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Generate code for loading from variables potentially shadowed by
2209589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // eval-introduced variables.
2210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
2211086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
2212589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ bind(&slow);
2213589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Call the runtime to find the function to call (returned in rax) and
2214589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // the object holding it (returned in rdx).
2215086aeeaae12517475c22695a200be45495516549Ben Murdoch    __ push(context_register());
2216589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ Push(proxy->name());
2217086aeeaae12517475c22695a200be45495516549Ben Murdoch    __ CallRuntime(Runtime::kLoadContextSlot, 2);
2218086aeeaae12517475c22695a200be45495516549Ben Murdoch    __ push(rax);  // Function.
2219086aeeaae12517475c22695a200be45495516549Ben Murdoch    __ push(rdx);  // Receiver.
2220086aeeaae12517475c22695a200be45495516549Ben Murdoch
2221589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // If fast case code has been generated, emit code to push the function
2222589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // and receiver and have the slow path jump around this code.
2223086aeeaae12517475c22695a200be45495516549Ben Murdoch    if (done.is_linked()) {
2224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label call;
2225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ jmp(&call, Label::kNear);
2226086aeeaae12517475c22695a200be45495516549Ben Murdoch      __ bind(&done);
2227086aeeaae12517475c22695a200be45495516549Ben Murdoch      // Push function.
2228086aeeaae12517475c22695a200be45495516549Ben Murdoch      __ push(rax);
2229589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // The receiver is implicitly the global receiver. Indicate this by
2230589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // passing the hole to the call function stub.
22313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ PushRoot(Heap::kTheHoleValueRootIndex);
2232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ bind(&call);
223359151504615d929945dc59db37bf1166937748c6Steve Block    }
223459151504615d929945dc59db37bf1166937748c6Steve Block
2235589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // The receiver is either the global receiver or an object found by
2236589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // LoadContextSlot. That object could be the hole if the receiver is
2237589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // implicitly the global object.
2238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT);
2239589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (property != NULL) {
2240589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    { PreservePositionScope scope(masm()->positions_recorder());
2241589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VisitForStackValue(property->obj());
2242589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
2243589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (property->key()->IsPropertyName()) {
2244589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      EmitCallWithIC(expr,
2245589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     property->key()->AsLiteral()->handle(),
2246589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     RelocInfo::CODE_TARGET);
2247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
2248589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      EmitKeyedCallWithIC(expr, property->key());
2249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
22503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2251589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Call to an arbitrary expression not handled specially above.
2252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope scope(masm()->positions_recorder());
2253589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VisitForStackValue(callee);
22543e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load global receiver object.
22568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ movq(rbx, GlobalObjectOperand());
2257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
2258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit function call.
2259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
2260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2261086aeeaae12517475c22695a200be45495516549Ben Murdoch
2262086aeeaae12517475c22695a200be45495516549Ben Murdoch#ifdef DEBUG
2263086aeeaae12517475c22695a200be45495516549Ben Murdoch  // RecordJSReturnSite should have been called.
2264086aeeaae12517475c22695a200be45495516549Ben Murdoch  ASSERT(expr->return_is_recorded_);
2265086aeeaae12517475c22695a200be45495516549Ben Murdoch#endif
2266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2269d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
2270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
2271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
2272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
2273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
2274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
227580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Push constructor on the stack.  If it's not a function it's used as
227680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
227780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ignored.
22780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->expression());
2279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
2281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
2283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
22840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
22853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
2288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
2289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
2290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
229180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load function and argument count into rdi and rax.
2292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Set(rax, arg_count);
229380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movq(rdi, Operand(rsp, arg_count * kPointerSize));
2294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
22953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Record call targets in unoptimized code, but not in the snapshot.
22963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallFunctionFlags flags;
22973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!Serializer::enabled()) {
22983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    flags = RECORD_CALL_TARGET;
22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> uninitialized =
23003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        TypeFeedbackCells::UninitializedSentinel(isolate());
23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell =
23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
23033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RecordTypeFeedbackCell(expr->id(), cell);
23043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(rbx, cell);
23053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
23063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    flags = NO_CALL_FUNCTION_FLAGS;
23073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
23083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallConstructStub stub(flags);
23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
23113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
23120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
23133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
23143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
23153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
23163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
23173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
232580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
23260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
23270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_true);
2331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
2332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
23383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2343f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
234680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
23470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
23480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2351f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax);
2352f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Split(non_negative_smi, if_true, if_false, fall_through);
2353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
23593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
236780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
23680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
23690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2370f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareRoot(rax, Heap::kNullValueRootIndex);
2373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
2374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Undetectable objects behave like undefined when tested with typeof.
2376f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke           Immediate(1 << Map::kIsUndetectable));
2378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_zero, if_false);
2379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
23803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmpq(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, if_false);
23823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmpq(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
23833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
238480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(below_equal, if_true, if_false, fall_through);
2385f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2387f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
23913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
23923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(args->length() == 1);
23933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
23940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
23953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
23963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label materialize_true, materialize_false;
23973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_true = NULL;
23983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_false = NULL;
239980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
24023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
24033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ JumpIfSmi(rax, if_false);
24043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx);
24053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
240680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(above_equal, if_true, if_false, fall_through);
24073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
24080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
24093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
24103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
24113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
24133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
242180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke           Immediate(1 << Map::kIsUndetectable));
24293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
243080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(not_zero, if_true, if_false, fall_through);
2431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2436756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
24373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime* expr) {
24383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2439756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ASSERT(args->length() == 1);
2440756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
24410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2442756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2443756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label materialize_true, materialize_false;
2444756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_true = NULL;
2445756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_false = NULL;
244680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2449756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
24508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (FLAG_debug_code) __ AbortIfSmi(rax);
24518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
24528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Check whether this map has already been checked to be safe for default
24538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // valueOf.
24548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
24558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ testb(FieldOperand(rbx, Map::kBitField2Offset),
24568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch           Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
24578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ j(not_zero, if_true);
24588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
24598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Check for fast case object. Generate false result for slow case object.
24608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ movq(rcx, FieldOperand(rax, JSObject::kPropertiesOffset));
24618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
24628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ CompareRoot(rcx, Heap::kHashTableMapRootIndex);
24638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ j(equal, if_false);
24648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
24658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Look for valueOf symbol in the descriptor array, and indicate false if
24668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // found. The type is not checked, so if it is a transition it is a false
24678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // negative.
2468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadInstanceDescriptors(rbx, rbx);
24698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ movq(rcx, FieldOperand(rbx, FixedArray::kLengthOffset));
24708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // rbx: descriptor array
24718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // rcx: length of descriptor array
24728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Calculate the end of the descriptor array.
24738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  SmiIndex index = masm_->SmiToIndex(rdx, rcx, kPointerSizeLog2);
24748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ lea(rcx,
24758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch         Operand(
24768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch             rbx, index.reg, index.scale, FixedArray::kHeaderSize));
24778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Calculate location of the first key name.
24788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ addq(rbx,
24798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          Immediate(FixedArray::kHeaderSize +
24808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                    DescriptorArray::kFirstIndex * kPointerSize));
24818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Loop through all the keys in the descriptor array. If one of these is the
24828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // symbol valueOf the result is false.
24838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Label entry, loop;
24848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ jmp(&entry);
24858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ bind(&loop);
24868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ movq(rdx, FieldOperand(rbx, 0));
24878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ Cmp(rdx, FACTORY->value_of_symbol());
24888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ j(equal, if_false);
24898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ addq(rbx, Immediate(kPointerSize));
24908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ bind(&entry);
24918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ cmpq(rbx, rcx);
24928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ j(not_equal, &loop);
24938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
24948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Reload map as register rbx was used as temporary above.
24958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
24968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
24978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // If a valueOf property is not found on the object check that it's
24988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // prototype is the un-modified String prototype. If not result is false.
24998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
25008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ testq(rcx, Immediate(kSmiTagMask));
25018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ j(zero, if_false);
25028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
25038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ movq(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
25048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalContextOffset));
25058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ cmpq(rcx,
25068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
25078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ j(not_equal, if_false);
25088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Set the bit in the map to indicate that it has been checked safe for
25098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // default valueOf and set true result.
25108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ or_(FieldOperand(rbx, Map::kBitField2Offset),
25118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch         Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
25128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ jmp(if_true);
25138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
25143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
25150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2516756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2517756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2518756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
25193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
25203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
252880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
25300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
25343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
253580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
25423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
255080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
25520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
25563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
255780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
25643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
257280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
25740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
25783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
257980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
25873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(expr->arguments()->length() == 0);
2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
259280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
25940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the frame pointer for the calling frame.
2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Skip the arguments adaptor frame if it exists.
2600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label check_frame_marker;
260144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Cmp(Operand(rax, StandardFrameConstants::kContextOffset),
260244f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &check_frame_marker);
2604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
2605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check the marker in the calling frame.
2607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&check_frame_marker);
260844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset),
260944f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Smi::FromInt(StackFrame::CONSTRUCT));
26103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
261180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
26183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the two objects into registers and perform the comparison.
26220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
26230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
2624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
262880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
26290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
26300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(rbx);
2633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(rax, rbx);
26343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
263580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArguments(CallRuntime* expr) {
26423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
264580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ArgumentsAccessStub expects the key in rdx and the formal
264680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // parameter count in rax.
26470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rdx, rax);
26493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
2650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
26520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
26573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(expr->arguments()->length() == 0);
2658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label exit;
2660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the number of formal parameters.
26613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
2662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the calling frame is an arguments adaptor frame.
2664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
266544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
266644f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &exit, Label::kNear);
2668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Arguments adaptor case: Read the arguments length from the
2670f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // adaptor frame.
2671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
2674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (FLAG_debug_code) __ AbortIfNotSmi(rax);
26750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2678f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
26803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, null, function, non_function_constructor;
2683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, we return null.
2687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, &null);
2688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check that the object is a JS object but take special care of JS
2690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // functions to make sure they have 'Function' as their class.
26913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Assume that there are only two callable types, and one of them is at
26923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // either end of the type range for JS object types. Saves extra comparisons.
26933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
26943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax);
26953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Map is now in rax.
2696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, &null);
26973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                FIRST_SPEC_OBJECT_TYPE + 1);
26993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(equal, &function);
27003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE);
27023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                LAST_SPEC_OBJECT_TYPE - 1);
27043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(equal, &function);
27053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Assume that there is no larger type.
27063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
27073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the constructor in the map is a JS function.
2709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rax, Map::kConstructorOffset));
2710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &non_function_constructor);
2712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // rax now contains the constructor function. Grab the
2714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // instance class name from there.
2715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
2716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset));
2717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Functions have class 'Function'.
2720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&function);
272144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(rax, isolate()->factory()->function_class_symbol());
2722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2723f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Objects with a non-function constructor have class 'Object'.
2725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&non_function_constructor);
272644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(rax, isolate()->factory()->Object_symbol());
2727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-JS objects have class null.
2730f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&null);
2731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(rax, Heap::kNullValueRootIndex);
2732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // All done.
2734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLog(CallRuntime* expr) {
2741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Conditionally generate a log call.
2742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Args:
2743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   0 (literal string): The type of logging (corresponds to the flags).
2744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     This is used to determine whether or not to generate the log call.
2745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   1 (string): Format string.  Access the string at argument index 2
2746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     with '%2s' (see Logger::LogRuntime for all the formats).
2747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   2 (array): Arguments to the format string.
27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 3);
2750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
27510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(1));
27520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(2));
2753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLog, 2);
2754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Finally, we're expected to leave a value on the top of the stack.
2756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
27570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
27623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(expr->arguments()->length() == 0);
2763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label slow_allocate_heapnumber;
2765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label heapnumber_allocated;
2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ AllocateHeapNumber(rbx, rcx, &slow_allocate_heapnumber);
2768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&heapnumber_allocated);
2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&slow_allocate_heapnumber);
27713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Allocate a heap number.
27723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CallRuntime(Runtime::kNumberAlloc, 0);
2773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, rax);
2774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&heapnumber_allocated);
2776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Return a random uint32 number in rax.
2778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs.
27798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ PrepareCallCFunction(1);
27808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef _WIN64
27813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rcx, ContextOperand(context_register(), Context::GLOBAL_INDEX));
27823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset));
27833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#else
27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rdi, ContextOperand(context_register(), Context::GLOBAL_INDEX));
27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rdi, FieldOperand(rdi, GlobalObject::kGlobalContextOffset));
27878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif
27888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
2789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert 32 random bits in rax to 0.(32 random bits) in a double
2791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // by computing:
2792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
2793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rcx, Immediate(0x49800000));  // 1.0 x 2^20 as single.
2794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movd(xmm1, rcx);
2795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movd(xmm0, rax);
2796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cvtss2sd(xmm1, xmm1);
2797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ xorps(xmm0, xmm1);
2798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ subsd(xmm0, xmm1);
2799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0);
2800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, rbx);
28020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSubString(CallRuntime* expr) {
2807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SubStringStub stub;
28093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
28110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
28120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
28130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
2814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
28150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
2820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  RegExpExecStub stub;
28223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 4);
28240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
28250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
28260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
28270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(3));
2828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
28290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
28343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));  // Load the object.
2838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
2840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi return the object.
2841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, &done);
2842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the object.
2843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_VALUE_TYPE, rbx);
2844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &done);
2845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(rax, JSValue::kValueOffset));
2846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
28480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitDateField(CallRuntime* expr) {
28533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
28543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(args->length() == 2);
28553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_NE(NULL, args->at(1)->AsLiteral());
28563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->handle()));
28573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitForAccumulatorValue(args->at(0));  // Load the object.
28593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label runtime, done;
28613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = rax;
28623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = rax;
28633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = rcx;
28643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
28663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ AbortIfSmi(object);
28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpObjectType(object, JS_DATE_TYPE, scratch);
28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Assert(equal, "Trying to get date field from non-date.");
28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
28703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (index->value() == 0) {
28723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(result, FieldOperand(object, JSDate::kValueOffset));
28733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
28743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (index->value() < JSDate::kFirstUncachedField) {
28753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
28763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(scratch, stamp);
28773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmpq(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
28783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(not_equal, &runtime, Label::kNear);
28793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(result, FieldOperand(object, JSDate::kValueOffset +
28803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           kPointerSize * index->value()));
28813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&done);
28823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
28833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&runtime);
28843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ PrepareCallCFunction(2);
28853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef _WIN64
28863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rcx, object);
28873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rdx, index, RelocInfo::NONE);
28883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#else
28893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rdi, object);
28903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rsi, index, RelocInfo::NONE);
28913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
28923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
28943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&done);
28953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
28963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->Plug(rax);
28973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
2901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the runtime function.
29023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
29040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
29050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
29063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MathPowStub stub(MathPowStub::ON_STACK);
2907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CallStub(&stub);
29080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
29133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));  // Load the object.
29170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));  // Load the value.
291880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ pop(rbx);  // rax = value. rbx = object.
2919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
2921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, return the value.
2922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rbx, &done);
2923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the value.
2925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx);
2926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &done);
2927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Store the value.
2929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(FieldOperand(rbx, JSValue::kValueOffset), rax);
2930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the write barrier.  Save the value as it will be
2931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // overwritten by the write barrier code and is needed afterward.
2932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rdx, rax);
29333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs);
2934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
29360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
29413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 1);
2943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
29450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  NumberToStringStub stub;
2948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
29490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
29543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
29607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharFromCodeGenerator generator(rax, rbx);
29617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
29627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
2963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
29657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
2966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
29680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rbx);
29697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
29707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
29717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
29723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
29733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
29747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
29757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
29760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
29770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
29787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
29797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = rbx;
29807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = rax;
29817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = rdx;
29827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
29837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
29847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
29857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
29867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
29877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
29887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharCodeAtGenerator generator(object,
29897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      index,
29907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      result,
29917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
29927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
29937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &index_out_of_range,
29947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      STRING_INDEX_IS_NUMBER);
29957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
2996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
29997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
30007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // NaN.
30017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kNanValueRootIndex);
30027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
30037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
30057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move the undefined value into the result register, which will
30067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // trigger conversion.
30077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
30087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
30097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
30117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
3012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
30140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
3015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
30207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
30217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
30230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
30247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = rbx;
30267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = rax;
30273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = rdx;
30287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = rax;
30297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
30317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
30337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
30347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
30357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharAtGenerator generator(object,
30367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  index,
30373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  scratch,
30387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  result,
30397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
30407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
30417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &index_out_of_range,
30427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  STRING_INDEX_IS_NUMBER);
30437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
30447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
30457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
30477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
30487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the empty string.
30497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kEmptyStringRootIndex);
30507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
30517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
30537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move smi zero into the result register, which will trigger
30547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // conversion.
30557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Move(result, Smi::FromInt(0));
30567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
30577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
30597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
30607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
30620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
3063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
3069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
30710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
3072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringAddStub stub(NO_STRING_ADD_FLAGS);
3074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
30750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
30803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
3082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
30840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
3085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringCompareStub stub;
3087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
30880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
3093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
3094e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  TranscendentalCacheStub stub(TranscendentalCache::SIN,
3095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               TranscendentalCacheStub::TAGGED);
30963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
30980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
3099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
31000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
3105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
3106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  TranscendentalCacheStub stub(TranscendentalCache::COS,
3107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               TranscendentalCacheStub::TAGGED);
31083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
31100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
3111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
31120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathTan(CallRuntime* expr) {
31173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the argument on the stack and call the stub.
31183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  TranscendentalCacheStub stub(TranscendentalCache::TAN,
31193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               TranscendentalCacheStub::TAGGED);
31203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
31213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(args->length() == 1);
31223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitForStackValue(args->at(0));
31233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallStub(&stub);
31243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->Plug(rax);
31253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
31263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
3129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the argument on the stack and call the stub.
3130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  TranscendentalCacheStub stub(TranscendentalCache::LOG,
3131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               TranscendentalCacheStub::TAGGED);
31323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(args->length() == 1);
3134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForStackValue(args->at(0));
3135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CallStub(&stub);
3136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(rax);
3137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
31403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
3141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the runtime function.
31423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
31440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
3145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_sqrt, 1);
31460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
31513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() >= 2);
3153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int arg_count = args->length() - 2;  // 2 ~ receiver and function.
3155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < arg_count + 1; i++) {
3156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VisitForStackValue(args->at(i));
3157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  VisitForAccumulatorValue(args->last());  // Function.
3159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for proxy.
31613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label proxy, done;
31623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpObjectType(rax, JS_FUNCTION_PROXY_TYPE, rbx);
31633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(equal, &proxy);
31643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // InvokeFunction requires the function in rdi. Move it in there.
3166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movq(rdi, result_register());
3167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ParameterCount count(arg_count);
3168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(rdi, count, CALL_FUNCTION,
3169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), CALL_AS_METHOD);
3170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
31713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&done);
31723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&proxy);
31743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(rax);
31753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallRuntime(Runtime::kCall, args->length());
31763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
31773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RegExpConstructResultStub stub;
31843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
31860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
31870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
31880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
3189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CallStub(&stub);
31900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3191f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3192f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
31953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
3197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_NE(NULL, args->at(0)->AsLiteral());
3199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
3200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<FixedArray> jsfunction_result_caches(
320244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->global_context()->jsfunction_result_caches());
3203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (jsfunction_result_caches->length() <= cache_id) {
3204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Abort("Attempt to use undefined cache.");
3205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
32060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
3207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
3211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register key = rax;
3213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register cache = rbx;
3214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register tmp = rcx;
321559151504615d929945dc59db37bf1166937748c6Steve Block  __ movq(cache, ContextOperand(rsi, Context::GLOBAL_INDEX));
3216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(cache,
3217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          FieldOperand(cache, GlobalObject::kGlobalContextOffset));
3218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(cache,
321959151504615d929945dc59db37bf1166937748c6Steve Block          ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
3220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(cache,
3221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
3222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done, not_found;
3224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // tmp now holds finger offset as a smi.
322569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
3227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SmiIndex index =
3228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2);
3229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpq(key, FieldOperand(cache,
3230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.reg,
3231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.scale,
3232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            FixedArray::kHeaderSize));
3233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &not_found, Label::kNear);
3234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rax, FieldOperand(cache,
3235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.reg,
3236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.scale,
3237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            FixedArray::kHeaderSize + kPointerSize));
3238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&done, Label::kNear);
3239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&not_found);
3241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call runtime to perform the lookup.
3242f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(cache);
3243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(key);
3244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetFromCache, 2);
3245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
32470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
32523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3253bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT_EQ(2, args->length());
3254bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3255bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register right = rax;
3256bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register left = rbx;
3257bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register tmp = rcx;
3258bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
32590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
32600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
3261bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(left);
3262bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done, fail, ok;
3264bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmpq(left, right);
3265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &ok, Label::kNear);
3266bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Fail if either is a non-HeapObject.
3267bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Condition either_smi = masm()->CheckEitherSmi(left, right, tmp);
3268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(either_smi, &fail, Label::kNear);
3269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(zero, &fail, Label::kNear);
3270bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(tmp, FieldOperand(left, HeapObject::kMapOffset));
3271bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmpb(FieldOperand(tmp, Map::kInstanceTypeOffset),
3272bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch          Immediate(JS_REGEXP_TYPE));
3273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &fail, Label::kNear);
3274bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmpq(tmp, FieldOperand(right, HeapObject::kMapOffset));
3275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &fail, Label::kNear);
3276bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(tmp, FieldOperand(left, JSRegExp::kDataOffset));
3277bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmpq(tmp, FieldOperand(right, JSRegExp::kDataOffset));
3278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &ok, Label::kNear);
3279bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&fail);
328044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(rax, isolate()->factory()->false_value());
3281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&done, Label::kNear);
3282bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&ok);
328344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(rax, isolate()->factory()->true_value());
3284bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&done);
3285bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
32860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3287bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
3288bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3289bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
32903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
32913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
329280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(args->length() == 1);
329380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
32940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
329580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
329680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
329780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
329880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
329980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
33000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
33010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
330280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
330380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ testl(FieldOperand(rax, String::kHashFieldOffset),
330480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           Immediate(String::kContainsCachedArrayIndexMask));
33053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
330680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(zero, if_true);
330780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(if_false);
330880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
33090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
331080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
331180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
331280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
33133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
33143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
331580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(args->length() == 1);
33160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
331780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (FLAG_debug_code) {
3319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ AbortIfNotString(rax);
3320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
3321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
332280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movl(rax, FieldOperand(rax, String::kHashFieldOffset));
332380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(String::kHashShift >= kSmiTagSize);
332480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ IndexFromHash(rax, rax);
332580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
33260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
332780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
332880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
332980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
33303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
333144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label bailout, return_result, done, one_char_separator, long_separator,
333244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      non_trivial_array, not_size_one_array, loop,
333344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
33343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
333544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(args->length() == 2);
333644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // We will leave the separator on the stack until the end of the function.
333744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  VisitForStackValue(args->at(1));
333844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load this to rax (= array)
333944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  VisitForAccumulatorValue(args->at(0));
334044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // All aliases of the same register have disjoint lifetimes.
334144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register array = rax;
334244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register elements = no_reg;  // Will be rax.
334344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
334444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register index = rdx;
334544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
334644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register string_length = rcx;
334744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
334844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register string = rsi;
334944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
335044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register scratch = rbx;
335144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
335244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register array_length = rdi;
335344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register result_pos = no_reg;  // Will be rdi.
335444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
335544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand separator_operand =    Operand(rsp, 2 * kPointerSize);
335644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand result_operand =       Operand(rsp, 1 * kPointerSize);
335744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand array_length_operand = Operand(rsp, 0 * kPointerSize);
335844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Separator operand is already pushed. Make room for the two
335944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // other stack fields, and clear the direction flag in anticipation
336044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // of calling CopyBytes.
336144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ subq(rsp, Immediate(2 * kPointerSize));
336244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cld();
336344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the array is a JSArray
336444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ JumpIfSmi(array, &bailout);
336544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
336644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(not_equal, &bailout);
336744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
336844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the array has fast elements.
33693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CheckFastElements(scratch, &bailout);
337044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
337144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Array has fast elements, so its length must be a smi.
337244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If the array has length zero, return the empty string.
337344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(array_length, FieldOperand(array, JSArray::kLengthOffset));
337444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiCompare(array_length, Smi::FromInt(0));
337544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(not_zero, &non_trivial_array);
337644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ LoadRoot(rax, Heap::kEmptyStringRootIndex);
337744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&return_result);
337844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
337944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Save the array length on the stack.
338044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&non_trivial_array);
338144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiToInteger32(array_length, array_length);
338244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movl(array_length_operand, array_length);
338344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
338444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Save the FixedArray containing array's elements.
338544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // End of array's live range.
338644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  elements = array;
338744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(elements, FieldOperand(array, JSArray::kElementsOffset));
338844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  array = no_reg;
338944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
339044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
339144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that all array elements are sequential ASCII strings, and
339244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // accumulate the sum of their lengths, as a smi-encoded value.
339344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Set(index, 0);
339444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Set(string_length, 0);
339544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Loop condition: while (index < array_length).
339644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live loop registers: index(int32), array_length(int32), string(String*),
339744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //                      scratch, string_length(int32), elements(FixedArray*).
339844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_debug_code) {
339944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(index, array_length);
340044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Assert(below, "No empty arrays here in EmitFastAsciiArrayJoin");
340144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
340244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&loop);
340344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(string, FieldOperand(elements,
340444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               index,
340544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               times_pointer_size,
340644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               FixedArray::kHeaderSize));
340744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ JumpIfSmi(string, &bailout);
340844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(scratch, FieldOperand(string, HeapObject::kMapOffset));
340944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
341044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ andb(scratch, Immediate(
341144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
341244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpb(scratch, Immediate(kStringTag | kAsciiStringTag | kSeqStringTag));
341344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(not_equal, &bailout);
341444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ AddSmiField(string_length,
341544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                 FieldOperand(string, SeqAsciiString::kLengthOffset));
341644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(overflow, &bailout);
341744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ incl(index);
341844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpl(index, array_length);
341944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(less, &loop);
342044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
342144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live registers:
342244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // string_length: Sum of string lengths.
342344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // elements: FixedArray of strings.
342444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // index: Array length.
342544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // array_length: Array length.
342644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
342744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If array_length is 1, return elements[0], a string.
342844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpl(array_length, Immediate(1));
342944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(not_equal, &not_size_one_array);
343044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(rax, FieldOperand(elements, FixedArray::kHeaderSize));
343144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&return_result);
343244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
343344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&not_size_one_array);
343444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
343544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // End of array_length live range.
343644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  result_pos = array_length;
343744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  array_length = no_reg;
343844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
343944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live registers:
344044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // string_length: Sum of string lengths.
344144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // elements: FixedArray of strings.
344244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // index: Array length.
344344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
344444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the separator is a sequential ASCII string.
344544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(string, separator_operand);
344644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ JumpIfSmi(string, &bailout);
344744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(scratch, FieldOperand(string, HeapObject::kMapOffset));
344844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
344944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ andb(scratch, Immediate(
345044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
345144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpb(scratch, Immediate(kStringTag | kAsciiStringTag | kSeqStringTag));
345244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(not_equal, &bailout);
345344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
345444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live registers:
345544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // string_length: Sum of string lengths.
345644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // elements: FixedArray of strings.
345744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // index: Array length.
345844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // string: Separator string.
345944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
346044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Add (separator length times (array_length - 1)) to string_length.
346144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiToInteger32(scratch,
346244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    FieldOperand(string, SeqAsciiString::kLengthOffset));
346344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ decl(index);
346444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ imull(scratch, index);
346544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(overflow, &bailout);
346644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ addl(string_length, scratch);
346744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(overflow, &bailout);
346844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
346944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live registers and stack values:
347044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   string_length: Total length of result string.
347144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   elements: FixedArray of strings.
347244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ AllocateAsciiString(result_pos, string_length, scratch,
347344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         index, string, &bailout);
347444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(result_operand, result_pos);
347544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ lea(result_pos, FieldOperand(result_pos, SeqAsciiString::kHeaderSize));
347644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
347744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(string, separator_operand);
347844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiCompare(FieldOperand(string, SeqAsciiString::kLengthOffset),
347944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Smi::FromInt(1));
348044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(equal, &one_char_separator);
348144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(greater, &long_separator);
348244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
348344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
348444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Empty separator case:
348544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Set(index, 0);
348644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movl(scratch, array_length_operand);
348744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&loop_1_condition);
348844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Loop condition: while (index < array_length).
348944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&loop_1);
349044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Each iteration of the loop concatenates one string to the result.
349144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live values in registers:
349244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   index: which element of the elements array we are adding to the result.
349344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   result_pos: the position to which we are currently copying characters.
349444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   elements: the FixedArray of strings we are joining.
349544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   scratch: array length.
349644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
349744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get string = array[index].
349844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(string, FieldOperand(elements, index,
349944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               times_pointer_size,
350044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               FixedArray::kHeaderSize));
350144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiToInteger32(string_length,
350244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    FieldOperand(string, String::kLengthOffset));
350344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ lea(string,
350444f0eee88ff00398ff7f715fab053374d808c90dSteve Block         FieldOperand(string, SeqAsciiString::kHeaderSize));
350544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ CopyBytes(result_pos, string, string_length);
350644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ incl(index);
350744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&loop_1_condition);
350844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpl(index, scratch);
350944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(less, &loop_1);  // Loop while (index < array_length).
351044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&done);
351144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
351244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Generic bailout code used from several places.
351344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&bailout);
351444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
351544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&return_result);
351644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
351744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
351844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // One-character separator case
351944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&one_char_separator);
35203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the separator ASCII character value.
352144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Register "string" holds the separator.
352244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movzxbl(scratch, FieldOperand(string, SeqAsciiString::kHeaderSize));
352344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Set(index, 0);
352444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Jump into the loop after the code that copies the separator, so the first
352544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // element is not preceded by a separator
352644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&loop_2_entry);
352744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Loop condition: while (index < length).
352844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&loop_2);
352944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Each iteration of the loop concatenates one string to the result.
353044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live values in registers:
353144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   elements: The FixedArray of strings we are joining.
353244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   index: which element of the elements array we are adding to the result.
353344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   result_pos: the position to which we are currently copying characters.
353444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   scratch: Separator character.
353544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
353644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Copy the separator character to the result.
353744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movb(Operand(result_pos, 0), scratch);
353844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ incq(result_pos);
353944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
354044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&loop_2_entry);
354144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get string = array[index].
354244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(string, FieldOperand(elements, index,
354344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               times_pointer_size,
354444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               FixedArray::kHeaderSize));
354544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiToInteger32(string_length,
354644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    FieldOperand(string, String::kLengthOffset));
354744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ lea(string,
354844f0eee88ff00398ff7f715fab053374d808c90dSteve Block         FieldOperand(string, SeqAsciiString::kHeaderSize));
354944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ CopyBytes(result_pos, string, string_length);
355044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ incl(index);
355144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpl(index, array_length_operand);
355244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(less, &loop_2);  // End while (index < length).
355344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&done);
355444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
355544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
355644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Long separator case (separator is more than one character).
355744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&long_separator);
355844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
355944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Make elements point to end of elements array, and index
356044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // count from -array_length to zero, so we don't need to maintain
356144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // a loop limit.
356244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movl(index, array_length_operand);
356344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ lea(elements, FieldOperand(elements, index, times_pointer_size,
356444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                FixedArray::kHeaderSize));
356544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ neg(index);
356644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
356744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Replace separator string with pointer to its first character, and
356844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // make scratch be its length.
356944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(string, separator_operand);
357044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiToInteger32(scratch,
357144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    FieldOperand(string, String::kLengthOffset));
357244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ lea(string,
357344f0eee88ff00398ff7f715fab053374d808c90dSteve Block         FieldOperand(string, SeqAsciiString::kHeaderSize));
357444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(separator_operand, string);
357544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
357644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Jump into the loop after the code that copies the separator, so the first
357744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // element is not preceded by a separator
357844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&loop_3_entry);
357944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Loop condition: while (index < length).
358044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&loop_3);
358144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Each iteration of the loop concatenates one string to the result.
358244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live values in registers:
358344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   index: which element of the elements array we are adding to the result.
358444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   result_pos: the position to which we are currently copying characters.
358544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   scratch: Separator length.
358644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   separator_operand (rsp[0x10]): Address of first char of separator.
358744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
358844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Copy the separator to the result.
358944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(string, separator_operand);
359044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movl(string_length, scratch);
359144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ CopyBytes(result_pos, string, string_length, 2);
359244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
359344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&loop_3_entry);
359444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get string = array[index].
359544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(string, Operand(elements, index, times_pointer_size, 0));
359644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiToInteger32(string_length,
359744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    FieldOperand(string, String::kLengthOffset));
359844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ lea(string,
359944f0eee88ff00398ff7f715fab053374d808c90dSteve Block         FieldOperand(string, SeqAsciiString::kHeaderSize));
360044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ CopyBytes(result_pos, string, string_length);
360144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ incq(index);
360244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(not_equal, &loop_3);  // Loop while (index < 0).
360344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
360444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&done);
360544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(rax, result_operand);
360644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
360744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&return_result);
360844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Drop temp values from the stack, and restore context register.
360944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ addq(rsp, Immediate(3 * kPointerSize));
361044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
361144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  context()->Plug(rax);
36128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
36138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
36148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3615d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
3616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<String> name = expr->name();
3617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (name->length() > 0 && name->Get(0) == '_') {
3618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ InlineRuntimeCall");
3619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitInlineRuntimeCall(expr);
3620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
36233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ CallRuntime");
36243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* args = expr->arguments();
36253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
3627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Prepare for calling JS runtime function.
36288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ movq(rax, GlobalObjectOperand());
3629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
3630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
36313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
36323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Push the arguments ("left-to-right").
36333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
36343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
36350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
3636d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
3639402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Call the JS runtime function using a call IC.
3640402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ Move(rcx, expr->name());
3641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
364244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Code> ic =
3643589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
36443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ call(ic, mode, expr->id());
3645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Restore context register.
3646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3647d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
3648d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(expr->function(), arg_count);
3649d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
36500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3651d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3654d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
3656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Token::DELETE: {
3657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
3658589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Property* property = expr->expression()->AsProperty();
3659589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VariableProxy* proxy = expr->expression()->AsVariableProxy();
3660e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3661589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (property != NULL) {
3662589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        VisitForStackValue(property->obj());
3663589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        VisitForStackValue(property->key());
36643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE)
36653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ? kNonStrictMode : kStrictMode;
36663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Push(Smi::FromInt(strict_mode_flag));
366769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
366869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        context()->Plug(rax);
3669589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else if (proxy != NULL) {
3670589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Variable* var = proxy->var();
3671e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Delete of an unqualified identifier is disallowed in strict mode
3672589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // but "delete this" is allowed.
36733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(language_mode() == CLASSIC_MODE || var->is_this());
3674589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (var->IsUnallocated()) {
3675e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(GlobalObjectOperand());
3676e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ Push(var->name());
3677e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ Push(Smi::FromInt(kNonStrictMode));
3678e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3679e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(rax);
3680589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        } else if (var->IsStackAllocated() || var->IsContextSlot()) {
3681589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // Result of deleting non-global variables is false.  'this' is
3682589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // not really a variable, though we implement it as one.  The
3683589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // subexpression does not have side effects.
3684589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          context()->Plug(var->is_this());
3685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else {
3686e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Non-global variable.  Call the runtime to try to delete from the
3687e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // context where the variable was introduced.
3688e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(context_register());
3689e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ Push(var->name());
3690e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ CallRuntime(Runtime::kDeleteContextSlot, 2);
3691e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(rax);
3692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
36931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
3694e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Result of deleting non-property, non-variable reference is true.
3695e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // The subexpression may have side effects.
3696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
3697e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        context()->Plug(true);
3698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
3699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
3700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
3701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
3703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
3704e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
37050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(Heap::kUndefinedValueRootIndex);
3706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
3710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
3711e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (context()->IsEffect()) {
3712e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Unary NOT has no side effects so it's only necessary to visit the
3713e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // subexpression.  Match the optimizing compiler by not branching.
3714e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
37153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (context()->IsTest()) {
37163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        const TestContext* test = TestContext::cast(context());
37173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The labels are swapped for the recursive call.
37183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VisitForControl(expr->expression(),
37193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->false_label(),
37203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->true_label(),
37213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->fall_through());
37223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        context()->Plug(test->true_label(), test->false_label());
3723e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
37243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We handle value contexts explicitly rather than simply visiting
37253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // for control and plugging the control flow into the context,
37263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // because we need to prepare a pair of extra administrative AST ids
37273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // for the optimizing compiler.
37283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
37293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label materialize_true, materialize_false, done;
37303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VisitForControl(expr->expression(),
37313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_false,
37323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_true,
37333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_true);
37343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&materialize_true);
37353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
37363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (context()->IsAccumulatorValue()) {
37373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ LoadRoot(rax, Heap::kTrueValueRootIndex);
37383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
37393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ PushRoot(Heap::kTrueValueRootIndex);
37403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
37413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&done, Label::kNear);
37423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&materialize_false);
37433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
37443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (context()->IsAccumulatorValue()) {
37453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ LoadRoot(rax, Heap::kFalseValueRootIndex);
37463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
37473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ PushRoot(Heap::kFalseValueRootIndex);
37483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
37493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&done);
3750e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
3751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
3755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
37560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      { StackValueContext context(this);
37570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForTypeofValue(expr->expression());
37580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
3759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallRuntime(Runtime::kTypeof, 1);
37600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(rax);
3761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3762d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3764d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Token::ADD: {
3765d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Comment cmt(masm_, "[ UnaryOperation (ADD)");
37660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->expression());
3767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Label no_conversion;
37683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ JumpIfSmi(result_register(), &no_conversion);
37691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ToNumberStub convert_stub;
37701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ CallStub(&convert_stub);
3771d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ bind(&no_conversion);
37720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(result_register());
3773d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      break;
3774d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3775d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::SUB:
3777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
37784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
37794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::BIT_NOT:
3781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
37824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
37834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
3785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
37863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
37873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
37883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
37893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
3791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                           const char* comment) {
3792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // TODO(svenpanne): Allowing format strings in Comment would be nice here...
3793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Comment cmt(masm_, comment);
3794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
3795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  UnaryOverwriteMode overwrite =
3796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
3797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  UnaryOpStub stub(expr->op(), overwrite);
3798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // UnaryOpStub expects the argument to be in the
3799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // accumulator register rax.
3800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  VisitForAccumulatorValue(expr->expression());
3801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SetSourcePosition(expr->position());
38023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
3803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  context()->Plug(rax);
3804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3807d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3808e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Comment cmnt(masm_, "[ CountOperation");
380980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
3810e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand-sides are rewritten to have a 'throw
3812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ReferenceError' as the left-hand side.
3813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->expression()->IsValidLeftHandSide()) {
3814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->expression());
3815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Expression can only be a property, a global or a (parameter or local)
38193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot.
3820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
3821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LhsKind assign_type = VARIABLE;
3822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
3823e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In case of a property we use the uninitialized expression context
3824e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // of the key to detect a named property.
3825e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (prop != NULL) {
3826e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    assign_type =
3827e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
3828e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3829e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3830e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
3831e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
3832e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
38330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
38343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    EmitVariableLoad(expr->expression()->AsVariableProxy());
3835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
3836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
38370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (expr->is_postfix() && !context()->IsEffect()) {
3838e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Push(Smi::FromInt(0));
3839e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3840e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (assign_type == NAMED_PROPERTY) {
38410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
38427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(rax);  // Copy of receiver, needed for later store.
3843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitNamedPropertyLoad(prop);
3844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
38453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForStackValue(prop->obj());
38463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForAccumulatorValue(prop->key());
38477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ movq(rdx, Operand(rsp, 0));  // Leave receiver on stack
38487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(rax);  // Copy of key, needed for later store.
3849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitKeyedPropertyLoad(prop);
3850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3851e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3852e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3853086aeeaae12517475c22695a200be45495516549Ben Murdoch  // We need a second deoptimization point after loading the value
3854086aeeaae12517475c22695a200be45495516549Ben Murdoch  // in case evaluating the property load my have a side effect.
38558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (assign_type == VARIABLE) {
38568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    PrepareForBailout(expr->expression(), TOS_REG);
38578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
38588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    PrepareForBailoutForId(expr->CountId(), TOS_REG);
38598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
3860086aeeaae12517475c22695a200be45495516549Ben Murdoch
3861d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Call ToNumber only if operand is not a smi.
3862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label no_conversion;
38633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(rax, &no_conversion, Label::kNear);
38641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ToNumberStub convert_stub;
38651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ CallStub(&convert_stub);
3866d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&no_conversion);
3867e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3868e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
3869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
38700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (!context()->IsEffect()) {
38710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Save the result on the stack. If we have a named or keyed property
38720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // we store the result under the receiver that is currently on top
38730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // of the stack.
38740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
38750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
38760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ push(rax);
38770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
38780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
38790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ movq(Operand(rsp, kPointerSize), rax);
38800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
38810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
38820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ movq(Operand(rsp, 2 * kPointerSize), rax);
38830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
38840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
3885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3886e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3887e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3888d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Inline smi case if we are in a loop.
3889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done, stub_call;
38901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  JumpPatchSite patch_site(masm_);
38911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
389280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (ShouldInlineSmiCase(expr->op())) {
3893d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
3894d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiAddConstant(rax, rax, Smi::FromInt(1));
3895d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
3896d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiSubConstant(rax, rax, Smi::FromInt(1));
3897d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(overflow, &stub_call, Label::kNear);
3899d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // We could eliminate this smi check if we split the code at
3900d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // the first smi check before calling ToNumber.
3901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    patch_site.EmitJumpIfSmi(rax, &done, Label::kNear);
39021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3903d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ bind(&stub_call);
3904d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Call stub. Undo operation first.
3905d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
3906d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiSubConstant(rax, rax, Smi::FromInt(1));
3907d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
3908d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ SmiAddConstant(rax, rax, Smi::FromInt(1));
3909d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3910d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
3911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Record position before stub call.
3913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
3914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call stub for +1/-1.
3916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
39171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (expr->op() == Token::INC) {
39181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Move(rdx, Smi::FromInt(1));
39191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
39201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ movq(rdx, rax);
39211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Move(rax, Smi::FromInt(1));
39221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
39233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId());
39243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
3925d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
3926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in rax.
3928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
3929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case VARIABLE:
3930e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
3931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
39320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        { EffectContext context(this);
39330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
39340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                 Token::ASSIGN);
3935086aeeaae12517475c22695a200be45495516549Ben Murdoch          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          context.Plug(rax);
39370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        }
3938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // For all contexts except kEffect: We have the result on
3939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
39400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
39410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3943e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
3944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
3945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
39460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                               Token::ASSIGN);
3947086aeeaae12517475c22695a200be45495516549Ben Murdoch        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        context()->Plug(rax);
3949e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3950e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
3951e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
3952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Move(rcx, prop->key()->AsLiteral()->handle());
39534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ pop(rdx);
39543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> ic = is_classic_mode()
39553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? isolate()->builtins()->StoreIC_Initialize()
39563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          : isolate()->builtins()->StoreIC_Initialize_Strict();
39573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ call(ic, RelocInfo::CODE_TARGET, expr->id());
3958086aeeaae12517475c22695a200be45495516549Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
39600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
39610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3962e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3963e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
39640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(rax);
3965e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3966e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
3967e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3968e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
3969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(rcx);
3970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(rdx);
39713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> ic = is_classic_mode()
39723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? isolate()->builtins()->KeyedStoreIC_Initialize()
39733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
39743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ call(ic, RelocInfo::CODE_TARGET, expr->id());
3975086aeeaae12517475c22695a200be45495516549Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
39770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
39780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3979e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3980e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
39810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(rax);
3982e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
3984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3985e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3986e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3987e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3988d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
39890d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
399080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  VariableProxy* proxy = expr->AsVariableProxy();
39910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!context()->IsEffect());
39920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!context()->IsTest());
39930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3994589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (proxy != NULL && proxy->var()->IsUnallocated()) {
399580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Comment cmnt(masm_, "Global variable");
399680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ Move(rcx, proxy->name());
39978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ movq(rax, GlobalObjectOperand());
399844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
399980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Use a regular load, not a contextual load, to avoid a reference
400080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // error.
40013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ call(ic);
4002086aeeaae12517475c22695a200be45495516549Ben Murdoch    PrepareForBailout(expr, TOS_REG);
40030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
4004589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
400559151504615d929945dc59db37bf1166937748c6Steve Block    Label done, slow;
400659151504615d929945dc59db37bf1166937748c6Steve Block
400759151504615d929945dc59db37bf1166937748c6Steve Block    // Generate code for loading from variables potentially shadowed
400859151504615d929945dc59db37bf1166937748c6Steve Block    // by eval-introduced variables.
4009589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
401059151504615d929945dc59db37bf1166937748c6Steve Block
401159151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
401280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(rsi);
401380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ Push(proxy->name());
401480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
4015086aeeaae12517475c22695a200be45495516549Ben Murdoch    PrepareForBailout(expr, TOS_REG);
401659151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&done);
401759151504615d929945dc59db37bf1166937748c6Steve Block
40180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
4019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
402080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // This expression cannot throw a reference error at the top level.
40213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitInDuplicateContext(expr);
402280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
402380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
402480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
402580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
40263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
40273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Expression* sub_expr,
40283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Handle<String> check) {
40293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label materialize_true, materialize_false;
40303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* if_true = NULL;
40313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* if_false = NULL;
40323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* fall_through = NULL;
40333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
40343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         &if_true, &if_false, &fall_through);
40353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  { AccumulatorValueContext context(this);
40373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForTypeofValue(sub_expr);
40380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
40393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
40400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
404144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (check->Equals(isolate()->heap()->number_symbol())) {
4042e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(rax, if_true);
404380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
404480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
404580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
404644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (check->Equals(isolate()->heap()->string_symbol())) {
4047e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(rax, if_false);
404880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
4049e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
4050e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ j(above_equal, if_false);
405180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
405280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen             Immediate(1 << Map::kIsUndetectable));
4053e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(zero, if_true, if_false, fall_through);
405444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (check->Equals(isolate()->heap()->boolean_symbol())) {
405580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
4056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
405780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kFalseValueRootIndex);
405880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
405969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  } else if (FLAG_harmony_typeof &&
406069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch             check->Equals(isolate()->heap()->null_symbol())) {
406169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ CompareRoot(rax, Heap::kNullValueRootIndex);
406269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Split(equal, if_true, if_false, fall_through);
406344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (check->Equals(isolate()->heap()->undefined_symbol())) {
406480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
4065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
4066e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(rax, if_false);
406780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => true.
406880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
406980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
407080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen             Immediate(1 << Map::kIsUndetectable));
407180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(not_zero, if_true, if_false, fall_through);
407244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (check->Equals(isolate()->heap()->function_symbol())) {
4073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(rax, if_false);
40743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
40753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx);
40763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(equal, if_true);
40773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE);
40783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Split(equal, if_true, if_false, fall_through);
407944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (check->Equals(isolate()->heap()->object_symbol())) {
4080e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(rax, if_false);
408169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (!FLAG_harmony_typeof) {
408269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ CompareRoot(rax, Heap::kNullValueRootIndex);
408369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ j(equal, if_true);
408469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
40853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ CmpObjectType(rax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, rdx);
4086e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ j(below, if_false);
40873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
40883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ j(above, if_false);
408980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
409080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
4091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke             Immediate(1 << Map::kIsUndetectable));
4092e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(zero, if_true, if_false, fall_through);
409380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
409480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (if_false != fall_through) __ jmp(if_false);
4095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
40963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->Plug(if_true, if_false);
4097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
4098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4100d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4101d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
410280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
4103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
41043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First we try a fast inlined version of the compare when one of
41053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the operands is a literal.
41063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (TryLiteralCompare(expr)) return;
41073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
4109e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
4110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
4111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
4112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
411380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
41140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
41150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
411680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
41173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Token::Value op = expr->op();
41180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->left());
411980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
4120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
41210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
4122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
41233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
4124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CompareRoot(rax, Heap::kTrueValueRootIndex);
412580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(equal, if_true, if_false, fall_through);
4126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
41273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
41290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
4130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      InstanceofStub stub(InstanceofStub::kNoFlags);
4131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
41323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ testq(rax, rax);
413480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen       // The stub returns 0 for true.
413580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(zero, if_true, if_false, fall_through);
4136d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
41400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->right());
4141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Condition cc = no_condition;
414280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      switch (op) {
4143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::EQ_STRICT:
414480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        case Token::EQ:
4145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = equal;
4146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LT:
4148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
4149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GT:
41513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          cc = greater;
4152d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block         break;
4153d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LTE:
41543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          cc = less_equal;
4155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GTE:
4157d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
4158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::IN:
4160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::INSTANCEOF:
4161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default:
4162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
4163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
41643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(rdx);
4165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
41660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      bool inline_smi_code = ShouldInlineSmiCase(op);
41671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      JumpPatchSite patch_site(masm_);
41680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (inline_smi_code) {
4169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Label slow_case;
41701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ movq(rcx, rdx);
41711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ or_(rcx, rax);
4172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
41731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ cmpq(rdx, rax);
417480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Split(cc, if_true, if_false, NULL);
417580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&slow_case);
417680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
4177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
41781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Record position and call the compare IC.
41791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      SetSourcePosition(expr->position());
41801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Handle<Code> ic = CompareIC::GetUninitialized(op);
41813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ call(ic, RelocInfo::CODE_TARGET, expr->id());
41823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      patch_site.EmitPatchInfo();
4183086aeeaae12517475c22695a200be45495516549Ben Murdoch
41843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ testq(rax, rax);
418680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(cc, if_true, if_false, fall_through);
4187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
41883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
41893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
4191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
41920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
4193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
41963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
41973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              Expression* sub_expr,
41983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              NilValue nil) {
419980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
420080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
420180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
420280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
42030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
42040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
420580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
42063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitForAccumulatorValue(sub_expr);
42073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
42083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Heap::RootListIndex nil_value = nil == kNullValue ?
42093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Heap::kNullValueRootIndex :
42103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Heap::kUndefinedValueRootIndex;
42113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareRoot(rax, nil_value);
42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expr->op() == Token::EQ_STRICT) {
421380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
421480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
42153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Heap::RootListIndex other_nil_value = nil == kNullValue ?
42163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Heap::kUndefinedValueRootIndex :
42173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Heap::kNullValueRootIndex;
421880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_true);
42193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(rax, other_nil_value);
422080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_true);
42213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(rax, if_false);
422280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // It can be an undetectable object.
422380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
422480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
422580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen             Immediate(1 << Map::kIsUndetectable));
422680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(not_zero, if_true, if_false, fall_through);
422780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
42280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
422980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
423080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
423180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
4232d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
42340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
4235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
42380d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() {
42390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return rax;
42400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
42430d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() {
42440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return rsi;
42450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
42460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
42470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4248d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(IsAligned(frame_offset, kPointerSize));
4250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movq(Operand(rbp, frame_offset), value);
42513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
42523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
42533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4254d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
425559151504615d929945dc59db37bf1166937748c6Steve Block  __ movq(dst, ContextOperand(rsi, context_index));
4256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
42593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
42603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Scope* declaration_scope = scope()->DeclarationScope();
42613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (declaration_scope->is_global_scope()) {
42623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Contexts nested in the global context have a canonical empty function
42633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // as their closure, not the anonymous closure containing the global
42643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // code.  Pass a smi sentinel and let the runtime look up the empty
42653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // function.
42663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ Push(Smi::FromInt(0));
42673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else if (declaration_scope->is_eval_scope()) {
42683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Contexts created by a call to eval have the same closure as the
42693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // context calling eval, not the anonymous closure containing the eval
42703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // code.  Fetch it from the context.
42713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ push(ContextOperand(rsi, Context::CLOSURE_INDEX));
42723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
42733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(declaration_scope->is_function_scope());
42743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
42753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
42763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
42773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
42783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ----------------------------------------------------------------------------
4280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support.
4281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4283d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() {
4284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rdx));
4285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rcx));
4286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Cook return address on top of stack (smi encoded Code* delta)
42873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ pop(rdx);
4288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, masm_->CodeObject());
4289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ subq(rdx, rcx);
4290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Integer32ToSmi(rdx, rdx);
42913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ push(rdx);
4292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store result register while executing finally block.
4293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
4294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4297d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() {
4298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rdx));
4299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(rcx));
4300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(result_register());
4301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Uncook return address.
43023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ pop(rdx);
4303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ SmiToInteger32(rdx, rdx);
4304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, masm_->CodeObject());
4305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ addq(rdx, rcx);
43063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(rdx);
4307d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
4308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef __
4311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
431269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#define __ ACCESS_MASM(masm())
431369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
431469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochFullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
431569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int* stack_depth,
431669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int* context_length) {
431769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // The macros used here must preserve the result register.
431869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
431969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Because the handler block contains the context of the finally
432069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // code, we can restore it directly from there for the finally code
432169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // rather than iteratively unwinding contexts via their previous
432269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // links.
432369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ Drop(*stack_depth);  // Down to the handler block.
432469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (*context_length > 0) {
432569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Restore the context to its dedicated register and the stack.
432669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ movq(rsi, Operand(rsp, StackHandlerConstants::kContextOffset));
432769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
432869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
432969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ PopTryHandler();
433069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ call(finally_entry_);
433169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
433269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  *stack_depth = 0;
433369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  *context_length = 0;
433469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return previous_;
433569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
433669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
433769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
433869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#undef __
4339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
43403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} }  // namespace v8::internal
4341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
4343