13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X64
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler.h"
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/debug.h"
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/full-codegen.h"
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h"
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/isolate-inl.h"
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/parser.h"
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/scopes.h"
193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 {
213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal {
223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_)
243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass JumpPatchSite BASE_EMBEDDED {
271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
28589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    info_emitted_ = false;
311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ~JumpPatchSite() {
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(patch_site_.is_bound() == info_emitted_);
361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
38257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitJumpIfNotSmi(Register reg,
39257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        Label* target,
40257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        Label::Distance near_jump = Label::kFar) {
411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ testb(reg, Immediate(kSmiTagMask));
42257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EmitJump(not_carry, target, near_jump);   // Always taken before patched.
431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
45257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitJumpIfSmi(Register reg,
46257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     Label* target,
47257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     Label::Distance near_jump = Label::kFar) {
481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ testb(reg, Immediate(kSmiTagMask));
49257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EmitJump(carry, target, near_jump);  // Never taken before patched.
501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EmitPatchInfo() {
533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (patch_site_.is_bound()) {
543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(is_uint8(delta_to_patch_site));
563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ testl(rax, Immediate(delta_to_patch_site));
571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      info_emitted_ = true;
591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ nop();  // Signals no inlined code.
623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // jc will be patched with jz, jnc will become jnz.
67257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitJump(Condition cc, Label* target, Label::Distance near_jump) {
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!patch_site_.is_bound() && !info_emitted_);
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(cc == carry || cc == not_carry);
701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&patch_site_);
71257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(cc, target, near_jump);
721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  MacroAssembler* masm_;
751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Label patch_site_;
761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool info_emitted_;
781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function.  On entry to the function the receiver
833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, with the
843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them.  The actual argument count matches the
853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function.
863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are:
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   o rdi: the JS function object being called (i.e. ourselves)
893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rsi: our context
903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rbp: our caller's frame pointer
913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rsp: stack pointer (pointing to return address)
923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame.  Please see JavaScriptFrameConstants in
943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-x64.h for its layout.
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::Generate() {
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompilationInfo* info = info_;
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  handler_table_ =
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  profiling_counter_ = isolate()->factory()->NewCell(
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
1023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  SetFunctionPosition(function());
1036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comment cmnt(masm_, "[ function compiled by full code generator");
1043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProfileEntryHookStub::MaybeCallEntryHook(masm_);
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
107f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG
108f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (strlen(FLAG_stop_at) > 0 &&
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
110f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ int3();
111f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
112f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif
113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Sloppy mode functions and builtins need to replace the receiver with the
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // global proxy when called as functions (without an explicit receiver
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object).
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (info->strict_mode() == SLOPPY && !info->is_native()) {
118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label ok;
119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // +1 for return address.
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    StackArgumentsAccessor args(rsp, info->scope()->num_parameters());
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rcx, args.GetReceiverOperand());
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, &ok, Label::kNear);
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rcx, GlobalObjectOperand());
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalProxyOffset));
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(args.GetReceiverOperand(), rcx);
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&ok);
132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Open a frame scope to indicate that there is a frame on the stack.  The
1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // MANUAL indicates that the scope shouldn't actually generate code to set up
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the frame (that is done below).
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameScope frame_scope(masm_, StackFrame::MANUAL);
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info->set_prologue_offset(masm_->pc_offset());
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Prologue(info->IsCodePreAgingActive());
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info->AddNoFrameRange(0, masm_->pc_offset());
142756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
143756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  { Comment cmnt(masm_, "[ Allocate locals");
1443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int locals_count = info->scope()->num_stack_slots();
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Generators allocate locals, if any, in context slots.
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!info->function()->is_generator() || locals_count == 0);
147756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (locals_count == 1) {
148756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ PushRoot(Heap::kUndefinedValueRootIndex);
149756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else if (locals_count > 1) {
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (locals_count >= 128) {
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label ok;
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(rcx, rsp);
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ subp(rcx, Immediate(locals_count * kPointerSize));
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ CompareRoot(rcx, Heap::kRealStackLimitRootIndex);
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ j(above_equal, &ok, Label::kNear);
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ bind(&ok);
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
159756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const int kMaxPushes = 32;
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (locals_count >= kMaxPushes) {
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int loop_iterations = locals_count / kMaxPushes;
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(rcx, Immediate(loop_iterations));
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label loop_header;
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ bind(&loop_header);
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Do pushes.
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        for (int i = 0; i < kMaxPushes; i++) {
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Push(rdx);
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Continue loop if not done.
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ decp(rcx);
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ j(not_zero, &loop_header, Label::kNear);
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int remaining = locals_count % kMaxPushes;
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Emit the remaining pushes.
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (int i  = 0; i < remaining; i++) {
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Push(rdx);
178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
180756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
182756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  bool function_in_register = true;
1834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
184756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate a local context.
1853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
186756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (heap_slots > 0) {
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment cmnt(masm_, "[ Allocate context");
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool need_write_barrier = true;
189756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Argument to NewContext is the function, which is still in rdi.
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rdi);
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(info->scope()->GetScopeInfo());
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kNewGlobalContext, 2);
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FastNewContextStub stub(isolate(), heap_slots);
196756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ CallStub(&stub);
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Result of FastNewContextStub is always in new space.
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      need_write_barrier = false;
199756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rdi);
2013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ CallRuntime(Runtime::kNewFunctionContext, 1);
202756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
203756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    function_in_register = false;
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Context is returned in rax.  It replaces the context passed to us.
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // It's saved in the stack and kept live in rsi.
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rsi, rax);
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax);
208756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
209756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Copy any necessary parameters into the context.
2103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int num_parameters = info->scope()->num_parameters();
211756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (int i = 0; i < num_parameters; i++) {
212589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Variable* var = scope()->parameter(i);
213589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (var->IsContextSlot()) {
214756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
215756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick            (num_parameters - 1 - i) * kPointerSize;
216756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Load parameter from stack.
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(rax, Operand(rbp, parameter_offset));
218756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Store it in the context.
219589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        int context_offset = Context::SlotOffset(var->index());
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(Operand(rsi, context_offset), rax);
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Update the write barrier.  This clobbers rax and rbx.
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (need_write_barrier) {
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ RecordWriteContextSlot(
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              rsi, context_offset, rax, rbx, kDontSaveFPRegs);
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (FLAG_debug_code) {
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Label done;
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ JumpIfInNewSpace(rsi, rax, &done, Label::kNear);
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Abort(kExpectedNewSpaceObject);
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ bind(&done);
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
233756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
2343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
235756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate an arguments object.
2360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Variable* arguments = scope()->arguments();
237756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (arguments != NULL) {
238756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Arguments object must be allocated after the context object, in
239756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // case the "arguments" or ".arguments" variables are in the context.
240756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate arguments object");
241756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (function_in_register) {
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rdi);
243756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
246756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The receiver is just before the parameters on the caller's stack.
2473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int num_parameters = info->scope()->num_parameters();
2483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int offset = num_parameters * kPointerSize;
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ leap(rdx,
250756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rdx);
2523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ Push(Smi::FromInt(num_parameters));
253756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Arguments to ArgumentsAccessStub:
254756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    //   function, receiver address, parameter count.
255756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The stub will rewrite receiver and parameter count if the previous
256756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // stack frame was an arguments adapter frame.
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ArgumentsAccessStub::Type type;
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (strict_mode() == STRICT) {
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      type = ArgumentsAccessStub::NEW_STRICT;
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (function()->has_duplicate_parameters()) {
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ArgumentsAccessStub stub(isolate(), type);
266756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
26744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
268589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SetVar(arguments, rax, rbx, rdx);
269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace) {
272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ CallRuntime(Runtime::kTraceEnter, 0);
273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Visit the declarations and body unless there is an illegal
276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // redeclaration.
277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (scope()->HasIllegalRedeclaration()) {
278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Comment cmnt(masm_, "[ Declarations");
279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    scope()->VisitIllegalRedeclaration(this);
280589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    { Comment cmnt(masm_, "[ Declarations");
284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // For named function expressions, declare the function name as a
285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // constant.
286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (scope()->is_function_scope() && scope()->function() != NULL) {
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VariableDeclaration* function = scope()->function();
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(function->proxy()->var()->mode() == CONST ||
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               function->proxy()->var()->mode() == CONST_LEGACY);
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED);
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitVariableDeclaration(function);
292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      VisitDeclarations(scope()->declarations());
294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    { Comment cmnt(masm_, "[ Stack check");
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Label ok;
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       __ j(above_equal, &ok, Label::kNear);
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET);
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       __ bind(&ok);
303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    { Comment cmnt(masm_, "[ Body");
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(loop_depth() == 0);
307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      VisitStatements(function()->body());
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(loop_depth() == 0);
309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
3103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
3113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Always emit a 'return undefined' in case control fell off the end of
313e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the body.
3143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
3153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
3167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    EmitReturnSequence();
317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
320d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
321db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdochvoid FullCodeGenerator::ClearAccumulator() {
3229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ Set(rax, 0);
323db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch}
324db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
325db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset),
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    Smi::FromInt(-delta));
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitProfilingCounterReset() {
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int reset_value = FLAG_interrupt_budget;
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(kScratchRegister, Smi::FromInt(reset_value));
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister);
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kJnsOffset = kPointerSize == kInt64Size ? 0x1d : 0x14;
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Label* back_edge_target) {
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ Back edge bookkeeping");
347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label ok;
348e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(back_edge_target->is_bound());
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int weight = Min(kMaxBackEdgeWeight,
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Max(1, distance / kCodeSizeMultiplier));
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitProfilingCounterDecrement(weight);
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(positive, &ok, Label::kNear);
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PredictableCodeSizeScope predictible_code_size_scope(masm_, kJnsOffset);
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DontEmitDebugCodeScope dont_emit_debug_code_scope(masm_);
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Record a mapping of this PC offset to the OSR id.  This is used to find
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the AST id from the unoptimized code in order to use it as a key into
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the deoptimization input data found in the optimized code.
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordBackEdge(stmt->OsrEntryId());
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitProfilingCounterReset();
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&ok);
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
371086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Record a mapping of the OSR id to this PC.  This is used if the OSR
372086aeeaae12517475c22695a200be45495516549Ben Murdoch  // entry becomes the target of a bailout.  We don't expect it to be, but
373086aeeaae12517475c22695a200be45495516549Ben Murdoch  // we want it to work if it is.
374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() {
379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ jmp(&return_label_);
382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
3843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rax);
3863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ CallRuntime(Runtime::kTraceExit, 1);
3873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Pretend that the exit is a backwards jump to the entry.
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int weight = 1;
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (info_->ShouldSelfOptimize()) {
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      weight = FLAG_interrupt_budget / FLAG_self_opt_count;
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int distance = masm_->pc_offset();
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      weight = Min(kMaxBackEdgeWeight,
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Max(1, distance / kCodeSizeMultiplier));
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitProfilingCounterDecrement(weight);
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(positive, &ok, Label::kNear);
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rax);
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ call(isolate()->builtins()->InterruptCheck(),
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            RelocInfo::CODE_TARGET);
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pop(rax);
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitProfilingCounterReset();
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&ok);
406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG
407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Add a label for checking the size of the code used for returning.
408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Label check_exit_codesize;
409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    masm_->bind(&check_exit_codesize);
410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
411bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
4123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ RecordJSReturn();
4133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Do not use the leave instruction here because it is too short to
4143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // patch with the code required by the debugger.
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rsp, rbp);
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ popq(rbp);
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int no_frame_start = masm_->pc_offset();
4181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize;
4201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Ret(arguments_bytes, rcx);
4211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Add padding that will be overwritten by a debugger breakpoint.  We
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // have just generated at least 7 bytes: "movp rsp, rbp; pop rbp; ret k"
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // (3 + 1 + 3) for x64 and at least 6 (2 + 1 + 3) bytes for x32.
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const int kPadding = Assembler::kJSReturnSequenceLength -
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         kPointerSize == kInt64Size ? 7 : 6;
4273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    for (int i = 0; i < kPadding; ++i) {
4283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      masm_->int3();
4293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
4301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check that the size of the code used for returning is large enough
4311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // for the debugger's requirements.
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(Assembler::kJSReturnSequenceLength <=
4331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
4363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
4373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
4383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
440589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EffectContext::Plug(Variable* var) const {
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
4420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
445589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
447589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  codegen()->GetVar(result_register(), var);
4480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
451589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
453589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand operand = codegen()->VarOperand(var, result_register());
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(operand);
455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
458589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::TestContext::Plug(Variable* var) const {
459589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  codegen()->GetVar(result_register(), var);
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
4613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  codegen()->DoTest(this);
4620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4650d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4690d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
4700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
4710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), index);
4720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
473e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4750d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
4760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
4770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ PushRoot(index);
4780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4810d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
4860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (index == Heap::kUndefinedValueRootIndex ||
4870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kNullValueRootIndex ||
4880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kFalseValueRootIndex) {
489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (false_label_ != fall_through_) __ jmp(false_label_);
4900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (index == Heap::kTrueValueRootIndex) {
491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (true_label_ != fall_through_) __ jmp(true_label_);
4920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
4930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ LoadRoot(result_register(), index);
4943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    codegen()->DoTest(this);
495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4990d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
5000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5030d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Handle<Object> lit) const {
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (lit->IsSmi()) {
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SafeMove(result_register(), Smi::cast(*lit));
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(result_register(), lit);
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5130d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (lit->IsSmi()) {
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SafePush(Smi::cast(*lit));
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(lit);
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5220d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!lit->IsUndetectableObject());  // There are no undetectable literals.
5280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (false_label_ != fall_through_) __ jmp(false_label_);
5300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsTrue() || lit->IsJSObject()) {
531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (true_label_ != fall_through_) __ jmp(true_label_);
5320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsString()) {
5330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (String::cast(*lit)->length() == 0) {
534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (false_label_ != fall_through_) __ jmp(false_label_);
5350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ jmp(true_label_);
5370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
5380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsSmi()) {
5390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (Smi::cast(*lit)->value() == 0) {
540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (false_label_ != fall_through_) __ jmp(false_label_);
5410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ jmp(true_label_);
5430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
5440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
5450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // For simplicity we always test the accumulator register.
5460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ Move(result_register(), lit);
5473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    codegen()->DoTest(this);
548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
551d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5520d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count,
5530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                   Register reg) const {
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(count > 0);
5550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
5560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
558e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5590d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
5600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    int count,
5610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Register reg) const {
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(count > 0);
5630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
5640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
5650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5680d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count,
5690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                       Register reg) const {
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(count > 0);
5710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (count > 1) __ Drop(count - 1);
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(Operand(rsp, 0), reg);
573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5760d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count,
5770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                 Register reg) const {
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(count > 0);
5790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
5800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
5810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
5833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  codegen()->DoTest(this);
5840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5870d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
5880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            Label* materialize_false) const {
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(materialize_true == materialize_false);
5900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
5910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5940d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
5950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
5960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
59944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(result_register(), isolate()->factory()->true_value());
600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&done, Label::kNear);
6010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
60244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(result_register(), isolate()->factory()->false_value());
6030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6070d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
6080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
6090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
6110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
61244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Push(isolate()->factory()->true_value());
613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&done, Label::kNear);
6140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
61544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Push(isolate()->factory()->false_value());
6160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
6170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6200d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true,
6210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                          Label* materialize_false) const {
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(materialize_true == true_label_);
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(materialize_false == false_label_);
6240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6270d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const {
6280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6310d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
6320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
6330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
6340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), value_root_index);
6350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6380d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const {
6390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
6400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
6410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ PushRoot(value_root_index);
6420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6450d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const {
6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
647086aeeaae12517475c22695a200be45495516549Ben Murdoch                                          true,
648086aeeaae12517475c22695a200be45495516549Ben Murdoch                                          true_label_,
649086aeeaae12517475c22695a200be45495516549Ben Murdoch                                          false_label_);
6500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (flag) {
6510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (true_label_ != fall_through_) __ jmp(true_label_);
6520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
6530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (false_label_ != fall_through_) __ jmp(false_label_);
654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
6583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::DoTest(Expression* condition,
6593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               Label* if_true,
66080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* if_false,
66180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* fall_through) {
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(ic, condition->test_id());
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testp(result_register(), result_register());
66580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The stub returns nonzero for true.
66680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(not_zero, if_true, if_false, fall_through);
66780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
67080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::Split(Condition cc,
67180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_true,
67280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_false,
67380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* fall_through) {
67480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (if_false == fall_through) {
67580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(cc, if_true);
67680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (if_true == fall_through) {
67780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(NegateCondition(cc), if_false);
67880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
67980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(cc, if_true);
68080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ jmp(if_false);
681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
685589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) {
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsStackAllocated());
687589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Offset is negative because higher indexes are at lower addresses.
688589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int offset = -var->index() * kPointerSize;
689589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Adjust by a (parameter or local) base offset.
690589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsParameter()) {
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    offset += kFPOnStackSize + kPCOnStackSize +
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              (info_->scope()->num_parameters() - 1) * kPointerSize;
693589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else {
694589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    offset += JavaScriptFrameConstants::kLocal0Offset;
695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
696589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return Operand(rbp, offset);
697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
700589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
702589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsContextSlot()) {
703589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    int context_chain_length = scope()->ContextChainLength(var->scope());
704589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ LoadContext(scratch, context_chain_length);
705589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return ContextOperand(scratch, var->index());
706589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else {
707589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return StackOperand(var);
708589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
709e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
711e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
712589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) {
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
714589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand location = VarOperand(var, dest);
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(dest, location);
716589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
717589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
718589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
719589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::SetVar(Variable* var,
720589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register src,
721589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register scratch0,
722589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register scratch1) {
723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch0.is(src));
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch0.is(scratch1));
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch1.is(src));
727589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand location = VarOperand(var, scratch0);
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(location, src);
7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
731589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsContextSlot()) {
732589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    int offset = Context::SlotOffset(var->index());
7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     bool should_normalize,
740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_true,
741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_false) {
742086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Only prepare for bailouts before splits if we're in a test
743086aeeaae12517475c22695a200be45495516549Ben Murdoch  // context. Otherwise, we let the Visit function deal with the
744086aeeaae12517475c22695a200be45495516549Ben Murdoch  // preparation to avoid preparing with the same AST id twice.
745086aeeaae12517475c22695a200be45495516549Ben Murdoch  if (!context()->IsTest() || !info_->IsOptimizable()) return;
746086aeeaae12517475c22695a200be45495516549Ben Murdoch
747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label skip;
748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (should_normalize) __ jmp(&skip, Label::kNear);
7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailout(expr, TOS_REG);
750086aeeaae12517475c22695a200be45495516549Ben Murdoch  if (should_normalize) {
751086aeeaae12517475c22695a200be45495516549Ben Murdoch    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
752086aeeaae12517475c22695a200be45495516549Ben Murdoch    Split(equal, if_true, if_false, NULL);
753086aeeaae12517475c22695a200be45495516549Ben Murdoch    __ bind(&skip);
754086aeeaae12517475c22695a200be45495516549Ben Murdoch  }
755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The variable in the declaration always resides in the current context.
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, scope()->ContextChainLength(variable->scope()));
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (generate_debug_code_) {
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check that we're not inside a with or catch context.
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rbx, FieldOperand(rsi, HeapObject::kMapOffset));
764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(rbx, Heap::kWithContextMapRootIndex);
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(not_equal, kDeclarationInWithContext);
766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(not_equal, kDeclarationInCatchContext);
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitVariableDeclaration(
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VariableDeclaration* declaration) {
774589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // If it was not possible to allocate the variable at compile time, we
775589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // need to "declare" it at runtime to make sure it actually exists in the
776589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // local context.
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VariableProxy* proxy = declaration->proxy();
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VariableMode mode = declaration->mode();
779589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Variable* variable = proxy->var();
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
781589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (variable->location()) {
782589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::UNALLOCATED:
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      globals_->Add(variable->name(), zone());
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      globals_->Add(variable->binding_needs_init()
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        ? isolate()->factory()->the_hole_value()
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    : isolate()->factory()->undefined_value(),
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    zone());
788589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
789589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
790589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::PARAMETER:
791589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOCAL:
792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (hole_init) {
793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment cmnt(masm_, "[ VariableDeclaration");
79469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(StackOperand(variable), kScratchRegister);
796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
79769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
799589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::CONTEXT:
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (hole_init) {
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment cmnt(masm_, "[ VariableDeclaration");
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        EmitDebugCheckDeclarationContext(variable);
80369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(ContextOperand(rsi, variable->index()), kScratchRegister);
80569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // No write barrier since the hole value is in old space.
806589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
80769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
80869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
810589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOOKUP: {
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ VariableDeclaration");
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rsi);
81369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ Push(variable->name());
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Declaration nodes are always introduced in one of four modes.
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(IsDeclaredVariableMode(mode));
8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PropertyAttributes attr =
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          IsImmutableVariableMode(mode) ? READ_ONLY : NONE;
81869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ Push(Smi::FromInt(attr));
81969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // Push initial value, if any.
82069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // Note: For variables we must not push an initial value (such as
82169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // 'undefined') because we may have a (legal) redeclaration and we
82269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // must not destroy the current value.
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (hole_init) {
82469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ PushRoot(Heap::kTheHoleValueRootIndex);
82569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      } else {
826589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ Push(Smi::FromInt(0));  // Indicates no initial value.
82769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kDeclareLookupSlot, 4);
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitFunctionDeclaration(
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FunctionDeclaration* declaration) {
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VariableProxy* proxy = declaration->proxy();
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Variable* variable = proxy->var();
839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (variable->location()) {
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::UNALLOCATED: {
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      globals_->Add(variable->name(), zone());
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<SharedFunctionInfo> function =
843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Compiler::BuildFunctionInfo(declaration->fun(), script(), info_);
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Check for stack-overflow exception.
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (function.is_null()) return SetStackOverflow();
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      globals_->Add(function, zone());
84769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::PARAMETER:
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::LOCAL: {
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ FunctionDeclaration");
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(declaration->fun());
854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(StackOperand(variable), result_register());
855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::CONTEXT: {
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ FunctionDeclaration");
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitDebugCheckDeclarationContext(variable);
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(declaration->fun());
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(ContextOperand(rsi, variable->index()), result_register());
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int offset = Context::SlotOffset(variable->index());
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // We know that we have written a function, which is not a smi.
865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ RecordWriteContextSlot(rsi,
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                offset,
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                result_register(),
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                rcx,
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                kDontSaveFPRegs,
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                EMIT_REMEMBERED_SET,
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                OMIT_SMI_CHECK);
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::LOOKUP: {
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ FunctionDeclaration");
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rsi);
879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(variable->name());
880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(Smi::FromInt(NONE));
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForStackValue(declaration->fun());
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kDeclareLookupSlot, 4);
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Variable* variable = declaration->proxy()->var();
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(variable->location() == Variable::CONTEXT);
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(variable->interface()->IsFrozen());
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ ModuleDeclaration");
895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitDebugCheckDeclarationContext(variable);
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load instance object.
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadContext(rax, scope_->ContextChainLength(scope_->GlobalScope()));
899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, ContextOperand(rax, variable->interface()->Index()));
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, ContextOperand(rax, Context::EXTENSION_INDEX));
901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Assign it.
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(ContextOperand(rsi, variable->index()), rax);
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We know that we have written a module, which is not a smi.
905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteContextSlot(rsi,
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Context::SlotOffset(variable->index()),
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            rax,
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            rcx,
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            kDontSaveFPRegs,
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            EMIT_REMEMBERED_SET,
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            OMIT_SMI_CHECK);
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS);
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Traverse into body.
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Visit(declaration->module());
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VariableProxy* proxy = declaration->proxy();
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Variable* variable = proxy->var();
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (variable->location()) {
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::UNALLOCATED:
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // TODO(rossberg)
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::CONTEXT: {
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ ImportDeclaration");
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitDebugCheckDeclarationContext(variable);
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // TODO(rossberg)
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::PARAMETER:
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::LOCAL:
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Variable::LOOKUP:
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
939d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
940d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) {
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(rossberg)
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
947d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
9483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rsi);  // The context is the first argument.
9503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(pairs);
951589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ Push(Smi::FromInt(DeclareGlobalsFlags()));
952589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ CallRuntime(Runtime::kDeclareGlobals, 3);
9533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
9543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
9553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) {
958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Call the runtime to declare the modules.
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(descriptions);
960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kDeclareModules, 1);
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return value is ignored.
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ SwitchStatement");
967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Breakable nested_statement(this, stmt);
968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
969086aeeaae12517475c22695a200be45495516549Ben Murdoch
970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Keep the switch value on the stack until a case matches.
9710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(stmt->tag());
972086aeeaae12517475c22695a200be45495516549Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<CaseClause*>* clauses = stmt->cases();
975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label next_test;  // Recycled for each test.
978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the tests with branches to their bodies.
979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
9818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    clause->body_target()->Unuse();
9821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The default is not a test, but remember it as final fall through.
984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (clause->is_default()) {
985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      default_clause = clause;
986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      continue;
987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case comparison");
990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&next_test);
991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    next_test.Unuse();
992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Compile the label expression.
9940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(clause->label());
995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
99680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Perform the comparison as if via '==='.
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdx, Operand(rsp, 0));  // Switch value.
9980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
9991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    JumpPatchSite patch_site(masm_);
10000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (inline_smi_code) {
1001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label slow_case;
1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(rcx, rdx);
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ orp(rcx, rax);
1004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
10051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmpp(rdx, rax);
100780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(not_equal, &next_test);
100880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ Drop(1);  // Switch value is no longer needed.
10098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      __ jmp(clause->body_target());
101080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&slow_case);
101180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Record position before stub call for type feedback.
10141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    SetSourcePosition(clause->position());
1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Code> ic =
1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallIC(ic, clause->CompareId());
10183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    patch_site.EmitPatchInfo();
10191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label skip;
1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&skip, Label::kNear);
1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrepareForBailout(clause, TOS_REG);
1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, &next_test);
1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Drop(1);
1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(clause->body_target());
1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&skip);
1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ testp(rax, rax);
1030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(not_equal, &next_test);
1031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
10328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ jmp(clause->body_target());
1033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Discard the test value and jump to the default if present, otherwise to
1036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the end of the statement.
1037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&next_test);
1038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(1);  // Switch value is no longer needed.
1039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (default_clause == NULL) {
104069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ jmp(nested_statement.break_label());
1041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
10428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ jmp(default_clause->body_target());
1043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the case bodies.
1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
1047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case body");
1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
10498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ bind(clause->body_target());
105044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitStatements(clause->statements());
1052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
105469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(nested_statement.break_label());
1055086aeeaae12517475c22695a200be45495516549Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ ForInStatement");
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int slot = stmt->ForInFeedbackSlot();
1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
1063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label loop, exit;
1065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ForIn loop_statement(this, stmt);
1066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  increment_loop_depth();
1067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the object to enumerate over. If the object is null or undefined, skip
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // over the loop.  See ECMA-262 version 5, section 12.6.4.
10700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(stmt->enumerable());
1071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
1072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
1073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register null_value = rdi;
1074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ LoadRoot(null_value, Heap::kNullValueRootIndex);
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rax, null_value);
1076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
1077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
10793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the object to a JS object.
1081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label convert, done_convert;
1082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, &convert);
10833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
1084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(above_equal, &done_convert);
1085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&convert);
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);
1087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done_convert);
1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);
1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for proxies.
10923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label call_runtime;
10933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
10943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx);
10953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(below_equal, &call_runtime);
10963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1097e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check cache validity in generated code. This is a fast case for
1098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
1099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // guarantee cache validity, call the runtime system to check cache
1100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // validity or get the property names in a fixed array.
11013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckEnumCache(null_value, &call_runtime);
1102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1103e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // The enum cache is valid.  Load the map of the object being
1104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // iterated over and use the cache for the iteration.
1105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label use_cache;
1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
1107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&use_cache, Label::kNear);
1108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the set of properties to enumerate.
1110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&call_runtime);
1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);  // Duplicate the enumerable object on the stack.
1112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If we got a map from the runtime call, we can do a fast
1115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // modification check. Otherwise, we got a fixed array, and we have
1116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // to do a slow check.
1117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fixed_array;
1118f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
1119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 Heap::kMetaMapRootIndex);
1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &fixed_array);
1121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a map in register rax. Get the enumeration cache from it.
1123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&use_cache);
1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_descriptors;
1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ EnumLength(rdx, rax);
1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cmp(rdx, Smi::FromInt(0));
1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &no_descriptors);
1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadInstanceDescriptors(rax, rcx);
1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheOffset));
1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the four remaining stack slots.
1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);  // Map.
1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rcx);  // Enumeration cache.
1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rdx);  // Number of valid entries for the map in the enum cache.
1139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(Smi::FromInt(0));  // Initial index.
1140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
1141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&no_descriptors);
1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(rsp, Immediate(kPointerSize));
1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&exit);
1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a fixed array in register rax. Iterate through that.
11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label non_proxy;
1148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&fixed_array);
11493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // No need for a write barrier, we are storing a Smi in the feedback vector.
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rbx, FeedbackVector());
1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(FieldOperand(rbx, FixedArray::OffsetOfElementAt(slot)),
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          TypeFeedbackVector::MegamorphicSentinel(isolate()));
11543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(rbx, Smi::FromInt(1));  // Smi indicates slow check
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, Operand(rsp, 0 * kPointerSize));  // Get enumerated object
11563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx);
11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(above, &non_proxy);
11593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(rbx, Smi::FromInt(0));  // Zero indicates proxy
11603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&non_proxy);
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rbx);  // Smi
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);  // Array
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, FieldOperand(rax, FixedArray::kLengthOffset));
1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);  // Fixed array length (as smi).
1165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Push(Smi::FromInt(0));  // Initial index.
1166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for doing the condition check.
11683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&loop);
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, Operand(rsp, 0 * kPointerSize));  // Get the current index.
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rax, Operand(rsp, 1 * kPointerSize));  // Compare to the array length.
117269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ j(above_equal, loop_statement.break_label());
1173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the current entry of the array into register rbx.
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, Operand(rsp, 2 * kPointerSize));
1176f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2);
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, FieldOperand(rbx,
1178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.reg,
1179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.scale,
1180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            FixedArray::kHeaderSize));
1181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the expected map from the stack or a smi in the
1183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // permanent slow case into register rdx.
1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, Operand(rsp, 3 * kPointerSize));
1185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the expected map still matches that of the enumerable.
11873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If not, we may have to filter the key.
1188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label update_each;
1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, Operand(rsp, 4 * kPointerSize));
1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rdx, FieldOperand(rcx, HeapObject::kMapOffset));
1191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &update_each, Label::kNear);
1192f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
11933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For proxies, no filtering is done.
11943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
11953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rdx, Smi::FromInt(0));
11963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(equal, &update_each, Label::kNear);
11973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the entry to a string or null if it isn't a property
1199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // anymore. If the property has been removed while iterating, we
1200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // just skip it.
1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rcx);  // Enumerable.
1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rbx);  // Current entry.
1203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
120444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Cmp(rax, Smi::FromInt(0));
120569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ j(equal, loop_statement.continue_label());
1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, rax);
1207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the 'each' property or variable from the possibly filtered
1209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // entry in register rbx.
1210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&update_each);
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(result_register(), rbx);
1212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Perform the assignment as if via '='.
1213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { EffectContext context(this);
12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAssignment(stmt->each());
1215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the body of the loop.
1218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Visit(stmt->body());
1219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for going to the next element by incrementing the
1221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // index (smi) stored on top of the stack.
122269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.continue_label());
1223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1));
1224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBackEdgeBookkeeping(stmt, &loop);
1226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ jmp(&loop);
1227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Remove the pointers stored on the stack.
122969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.break_label());
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(rsp, Immediate(5 * kPointerSize));
1231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Exit and decrement the loop depth.
12333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
1235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  decrement_loop_depth();
1236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
12373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ ForOfStatement");
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetStatementPosition(stmt);
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Iteration loop_statement(this, stmt);
1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  increment_loop_depth();
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // var iterator = iterable[Symbol.iterator]();
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForEffect(stmt->assign_iterator());
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loop entry.
1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(loop_statement.continue_label());
1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // result = iterator.next()
1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForEffect(stmt->next_result());
1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // if (result.done) break;
1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label result_not_done;
1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForControl(stmt->result_done(),
1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  loop_statement.break_label(),
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &result_not_done,
1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &result_not_done);
1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&result_not_done);
1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // each = result.value
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForEffect(stmt->assign_each());
1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generate code for the body of the loop.
1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Visit(stmt->body());
1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check stack before looping.
1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(loop_statement.continue_label());
1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Exit and decrement the loop depth.
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(loop_statement.break_label());
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  decrement_loop_depth();
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
12828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                       bool pretenure) {
1283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Use the fast case closure allocation code that allocates in new
1284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // space for nested functions that don't need literals cloning. If
1285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // we're running with the --always-opt or the --prepare-always-opt
1286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // flag, we need to use the runtime function so that the new function
1287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // we are creating here gets a chance to have its code optimized and
1288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // doesn't just get a copy of the existing unoptimized code.
1289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!FLAG_always_opt &&
1290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      !FLAG_prepare_always_opt &&
129144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      !pretenure &&
1292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      scope()->is_function_scope() &&
129344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      info->num_literals() == 0) {
1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(rbx, info);
1296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
1297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rsi);
1299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Push(info);
130044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Push(pretenure
130144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            ? isolate()->factory()->true_value()
130244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            : isolate()->factory()->false_value());
13038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ CallRuntime(Runtime::kNewClosure, 3);
1304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
13050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
13063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
13073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1309d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
13103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ VariableProxy");
13113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  EmitVariableLoad(expr);
1312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cnmt(masm_, "[ SuperReference ");
1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(LoadDescriptor::ReceiverRegister(),
1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(LoadDescriptor::NameRegister(), home_object_symbol);
1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cmp(rax, isolate()->factory()->undefined_value());
1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &done);
1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kThrowNonMethodError, 0);
1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
1335589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                      TypeofState typeof_state,
1336589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                      Label* slow) {
133759151504615d929945dc59db37bf1166937748c6Steve Block  Register context = rsi;
133859151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = rdx;
133959151504615d929945dc59db37bf1166937748c6Steve Block
134059151504615d929945dc59db37bf1166937748c6Steve Block  Scope* s = scope();
134159151504615d929945dc59db37bf1166937748c6Steve Block  while (s != NULL) {
134259151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (s->calls_sloppy_eval()) {
134459151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmpp(ContextOperand(context, Context::EXTENSION_INDEX),
134659151504615d929945dc59db37bf1166937748c6Steve Block                Immediate(0));
134759151504615d929945dc59db37bf1166937748c6Steve Block        __ j(not_equal, slow);
134859151504615d929945dc59db37bf1166937748c6Steve Block      }
134959151504615d929945dc59db37bf1166937748c6Steve Block      // Load next context in chain.
1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
135159151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering rsi.
135259151504615d929945dc59db37bf1166937748c6Steve Block      context = temp;
135359151504615d929945dc59db37bf1166937748c6Steve Block    }
135459151504615d929945dc59db37bf1166937748c6Steve Block    // If no outer scope calls eval, we do not need to check more
135559151504615d929945dc59db37bf1166937748c6Steve Block    // context extensions.  If we have reached an eval scope, we check
135659151504615d929945dc59db37bf1166937748c6Steve Block    // all extensions from this point.
1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break;
135859151504615d929945dc59db37bf1166937748c6Steve Block    s = s->outer_scope();
135959151504615d929945dc59db37bf1166937748c6Steve Block  }
136059151504615d929945dc59db37bf1166937748c6Steve Block
136159151504615d929945dc59db37bf1166937748c6Steve Block  if (s != NULL && s->is_eval_scope()) {
136259151504615d929945dc59db37bf1166937748c6Steve Block    // Loop up the context chain.  There is no frame effect so it is
136359151504615d929945dc59db37bf1166937748c6Steve Block    // safe to use raw labels here.
1364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label next, fast;
136559151504615d929945dc59db37bf1166937748c6Steve Block    if (!context.is(temp)) {
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(temp, context);
136759151504615d929945dc59db37bf1166937748c6Steve Block    }
136859151504615d929945dc59db37bf1166937748c6Steve Block    // Load map for comparison into register, outside loop.
1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(kScratchRegister, Heap::kNativeContextMapRootIndex);
137059151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&next);
1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Terminate at native context.
1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpp(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset));
1373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(equal, &fast, Label::kNear);
137459151504615d929945dc59db37bf1166937748c6Steve Block    // Check that extension is NULL.
1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
137659151504615d929945dc59db37bf1166937748c6Steve Block    __ j(not_equal, slow);
137759151504615d929945dc59db37bf1166937748c6Steve Block    // Load next context in chain.
1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(temp, ContextOperand(temp, Context::PREVIOUS_INDEX));
137959151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(&next);
138059151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&fast);
138159151504615d929945dc59db37bf1166937748c6Steve Block  }
138259151504615d929945dc59db37bf1166937748c6Steve Block
138359151504615d929945dc59db37bf1166937748c6Steve Block  // All extension objects were empty and it is safe to use a global
138459151504615d929945dc59db37bf1166937748c6Steve Block  // load IC call.
1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(LoadDescriptor::NameRegister(), proxy->var()->name());
1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_vector_ics) {
1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(VectorLoadICDescriptor::SlotRegister(),
1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Smi::FromInt(proxy->VariableFeedbackSlot()));
1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? NOT_CONTEXTUAL
1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : CONTEXTUAL;
1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallLoadIC(mode);
139659151504615d929945dc59db37bf1166937748c6Steve Block}
139759151504615d929945dc59db37bf1166937748c6Steve Block
139859151504615d929945dc59db37bf1166937748c6Steve Block
1399589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1400589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                                Label* slow) {
1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsContextSlot());
140259151504615d929945dc59db37bf1166937748c6Steve Block  Register context = rsi;
140359151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = rbx;
140459151504615d929945dc59db37bf1166937748c6Steve Block
1405589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
140659151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (s->calls_sloppy_eval()) {
140859151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmpp(ContextOperand(context, Context::EXTENSION_INDEX),
141059151504615d929945dc59db37bf1166937748c6Steve Block                Immediate(0));
141159151504615d929945dc59db37bf1166937748c6Steve Block        __ j(not_equal, slow);
141259151504615d929945dc59db37bf1166937748c6Steve Block      }
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
141459151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering rsi.
141559151504615d929945dc59db37bf1166937748c6Steve Block      context = temp;
141659151504615d929945dc59db37bf1166937748c6Steve Block    }
141759151504615d929945dc59db37bf1166937748c6Steve Block  }
141859151504615d929945dc59db37bf1166937748c6Steve Block  // Check that last extension is NULL.
1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
142059151504615d929945dc59db37bf1166937748c6Steve Block  __ j(not_equal, slow);
1421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // This function is used only for loads, not stores, so it's safe to
1423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // return an rsi-based operand (the write barrier cannot be allowed to
1424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // destroy the rsi register).
1425589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return ContextOperand(context, var->index());
142659151504615d929945dc59db37bf1166937748c6Steve Block}
142759151504615d929945dc59db37bf1166937748c6Steve Block
142859151504615d929945dc59db37bf1166937748c6Steve Block
1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
1430589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                  TypeofState typeof_state,
1431589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                  Label* slow,
1432589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                  Label* done) {
143359151504615d929945dc59db37bf1166937748c6Steve Block  // Generate fast-case code for variables that might be shadowed by
143459151504615d929945dc59db37bf1166937748c6Steve Block  // eval-introduced variables.  Eval is used a lot without
143559151504615d929945dc59db37bf1166937748c6Steve Block  // introducing variables.  In those cases, we do not want to
143659151504615d929945dc59db37bf1166937748c6Steve Block  // perform a runtime call for all variables in the scope
143759151504615d929945dc59db37bf1166937748c6Steve Block  // containing the eval.
1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Variable* var = proxy->var();
14393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (var->mode() == DYNAMIC_GLOBAL) {
1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitLoadGlobalCheckExtensions(proxy, typeof_state, slow);
144159151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(done);
14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (var->mode() == DYNAMIC_LOCAL) {
1443589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Variable* local = var->local_if_not_shadowed();
1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rax, ContextSlotOperandCheckExtensions(local, slow));
1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (local->mode() == LET || local->mode() == CONST ||
1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        local->mode() == CONST_LEGACY) {
1447589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1448589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ j(not_equal, done);
1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (local->mode() == CONST_LEGACY) {
14503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {  // LET || CONST
14523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Push(var->name());
14533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CallRuntime(Runtime::kThrowReferenceError, 1);
14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
145559151504615d929945dc59db37bf1166937748c6Steve Block    }
1456589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ jmp(done);
145759151504615d929945dc59db37bf1166937748c6Steve Block  }
145859151504615d929945dc59db37bf1166937748c6Steve Block}
145959151504615d929945dc59db37bf1166937748c6Steve Block
146059151504615d929945dc59db37bf1166937748c6Steve Block
14613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
14623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Record position before possible IC call.
14633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SetSourcePosition(proxy->position());
14643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Variable* var = proxy->var();
14653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1466589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Three cases: global variables, lookup variables, and all other types of
1467589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // variables.
1468589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (var->location()) {
1469589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::UNALLOCATED: {
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ Global variable");
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(LoadDescriptor::NameRegister(), var->name());
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (FLAG_vector_ics) {
1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Move(VectorLoadICDescriptor::SlotRegister(),
1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Smi::FromInt(proxy->VariableFeedbackSlot()));
1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallLoadIC(CONTEXTUAL);
1478589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      context()->Plug(rax);
1479589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1480589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
148159151504615d929945dc59db37bf1166937748c6Steve Block
1482589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::PARAMETER:
1483589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOCAL:
1484589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::CONTEXT: {
1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot"
1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               : "[ Stack slot");
14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (var->binding_needs_init()) {
14883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // var->scope() may be NULL when the proxy is located in eval code and
14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // refers to a potential outside binding. Currently those bindings are
14903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // always looked up dynamically, i.e. in that case
14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //     var->location() == LOOKUP.
14923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // always holds.
1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(var->scope() != NULL);
14943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Check if the binding really needs an initialization check. The check
14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // can be skipped in the following situation: we have a LET or CONST
14973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // binding in harmony mode, both the Variable and the VariableProxy have
14983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // the same declaration scope (i.e. they are both in global code, in the
14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // same function or in the same eval code) and the VariableProxy is in
15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // the source physically located after the initializer of the variable.
15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We cannot skip any initialization checks for CONST in non-harmony
15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // mode because const variables may be declared but never initialized:
15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //   if (false) { const x; }; var y = x;
15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The condition on the declaration scopes is a conservative check for
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // nested functions that access a binding and are called before the
15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // binding is initialized:
15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //   function() { f(); let x = 1; function f() { x = 2; } }
15103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
15113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bool skip_init_check;
15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
15133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          skip_init_check = false;
15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Check that we always have valid source position.
1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          DCHECK(var->initializer_position() != RelocInfo::kNoPosition);
1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          DCHECK(proxy->position() != RelocInfo::kNoPosition);
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          skip_init_check = var->mode() != CONST_LEGACY &&
15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              var->initializer_position() < proxy->position();
15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!skip_init_check) {
15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Let and const need a read barrier.
15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Label done;
15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          GetVar(rax, var);
15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ j(not_equal, &done, Label::kNear);
1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (var->mode() == LET || var->mode() == CONST) {
15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // Throw a reference error when using an uninitialized let/const
15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // binding in harmony mode.
15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ Push(var->name());
15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ CallRuntime(Runtime::kThrowReferenceError, 1);
15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else {
15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // Uninitalized const bindings outside of harmony mode are unholed.
1535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            DCHECK(var->mode() == CONST_LEGACY);
15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ bind(&done);
15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          context()->Plug(rax);
15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          break;
1541589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        }
1542589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      context()->Plug(var);
1544589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1545589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
1546d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1547589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOOKUP: {
1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ Lookup slot");
1549589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Label done, slow;
1550589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Generate code for loading from variables potentially shadowed
1551589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // by eval-introduced variables.
1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
1553589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ bind(&slow);
1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rsi);  // Context.
155569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ Push(var->name());
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kLoadLookupSlot, 2);
155769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ bind(&done);
155869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      context()->Plug(rax);
1559589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
15613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
15623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
15633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1565d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1566d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ RegExpLiteral");
1567bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label materialized;
15683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Registers will be used as follows:
15693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // rdi = JS function.
1570bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // rcx = literals array.
1571bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // rbx = regexp literal.
1572bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // rax = regexp literal clone.
1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
15753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int literal_offset =
157680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, FieldOperand(rcx, literal_offset));
1578bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
1579589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ j(not_equal, &materialized, Label::kNear);
1580bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
15813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Create regexp literal using runtime function
15823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Result will be in rax.
1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rcx);
15843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(Smi::FromInt(expr->literal_index()));
15853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(expr->pattern());
15863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(expr->flags());
15873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, rax);
1589bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1590bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&materialized);
1591bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1592bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label allocated, runtime_allocate;
1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
1594bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ jmp(&allocated);
1595bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1596bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&runtime_allocate);
1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rbx);
1598bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ Push(Smi::FromInt(size));
1599bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rbx);
1601bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1602bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&allocated);
1603bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Copy the content into the newly allocated memory.
1604bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // (Unroll copy loop once for better throughput).
1605bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdx, FieldOperand(rbx, i));
1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rcx, FieldOperand(rbx, i + kPointerSize));
1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(FieldOperand(rax, i), rdx);
1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(FieldOperand(rax, i + kPointerSize), rcx);
1610bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1611bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if ((size % (2 * kPointerSize)) != 0) {
1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdx, FieldOperand(rbx, size - kPointerSize));
1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(FieldOperand(rax, size - kPointerSize), rdx);
1614bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
16150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
1616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1618d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAccessor(Expression* expression) {
16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expression == NULL) {
16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ PushRoot(Heap::kNullValueRootIndex);
16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForStackValue(expression);
16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  expr->BuildConstantProperties(isolate());
16323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> constant_properties = expr->constant_properties();
163344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int flags = expr->fast_elements()
163444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? ObjectLiteral::kFastElements
163544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : ObjectLiteral::kNoFlags;
163644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  flags |= expr->has_function()
163744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? ObjectLiteral::kHasFunction
163844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : ObjectLiteral::kNoFlags;
16393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int properties_count = constant_properties->length() / 2;
1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expr->may_store_doubles() || expr->depth() > 1 ||
1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements ||
16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(Smi::FromInt(expr->literal_index()));
1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(constant_properties);
1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(Smi::FromInt(flags));
1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rax, FieldOperand(rdi, JSFunction::kLiteralsOffset));
1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(rbx, Smi::FromInt(expr->literal_index()));
1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(rcx, constant_properties);
1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(rdx, Smi::FromInt(flags));
1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FastCloneShallowObjectStub stub(isolate(), properties_count);
16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
1657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
1660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in rax.
1661d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
1662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
16633e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Mark all computed expressions that are bound to a key that
16643e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // is shadowed by a later occurrence of the same key. For the
16653e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // marked expressions, no store code is emitted.
1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  expr->CalculateEmitStore(zone());
16673e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AccessorTable accessor_table(zone());
1669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < expr->properties()->length(); i++) {
1670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectLiteral::Property* property = expr->properties()->at(i);
1671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
1672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = property->key();
1674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
1675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rax);  // Save result on the stack
1677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
1678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1679d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
1680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::CONSTANT:
1681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        UNREACHABLE();
1682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
1684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (key->value()->IsInternalizedString()) {
16873e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          if (property->emit_store()) {
1688053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block            VisitForAccumulatorValue(value);
1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            DCHECK(StoreDescriptor::ValueRegister().is(rax));
1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ Move(StoreDescriptor::NameRegister(), key->value());
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            CallStoreIC(key->LiteralFeedbackId());
1693086aeeaae12517475c22695a200be45495516549Ben Murdoch            PrepareForBailoutForId(key->id(), NO_REGISTERS);
1694053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block          } else {
1695053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block            VisitForEffect(value);
16963e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          }
1697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Push(Operand(rsp, 0));  // Duplicate receiver.
17000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(key);
17010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(value);
17023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        if (property->emit_store()) {
1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Push(Smi::FromInt(SLOPPY));  // Strict mode
1704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ CallRuntime(Runtime::kSetProperty, 4);
17053e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        } else {
17063e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          __ Drop(3);
17073e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        }
1708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case ObjectLiteral::Property::PROTOTYPE:
1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Push(Operand(rsp, 0));  // Duplicate receiver.
1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(value);
1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (property->emit_store()) {
1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ CallRuntime(Runtime::kSetPrototype, 2);
1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Drop(2);
1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
171885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      case ObjectLiteral::Property::GETTER:
17193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        accessor_table.lookup(key)->second->getter = value;
17203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
17213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case ObjectLiteral::Property::SETTER:
17223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        accessor_table.lookup(key)->second->setter = value;
1723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
17273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Emit code to define accessors, using only a single call to the runtime for
17283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // each pair of corresponding getters and setters.
17293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (AccessorTable::Iterator it = accessor_table.begin();
17303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       it != accessor_table.end();
17313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       ++it) {
1732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(Operand(rsp, 0));  // Duplicate receiver.
17333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForStackValue(it->first);
17343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAccessor(it->second->getter);
17353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAccessor(it->second->setter);
17363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Push(Smi::FromInt(NONE));
1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
17383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
17393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
174044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (expr->has_function()) {
1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(result_saved);
1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(Operand(rsp, 0));
174344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
174444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
174544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
17470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
17490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
17503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
17513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
17523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1754d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
17553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
1756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  expr->BuildConstantElements(isolate());
1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int flags = expr->depth() == 1
1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? ArrayLiteral::kShallowElements
1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : ArrayLiteral::kNoFlags;
1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<Expression*>* subexprs = expr->values();
1763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int length = subexprs->length();
17643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> constant_elements = expr->constant_elements();
1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(2, constant_elements->length());
17663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsKind constant_elements_kind =
17673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool has_constant_fast_elements =
1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      IsFastObjectElementsKind(constant_elements_kind);
17703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArrayBase> constant_elements_values(
17713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FixedArrayBase::cast(constant_elements->get(1)));
1772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If the only customer of allocation sites is transitioning, then
1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // we can turn it off if we don't have anywhere else to transition to.
1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) {
1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(Smi::FromInt(expr->literal_index()));
1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(constant_elements);
1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(Smi::FromInt(flags));
1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
1787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rax, FieldOperand(rbx, JSFunction::kLiteralsOffset));
1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(rbx, Smi::FromInt(expr->literal_index()));
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(rcx, constant_elements);
1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
1793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
17943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
17953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
17973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
17993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
1800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < length; i++) {
18013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Expression* subexpr = subexprs->at(i);
18023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
18033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
18053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rax);  // array literal
1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(Smi::FromInt(expr->literal_index()));
18093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
18103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
18110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(subexpr);
18123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsFastObjectElementsKind(constant_elements_kind)) {
1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they
1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // cannot transition and don't need to call the runtime stub.
18163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(rbx, Operand(rsp, kPointerSize));  // Copy of array literal.
1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
18193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the subexpression value in the array's elements.
1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(FieldOperand(rbx, offset), result_register());
18213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Update the write barrier for the array store.
18223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWriteField(rbx, offset, result_register(), rcx,
18233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          kDontSaveFPRegs,
18243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          EMIT_REMEMBERED_SET,
18253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          INLINE_SMI_CHECK);
18263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
18273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the subexpression value in the array's elements.
18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Move(rcx, Smi::FromInt(i));
1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      StoreArrayLiteralElementStub stub(isolate());
18303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CallStub(&stub);
18313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1832086aeeaae12517475c22695a200be45495516549Ben Murdoch
1833086aeeaae12517475c22695a200be45495516549Ben Murdoch    PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
18343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
18353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addp(rsp, Immediate(kPointerSize));  // literal index
18380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1839e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
18400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
18413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
18423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
18433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1845402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->target()->IsValidReferenceExpression());
1847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1848402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Comment cmnt(masm_, "[ Assignment");
1849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1850402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Left-hand side can only be a property, a global or a (parameter or local)
18513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot.
1852402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1853402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LhsKind assign_type = VARIABLE;
185480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Property* property = expr->target()->AsProperty();
185580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (property != NULL) {
185680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    assign_type = (property->key()->IsPropertyName())
185780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? NAMED_PROPERTY
185880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : KEYED_PROPERTY;
1859402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1860402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1861402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate LHS expression.
1862402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1863402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1864402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Nothing to do here.
1865402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1866402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1867402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // We need the receiver both on the stack and in the register.
1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->obj());
1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
1871402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
18720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
1873402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1874402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1875086aeeaae12517475c22695a200be45495516549Ben Murdoch    case KEYED_PROPERTY: {
1876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (expr->is_compound()) {
18773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->obj());
1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->key());
1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, kPointerSize));
1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(LoadDescriptor::NameRegister(), Operand(rsp, 0));
1881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else {
18823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->obj());
18833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->key());
1884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
1885402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1886086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
1887402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1888402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
18898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // For compound assignments we need another deoptimization point after the
18908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // variable/property load.
1891402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
18920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    { AccumulatorValueContext context(this);
18930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
18940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
18953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          EmitVariableLoad(expr->target()->AsVariableProxy());
18968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          PrepareForBailout(expr->target(), TOS_REG);
18970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
18980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
18990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitNamedPropertyLoad(property);
1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          PrepareForBailoutForId(property->LoadId(), TOS_REG);
19010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
19020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
19030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitKeyedPropertyLoad(property);
1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          PrepareForBailoutForId(property->LoadId(), TOS_REG);
19050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
19060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
1907402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1908402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
190980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Token::Value op = expr->binary_op();
1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rax);  // Left operand goes on the stack.
1911e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    VisitForAccumulatorValue(expr->value());
1912402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
191380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
191480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? OVERWRITE_RIGHT
191580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : NO_OVERWRITE;
191680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    SetSourcePosition(expr->position() + 1);
19170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
191880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (ShouldInlineSmiCase(op)) {
1919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitInlineSmiBinaryOp(expr->binary_operation(),
192080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            op,
192180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            mode,
192280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            expr->target(),
1923e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                            expr->value());
192480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    } else {
1925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitBinaryOp(expr->binary_operation(), op, mode);
192680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
1927086aeeaae12517475c22695a200be45495516549Ben Murdoch    // Deoptimization point in case the binary operation may have side effects.
1928086aeeaae12517475c22695a200be45495516549Ben Murdoch    PrepareForBailout(expr->binary_operation(), TOS_REG);
192980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
19300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->value());
1931402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1932402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1933402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Record source position before possible IC call.
1934402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  SetSourcePosition(expr->position());
1935402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1936402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Store the value.
1937402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1938402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1939402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
19400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             expr->op());
1941086aeeaae12517475c22695a200be45495516549Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      context()->Plug(rax);
1943402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1944402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1945402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitNamedPropertyAssignment(expr);
1946402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1947402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1948402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitKeyedPropertyAssignment(expr);
1949402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1950402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1951402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1952402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1953402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitYield(Yield* expr) {
1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ Yield");
1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Evaluate yielded value first; the initial iterator definition depends on
1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this.  It stays on the stack while we update the iterator.
1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(expr->expression());
1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (expr->yield_kind()) {
1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Yield::kSuspend:
1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Pop value from top-of-stack slot; box result into result register.
1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitCreateIteratorResult(false);
1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(result_register());
1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Fall through.
1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Yield::kInitial: {
1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label suspend, continuation, post_runtime, resume;
1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&suspend);
1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&continuation);
1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&resume);
1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&suspend);
1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(expr->generator_object());
1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset),
1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Smi::FromInt(continuation.pos()));
1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi);
1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(rcx, rsi);
1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx,
1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          kDontSaveFPRegs);
1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ leap(rbx, Operand(rbp, StandardFrameConstants::kExpressionsOffset));
1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmpp(rsp, rbx);
1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(equal, &post_runtime);
1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rax);  // generator object
1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(context_register(),
1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Operand(rbp, StandardFrameConstants::kContextOffset));
1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&post_runtime);
1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(result_register());
1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitReturnSequence();
1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&resume);
1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context()->Plug(result_register());
1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Yield::kFinal: {
2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(expr->generator_object());
2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(FieldOperand(result_register(),
2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           JSGeneratorObject::kContinuationOffset),
2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Smi::FromInt(JSGeneratorObject::kGeneratorClosed));
2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Pop value from top-of-stack slot, box result into result register.
2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitCreateIteratorResult(true);
2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitUnwindBeforeReturn();
2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitReturnSequence();
2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Yield::kDelegating: {
2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForStackValue(expr->generator_object());
2014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Initial stack layout is as follows:
2016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // [sp + 1 * kPointerSize] iter
2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // [sp + 0 * kPointerSize] g
2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label l_catch, l_try, l_suspend, l_continuation, l_resume;
2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label l_next, l_call, l_loop;
2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register load_receiver = LoadDescriptor::ReceiverRegister();
2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register load_name = LoadDescriptor::NameRegister();
2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Initial send value is undefined.
2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&l_next);
2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_catch);
2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(load_name, Heap::kthrow_stringRootIndex);  // "throw"
2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(load_name);
2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(Operand(rsp, 2 * kPointerSize));               // iter
2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rax);                                          // exception
2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&l_call);
2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // try { received = %yield result }
2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Shuffle the received result above a try handler and yield it without
2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // re-boxing.
2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_try);
2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(rax);                                       // result
2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ PushTryHandler(StackHandler::CATCH, expr->index());
2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const int handler_size = StackHandlerConstants::kSize;
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rax);                                      // result
2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&l_suspend);
2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_continuation);
2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&l_resume);
2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_suspend);
2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const int generator_object_depth = kPointerSize + handler_size;
2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(rax, Operand(rsp, generator_object_depth));
2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rax);                                      // g
2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset),
2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Smi::FromInt(l_continuation.pos()));
2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi);
2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(rcx, rsi);
2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx,
2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          kDontSaveFPRegs);
2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(context_register(),
2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Operand(rbp, StandardFrameConstants::kContextOffset));
2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(rax);                                       // result
2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitReturnSequence();
2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_resume);                                // received in rax
2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ PopTryHandler();
2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // receiver = iter; f = 'next'; arg = received;
2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_next);
2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(load_name, Heap::knext_stringRootIndex);
2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(load_name);                           // "next"
2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(Operand(rsp, 2 * kPointerSize));      // iter
2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rax);                                 // received
2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // result = receiver[f](arg);
2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_call);
2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(load_receiver, Operand(rsp, kPointerSize));
2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (FLAG_vector_ics) {
2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Move(VectorLoadICDescriptor::SlotRegister(),
2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Smi::FromInt(expr->KeyedLoadFeedbackSlot()));
2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallIC(ic, TypeFeedbackId::None());
2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(rdi, rax);
2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(Operand(rsp, 2 * kPointerSize), rdi);
2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallStub(&stub);
2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Drop(1);  // The function is still on the stack; drop it.
2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // if (!result.done) goto l_try;
2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&l_loop);
2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(load_receiver, rax);
2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(load_receiver);                               // save result
2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(load_name, Heap::kdone_stringRootIndex);  // "done"
2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (FLAG_vector_ics) {
2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Move(VectorLoadICDescriptor::SlotRegister(),
2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Smi::FromInt(expr->DoneFeedbackSlot()));
2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallLoadIC(NOT_CONTEXTUAL);                           // rax=result.done
2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallIC(bool_ic);
2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ testp(result_register(), result_register());
2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(zero, &l_try);
2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // result.value
2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(load_receiver);                             // result
2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(load_name, Heap::kvalue_stringRootIndex);  // "value"
2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (FLAG_vector_ics) {
2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Move(VectorLoadICDescriptor::SlotRegister(),
2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Smi::FromInt(expr->ValueFeedbackSlot()));
2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallLoadIC(NOT_CONTEXTUAL);                        // result.value in rax
2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context()->DropAndPlug(2, rax);                    // drop iter and g
2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitGeneratorResume(Expression *generator,
2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Expression *value,
2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JSGeneratorObject::ResumeMode resume_mode) {
2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The value stays in rax, and is ultimately read by the resumed generator, as
2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // is read to throw the value when the resumed generator is already closed.
2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rbx will hold the generator object until the activation has been resumed.
2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(generator);
2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(value);
2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rbx);
2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check generator state.
2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label wrong_state, closed_state, done;
2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiCompare(FieldOperand(rbx, JSGeneratorObject::kContinuationOffset),
2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Smi::FromInt(0));
2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &closed_state);
2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(less, &wrong_state);
2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load suspended function and context.
2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rsi, FieldOperand(rbx, JSGeneratorObject::kContextOffset));
2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, FieldOperand(rbx, JSGeneratorObject::kFunctionOffset));
2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push receiver.
2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(FieldOperand(rbx, JSGeneratorObject::kReceiverOffset));
2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push holes for arguments to generator function.
2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
2151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadSharedFunctionInfoSpecialField(rdx, rdx,
2152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SharedFunctionInfo::kFormalParameterCountOffset);
2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(rcx, Heap::kTheHoleValueRootIndex);
2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label push_argument_holes, push_frame;
2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&push_argument_holes);
2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(rdx, Immediate(1));
2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(carry, &push_frame);
2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rcx);
2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&push_argument_holes);
2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Enter a new JavaScript frame, and initialize its slots as they were when
2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the generator was suspended.
2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label resume_frame;
2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&push_frame);
2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ call(&resume_frame);
2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done);
2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&resume_frame);
2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pushq(rbp);  // Caller's frame pointer.
2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbp, rsp);
2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rsi);  // Callee's context.
2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rdi);  // Callee's JS Function.
2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the operand stack size.
2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, FieldOperand(rbx, JSGeneratorObject::kOperandStackOffset));
2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, FieldOperand(rdx, FixedArray::kLengthOffset));
2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(rdx, rdx);
2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If we are sending a value and there is no operand stack, we can jump back
2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // in directly.
2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (resume_mode == JSGeneratorObject::NEXT) {
2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label slow_resume;
2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpp(rdx, Immediate(0));
2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_zero, &slow_resume);
2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiToInteger64(rcx,
2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        FieldOperand(rbx, JSGeneratorObject::kContinuationOffset));
2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addp(rdx, rcx);
2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(FieldOperand(rbx, JSGeneratorObject::kContinuationOffset),
2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Smi::FromInt(JSGeneratorObject::kGeneratorExecuting));
2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(rdx);
2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&slow_resume);
2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Otherwise, we push holes for the operand stack and call the runtime to fix
2195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // up the stack and the handlers.
2196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label push_operand_holes, call_resume;
2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&push_operand_holes);
2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(rdx, Immediate(1));
2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(carry, &call_resume);
2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rcx);
2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&push_operand_holes);
2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&call_resume);
2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rbx);
2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(result_register());
2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(Smi::FromInt(resume_mode));
2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3);
2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Not reached: the runtime call returns elsewhere.
2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Abort(kGeneratorFailedToResume);
2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Reach here when generator is closed.
2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&closed_state);
2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (resume_mode == JSGeneratorObject::NEXT) {
2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Return completed iterator result when generator is closed.
2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ PushRoot(Heap::kUndefinedValueRootIndex);
2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Pop value from top-of-stack slot; box result into result register.
2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitCreateIteratorResult(true);
2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Throw the provided value.
2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rax);
2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntime(Runtime::kThrow, 1);
2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done);
2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Throw error if we attempt to operate on a running generator.
2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&wrong_state);
2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rbx);
2227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kThrowGeneratorStateError, 1);
2228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(result_register());
2231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCreateIteratorResult(bool done) {
2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label gc_required;
2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label allocated;
2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Map> map(isolate()->native_context()->iterator_result_map());
2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Allocate(map->instance_size(), rax, rcx, rdx, &gc_required, TAG_OBJECT);
2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&allocated);
2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&gc_required);
2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(Smi::FromInt(map->instance_size()));
2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(context_register(),
2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Operand(rbp, StandardFrameConstants::kContextOffset));
2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&allocated);
2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rbx, map);
2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rcx);
2252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rdx, isolate()->factory()->ToBoolean(done));
2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(map->instance_size(), 5 * kPointerSize);
2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx);
2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(FieldOperand(rax, JSObject::kPropertiesOffset),
2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          isolate()->factory()->empty_fixed_array());
2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(FieldOperand(rax, JSObject::kElementsOffset),
2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          isolate()->factory()->empty_fixed_array());
2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rax, JSGeneratorObject::kResultValuePropertyOffset),
2260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          rcx);
2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rax, JSGeneratorObject::kResultDonePropertyOffset),
2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          rdx);
2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Only the value field needs a write barrier, as the other values are in the
2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // root set.
2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset,
2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      rcx, rdx, kDontSaveFPRegs);
2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2271d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
2272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
2273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Literal* key = prop->key()->AsLiteral();
2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(LoadDescriptor::NameRegister(), key->value());
2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_vector_ics) {
2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(VectorLoadICDescriptor::SlotRegister(),
2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Smi::FromInt(prop->PropertyFeedbackSlot()));
2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallLoadIC(NOT_CONTEXTUAL);
2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetSourcePosition(prop->position());
2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Literal* key = prop->key()->AsLiteral();
2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!key->value()->IsSmi());
2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(prop->IsSuperAccess());
2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SuperReference* super_ref = prop->obj()->AsSuperReference();
2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitLoadHomeObject(super_ref);
2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);
2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(super_ref->this_var());
2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(key->value());
2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kLoadFromSuper, 3);
2297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2300d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
2301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_vector_ics) {
2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(VectorLoadICDescriptor::SlotRegister(),
2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Smi::FromInt(prop->PropertyFeedbackSlot()));
2306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallIC(ic);
2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallIC(ic, prop->PropertyFeedbackId());
2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
231480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Token::Value op,
231580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              OverwriteMode mode,
231680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Expression* left,
2317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              Expression* right) {
231880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Do combined smi check of the operands. Left operand is on the
231980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // stack (popped into rdx). Right operand is in rax but moved into
232080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rcx to make the shifts easier.
2321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done, stub_call, smi_case;
2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rdx);
2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, rax);
2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ orp(rax, rdx);
23251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  JumpPatchSite patch_site(masm_);
2326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear);
232780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
232880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&stub_call);
2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, rcx);
2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code();
2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(code, expr->BinaryOperationFeedbackId());
23323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
2333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&done, Label::kNear);
233480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
233580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&smi_case);
233680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
233780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SAR:
233880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiShiftArithmeticRight(rax, rdx, rcx);
233980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
234080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHL:
2341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ SmiShiftLeft(rax, rdx, rcx, &stub_call);
234280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
234380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHR:
234480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiShiftLogicalRight(rax, rdx, rcx, &stub_call);
234580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
234680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::ADD:
234780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiAdd(rax, rdx, rcx, &stub_call);
234880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
234980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SUB:
235080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiSub(rax, rdx, rcx, &stub_call);
235180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
235280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::MUL:
235380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiMul(rax, rdx, rcx, &stub_call);
235480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
235580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_OR:
235680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiOr(rax, rdx, rcx);
235780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
235880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_AND:
235980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiAnd(rax, rdx, rcx);
236080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
236180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_XOR:
236280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiXor(rax, rdx, rcx);
236380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
236480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    default:
236580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      UNREACHABLE();
236680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
236780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
236880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
236980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&done);
23700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
237180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
237280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
237380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
2375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Token::Value op,
237680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                     OverwriteMode mode) {
2377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rdx);
2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code();
23793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(code, expr->BinaryOperationFeedbackId());
23813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
23820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
23863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr) {
2387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->IsValidReferenceExpression());
2388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand side can only be a property, a global or a (parameter or local)
23903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot.
2391f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
2392f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  LhsKind assign_type = VARIABLE;
2393f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = expr->AsProperty();
2394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (prop != NULL) {
2395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    assign_type = (prop->key()->IsPropertyName())
2396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ? NAMED_PROPERTY
2397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        : KEYED_PROPERTY;
2398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (assign_type) {
2401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case VARIABLE: {
2402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->AsVariableProxy()->var();
24030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EffectContext context(this);
24040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitVariableAssignment(var, Token::ASSIGN);
2405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case NAMED_PROPERTY: {
2408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rax);  // Preserve value.
24090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(StoreDescriptor::ReceiverRegister(), rax);
2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(StoreDescriptor::ValueRegister());  // Restore value.
2412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(StoreDescriptor::NameRegister(),
2413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              prop->key()->AsLiteral()->value());
2414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallStoreIC();
2415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case KEYED_PROPERTY: {
2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rax);  // Preserve value.
24193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForStackValue(prop->obj());
24203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForAccumulatorValue(prop->key());
2421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(StoreDescriptor::NameRegister(), rax);
2422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(StoreDescriptor::ReceiverRegister());
2423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(StoreDescriptor::ValueRegister());  // Restore value.
2424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Code> ic =
2425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code();
2426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallIC(ic);
2427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(rax);
2431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Variable* var, MemOperand location) {
2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(location, rax);
2437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (var->IsContextSlot()) {
2438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdx, rax);
2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ RecordWriteContextSlot(
2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2445d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var,
24460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                               Token::Value op) {
2447589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsUnallocated()) {
2448589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Global var, const, or let.
2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(StoreDescriptor::NameRegister(), var->name());
2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
2451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallStoreIC();
2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (op == Token::INIT_CONST_LEGACY) {
2454589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Const initializers need a write barrier.
2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!var->IsParameter());  // No const parameters.
2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (var->IsLookupSlot()) {
2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rax);
2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rsi);
2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(var->name());
2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3);
2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(var->IsStackLocal() || var->IsContextSlot());
2463589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Label skip;
2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MemOperand location = VarOperand(var, rcx);
2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(rdx, location);
2466589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2467589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ j(not_equal, &skip);
2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitStoreToStackLocalOrContextSlot(var, location);
2469589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ bind(&skip);
2470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2471e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
24723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (var->mode() == LET && op != Token::INIT_LET) {
2473589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Non-initializing assignment to let variable needs a write barrier.
2474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!var->IsLookupSlot());
2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label assign;
2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemOperand location = VarOperand(var, rcx);
2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdx, location);
2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, &assign, Label::kNear);
2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(var->name());
2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntime(Runtime::kThrowReferenceError, 1);
2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&assign);
2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitStoreToStackLocalOrContextSlot(var, location);
2485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
2487589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (var->IsLookupSlot()) {
2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Assignment to var.
2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rax);  // Value.
2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rsi);  // Context.
2491589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ Push(var->name());
2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(Smi::FromInt(strict_mode()));
2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kStoreLookupSlot, 4);
2494589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else {
2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Assignment to var or initializing assignment to let/const in harmony
2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // mode.
2497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2498589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      MemOperand location = VarOperand(var, rcx);
2499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (generate_debug_code_ && op == Token::INIT_LET) {
2500589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // Check for an uninitialized let binding.
2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(rdx, location);
2502589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Check(equal, kLetBindingReInitialization);
25043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitStoreToStackLocalOrContextSlot(var, location);
25063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
25073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2508589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Non-initializing assignments to consts are ignored.
25093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
25103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
25113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2512d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
2514d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(prop != NULL);
2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(prop->key()->IsLiteral());
2517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
2519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value());
2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(StoreDescriptor::ReceiverRegister());
2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStoreIC(expr->AssignmentFeedbackId());
2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2524086aeeaae12517475c22695a200be45495516549Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(rax);
2526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2529d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
2531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(StoreDescriptor::NameRegister());  // Key.
2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(StoreDescriptor::ReceiverRegister());
2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(StoreDescriptor::ValueRegister().is(rax));
2535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
2536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> ic = CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code();
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(ic, expr->AssignmentFeedbackId());
2539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2540086aeeaae12517475c22695a200be45495516549Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
25410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2545d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) {
2546d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Property");
2547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* key = expr->key();
2548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (key->IsPropertyName()) {
2550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!expr->IsSuperAccess()) {
2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(expr->obj());
2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!rax.is(LoadDescriptor::ReceiverRegister()));
2553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(LoadDescriptor::ReceiverRegister(), rax);
2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitNamedPropertyLoad(expr);
2555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitNamedSuperPropertyLoad(expr);
2557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrepareForBailoutForId(expr->LoadId(), TOS_REG);
2559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    context()->Plug(rax);
2560d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
25610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(expr->obj());
25620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->key());
2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(LoadDescriptor::NameRegister(), rax);
2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pop(LoadDescriptor::ReceiverRegister());
2565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitKeyedPropertyLoad(expr);
2566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    context()->Plug(rax);
2567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::CallIC(Handle<Code> code,
2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               TypeFeedbackId ast_id) {
2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ic_total_count_++;
2574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ call(code, RelocInfo::CODE_TARGET, ast_id);
2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC.
2579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Expression* callee = expr->expression();
2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallICState::CallType call_type =
2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD;
2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the target function.
2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (call_type == CallICState::FUNCTION) {
2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    { StackValueContext context(this);
2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitVariableLoad(callee->AsVariableProxy());
2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrepareForBailout(callee, NO_REGISTERS);
25893e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push undefined as receiver. This is patched in the method prologue if it
2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // is a sloppy mode method.
2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(isolate()->factory()->undefined_value());
2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load the function from the receiver.
2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(callee->IsProperty());
2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!callee->AsProperty()->IsSuperAccess());
2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitNamedPropertyLoad(callee->AsProperty());
2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push the target function under the receiver.
2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(Operand(rsp, 0));
2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(Operand(rsp, kPointerSize), rax);
26033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitCall(expr, call_type);
2606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2608d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Expression* callee = expr->expression();
2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(callee->IsProperty());
2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Property* prop = callee->AsProperty();
2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(prop->IsSuperAccess());
2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetSourcePosition(prop->position());
2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Literal* key = prop->key()->AsLiteral();
2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!key->value()->IsSmi());
2618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the function from the receiver.
2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SuperReference* super_ref = prop->obj()->AsSuperReference();
2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitLoadHomeObject(super_ref);
2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);
2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(super_ref->this_var());
2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);
2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(Operand(rsp, kPointerSize));
2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);
2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(key->value());
2627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Stack here:
2629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  - home_object
2630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  - this (receiver)
2631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  - home_object <-- LoadFromSuper will pop here and below.
2632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  - this (receiver)
2633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  - key
2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kLoadFromSuper, 3);
2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Replace home_object with target function.
2637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(Operand(rsp, kPointerSize), rax);
2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Stack here:
2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // - target function
2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // - this (receiver)
2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitCall(expr, CallICState::METHOD);
2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Common code for calls using the IC.
2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Expression* key) {
26498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the key.
26508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForAccumulatorValue(key);
26518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Expression* callee = expr->expression();
26538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the function from the receiver.
2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(callee->IsProperty());
2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(LoadDescriptor::NameRegister(), rax);
2658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitKeyedPropertyLoad(callee->AsProperty());
2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push the target function under the receiver.
2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(Operand(rsp, 0));
2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(Operand(rsp, kPointerSize), rax);
2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitCall(expr, CallICState::METHOD);
26669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
26679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
26689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the arguments.
2671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
2673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { PreservePositionScope scope(masm()->positions_recorder());
26743e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
26753e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
26763e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Record source position of the IC call.
2680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> ic = CallIC::initialize_stub(
2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate(), arg_count, call_type);
2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rdx, Smi::FromInt(expr->CallFeedbackSlot()));
2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Don't assign a type feedback id to the IC, since type feedback is provided
2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // by the vector above.
2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(ic);
2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2689086aeeaae12517475c22695a200be45495516549Ben Murdoch  RecordJSReturnSite(expr);
2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
26913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore context register.
2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
26933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Discard the function left on TOS.
26940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->DropAndPlug(1, rax);
2695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2699e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Push copy of the first argument or undefined if it doesn't exist.
2700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (arg_count > 0) {
2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(Operand(rsp, arg_count * kPointerSize));
2702e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
2703e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ PushRoot(Heap::kUndefinedValueRootIndex);
2704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2705e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push the enclosing function.
2707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
2708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2709e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Push the receiver of the enclosing function and do runtime call.
2710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args(rbp, info_->scope()->num_parameters());
2711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(args.GetReceiverOperand());
2712e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
27133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the language mode.
2714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(Smi::FromInt(strict_mode()));
27153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the start position of the scope the calls resides in.
27173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(Smi::FromInt(scope()->start_position()));
2718e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
27193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do the runtime call.
2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
2721e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2722e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2723e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2724d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) {
2725086aeeaae12517475c22695a200be45495516549Ben Murdoch#ifdef DEBUG
2726086aeeaae12517475c22695a200be45495516549Ben Murdoch  // We want to verify that RecordJSReturnSite gets called on all paths
2727086aeeaae12517475c22695a200be45495516549Ben Murdoch  // through this function.  Avoid early returns.
2728086aeeaae12517475c22695a200be45495516549Ben Murdoch  expr->return_is_recorded_ = false;
2729086aeeaae12517475c22695a200be45495516549Ben Murdoch#endif
2730086aeeaae12517475c22695a200be45495516549Ben Murdoch
2731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Call");
2732589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Expression* callee = expr->expression();
2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Call::CallType call_type = expr->GetCallType(isolate());
2734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (call_type == Call::POSSIBLY_EVAL_CALL) {
2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
2737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // to resolve the function we need to call and the receiver of the call.
2738589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Then we call the resolved function using the given arguments.
2739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    ZoneList<Expression*>* args = expr->arguments();
2740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    int arg_count = args->length();
2741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope pos_scope(masm()->positions_recorder());
2742589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VisitForStackValue(callee);
27433e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ PushRoot(Heap::kUndefinedValueRootIndex);  // Reserved receiver slot.
2744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Push the arguments.
27463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      for (int i = 0; i < arg_count; i++) {
27473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        VisitForStackValue(args->at(i));
27483e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      }
2749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2750589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Push a copy of the function (found below the arguments) and resolve
2751589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // eval.
2752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(Operand(rsp, (arg_count + 1) * kPointerSize));
27533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitResolvePossiblyDirectEval(arg_count);
2754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // The runtime call returns a pair of values in rax (function) and
27563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // rdx (receiver). Touch up the stack with the right values.
2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
27593e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Record source position for debugger.
2761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetSourcePosition(expr->position());
2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
2765086aeeaae12517475c22695a200be45495516549Ben Murdoch    RecordJSReturnSite(expr);
2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Restore context register.
2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
27680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->DropAndPlug(1, rax);
2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (call_type == Call::GLOBAL_CALL) {
2770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitCallWithLoadIC(expr);
2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (call_type == Call::LOOKUP_SLOT_CALL) {
277359151504615d929945dc59db37bf1166937748c6Steve Block    // Call to a lookup slot (dynamically introduced variable).
2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VariableProxy* proxy = callee->AsVariableProxy();
277559151504615d929945dc59db37bf1166937748c6Steve Block    Label slow, done;
277659151504615d929945dc59db37bf1166937748c6Steve Block
2777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope scope(masm()->positions_recorder());
2778589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Generate code for loading from variables potentially shadowed by
2779589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // eval-introduced variables.
2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
2781086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
2782589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ bind(&slow);
2783589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Call the runtime to find the function to call (returned in rax) and
2784589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // the object holding it (returned in rdx).
2785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(context_register());
2786589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ Push(proxy->name());
2787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntime(Runtime::kLoadLookupSlot, 2);
2788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rax);  // Function.
2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rdx);  // Receiver.
2790086aeeaae12517475c22695a200be45495516549Ben Murdoch
2791589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // If fast case code has been generated, emit code to push the function
2792589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // and receiver and have the slow path jump around this code.
2793086aeeaae12517475c22695a200be45495516549Ben Murdoch    if (done.is_linked()) {
2794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label call;
2795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ jmp(&call, Label::kNear);
2796086aeeaae12517475c22695a200be45495516549Ben Murdoch      __ bind(&done);
2797086aeeaae12517475c22695a200be45495516549Ben Murdoch      // Push function.
2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rax);
2799589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // The receiver is implicitly the global receiver. Indicate this by
2800589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // passing the hole to the call function stub.
2801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ PushRoot(Heap::kUndefinedValueRootIndex);
2802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ bind(&call);
280359151504615d929945dc59db37bf1166937748c6Steve Block    }
280459151504615d929945dc59db37bf1166937748c6Steve Block
2805589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // The receiver is either the global receiver or an object found by
2806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // LoadContextSlot.
2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitCall(expr);
2808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (call_type == Call::PROPERTY_CALL) {
2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Property* property = callee->AsProperty();
2810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool is_named_call = property->key()->IsPropertyName();
2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // super.x() is handled in EmitCallWithLoadIC.
2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (property->IsSuperAccess() && is_named_call) {
2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitSuperCallWithLoadIC(expr);
2814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
2815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      {
2816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        PreservePositionScope scope(masm()->positions_recorder());
2817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->obj());
2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (is_named_call) {
2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        EmitCallWithLoadIC(expr);
2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
2822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        EmitKeyedCallWithLoadIC(expr, property->key());
2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
28253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(call_type == Call::OTHER_CALL);
2827589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Call to an arbitrary expression not handled specially above.
2828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope scope(masm()->positions_recorder());
2829589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VisitForStackValue(callee);
28303e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ PushRoot(Heap::kUndefinedValueRootIndex);
2832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit function call.
2833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitCall(expr);
2834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2835086aeeaae12517475c22695a200be45495516549Ben Murdoch
2836086aeeaae12517475c22695a200be45495516549Ben Murdoch#ifdef DEBUG
2837086aeeaae12517475c22695a200be45495516549Ben Murdoch  // RecordJSReturnSite should have been called.
2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->return_is_recorded_);
2839086aeeaae12517475c22695a200be45495516549Ben Murdoch#endif
2840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2843d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
2844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
2845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
2846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
2847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
2848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
284980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Push constructor on the stack.  If it's not a function it's used as
285080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
285180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ignored.
28520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->expression());
2853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
2855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
2857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
28580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
28593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
2862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
2863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
2864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
286580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load function and argument count into rdi and rax.
2866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Set(rax, arg_count);
2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, Operand(rsp, arg_count * kPointerSize));
2868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Record call targets in unoptimized code, but not in the snapshot.
2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_pretenuring_call_new) {
2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot());
2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(expr->AllocationSiteFeedbackSlot() ==
2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           expr->CallNewFeedbackSlot() + 1);
28743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
28753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rbx, FeedbackVector());
2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rdx, Smi::FromInt(expr->CallNewFeedbackSlot()));
2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET);
28803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
28813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
28820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
28833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
28843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
28853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
28863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
28873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
2889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
289580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
28960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
28970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_true);
2901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(if_false);
2902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
29083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
2910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
291680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
29170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
29180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2921f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax);
2922f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Split(non_negative_smi, if_true, if_false, fall_through);
2923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
29293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
2931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
293780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
29380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
29390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareRoot(rax, Heap::kNullValueRootIndex);
2943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
2944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Undetectable objects behave like undefined when tested with typeof.
2946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke           Immediate(1 << Map::kIsUndetectable));
2948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_zero, if_false);
2949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movzxbp(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, if_false);
2952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
29533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
295480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(below_equal, if_true, if_false, fall_through);
2955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
29613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
29633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
29640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
29653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
29663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label materialize_true, materialize_false;
29673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_true = NULL;
29683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_false = NULL;
296980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
29700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
29710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
29723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
29733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ JumpIfSmi(rax, if_false);
29743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx);
29753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
297680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(above_equal, if_true, if_false, fall_through);
29773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
29780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
29793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
29803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
29813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
29823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
2985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
299180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
29920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
29930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
2996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke           Immediate(1 << Map::kIsUndetectable));
29993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
300080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(not_zero, if_true, if_false, fall_through);
3001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3006756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
30073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime* expr) {
30083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3010756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
30110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3012756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label materialize_true, materialize_false, skip_lookup;
3014756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_true = NULL;
3015756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_false = NULL;
301680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
30170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
30180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
3019756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AssertNotSmi(rax);
30218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
30228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Check whether this map has already been checked to be safe for default
30238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // valueOf.
3024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
30258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ testb(FieldOperand(rbx, Map::kBitField2Offset),
30268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch           Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
3027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_zero, &skip_lookup);
30288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
30298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Check for fast case object. Generate false result for slow case object.
3030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rax, JSObject::kPropertiesOffset));
3031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
30328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ CompareRoot(rcx, Heap::kHashTableMapRootIndex);
30338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ j(equal, if_false);
30348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
3035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Look for valueOf string in the descriptor array, and indicate false if
3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // found. Since we omit an enumeration index check, if it is added via a
3037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // transition that shares its descriptor array, this is a false positive.
3038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label entry, loop, done;
3039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Skip loop if no descriptors are valid.
3041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ NumberOfOwnDescriptors(rcx, rbx);
3042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rcx, Immediate(0));
3043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &done);
3044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadInstanceDescriptors(rbx, r8);
3046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rbx: descriptor array.
3047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rcx: valid entries in the descriptor array.
30488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Calculate the end of the descriptor array.
3049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ imulp(rcx, rcx, Immediate(DescriptorArray::kDescriptorSize));
3050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(rcx,
3051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Operand(r8, rcx, times_pointer_size, DescriptorArray::kFirstOffset));
30528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Calculate location of the first key name.
3053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(r8, Immediate(DescriptorArray::kFirstOffset));
30548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Loop through all the keys in the descriptor array. If one of these is the
3055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // internalized string "valueOf" the result is false.
30568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ jmp(&entry);
30578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ bind(&loop);
3058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, FieldOperand(r8, 0));
3059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cmp(rdx, isolate()->factory()->value_of_string());
30608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ j(equal, if_false);
3061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(r8, Immediate(DescriptorArray::kDescriptorSize * kPointerSize));
30628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ bind(&entry);
3063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(r8, rcx);
30648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ j(not_equal, &loop);
30658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
3066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
3067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set the bit in the map to indicate that there is no local valueOf field.
3069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ orp(FieldOperand(rbx, Map::kBitField2Offset),
3070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
3071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&skip_lookup);
30738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If a valueOf property is not found on the object check that its
30758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // prototype is the un-modified String prototype. If not result is false.
3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testp(rcx, Immediate(kSmiTagMask));
30788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ j(zero, if_false);
3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, FieldOperand(rdx, GlobalObject::kNativeContextOffset));
3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rcx,
30838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
30843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Split(equal, if_true, if_false, fall_through);
3086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3088756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
3089756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3090756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
30913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
30923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
310080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
31010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
31020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
3103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
3105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
31063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
310780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
3108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(0));
3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label materialize_true, materialize_false;
3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_true = NULL;
3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* if_false = NULL;
3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* fall_through = NULL;
3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
3124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         &if_true, &if_false, &fall_through);
3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
3127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CheckMap(rax, map, if_false, DO_SMI_CHECK);
3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpl(FieldOperand(rax, HeapNumber::kExponentOffset),
3129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Immediate(0x1));
3130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(no_overflow, if_false);
3131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpl(FieldOperand(rax, HeapNumber::kMantissaOffset),
3132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Immediate(0x00000000));
3133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Split(equal, if_true, if_false, fall_through);
3135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(if_true, if_false);
3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
31403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
31413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
314980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
31500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
31510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
3152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
3154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
31553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
315680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
3157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
31633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
317180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
31720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
31730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
3174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
3176f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
31773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
317880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
3179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
3186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->arguments()->length() == 0);
3187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3188f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
319180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
31920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
31930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
3194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the frame pointer for the calling frame.
3196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
3197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Skip the arguments adaptor frame if it exists.
3199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label check_frame_marker;
320044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Cmp(Operand(rax, StandardFrameConstants::kContextOffset),
320144f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
3202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &check_frame_marker);
3203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
3204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check the marker in the calling frame.
3206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&check_frame_marker);
320744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset),
320844f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Smi::FromInt(StackFrame::CONSTRUCT));
32093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
321080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
3211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
32173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
3219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the two objects into registers and perform the comparison.
32210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
32220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
3223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
322780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
32280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
32290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
3230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rbx);
3232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rax, rbx);
32333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
323480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
3235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
3237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArguments(CallRuntime* expr) {
32413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
324480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ArgumentsAccessStub expects the key in rdx and the formal
324580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // parameter count in rax.
32460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, rax);
32483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
3249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT);
3250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
32510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
3256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->arguments()->length() == 0);
3257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label exit;
3259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the number of formal parameters.
32603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
3261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the calling frame is an arguments adaptor frame.
3263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
326444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
326544f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
3266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &exit, Label::kNear);
3267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Arguments adaptor case: Read the arguments length from the
3269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // adaptor frame.
3270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
3271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
3273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AssertSmi(rax);
32740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
32793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, null, function, non_function_constructor;
3282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, we return null.
3286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, &null);
3287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check that the object is a JS object but take special care of JS
3289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // functions to make sure they have 'Function' as their class.
32903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Assume that there are only two callable types, and one of them is at
32913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // either end of the type range for JS object types. Saves extra comparisons.
32923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
32933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax);
32943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Map is now in rax.
3295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, &null);
32963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
32973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                FIRST_SPEC_OBJECT_TYPE + 1);
32983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(equal, &function);
32993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE);
33013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
33023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                LAST_SPEC_OBJECT_TYPE - 1);
33033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(equal, &function);
33043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Assume that there is no larger type.
33053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
33063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the constructor in the map is a JS function.
3308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, FieldOperand(rax, Map::kConstructorOffset));
3309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
3310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &non_function_constructor);
3311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // rax now contains the constructor function. Grab the
3313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // instance class name from there.
3314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
3315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset));
3316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
3317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Functions have class 'Function'.
3319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&function);
3320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rax, isolate()->factory()->Function_string());
3321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
3322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Objects with a non-function constructor have class 'Object'.
3324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&non_function_constructor);
3325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rax, isolate()->factory()->Object_string());
3326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
3327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-JS objects have class null.
3329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&null);
3330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ LoadRoot(rax, Heap::kNullValueRootIndex);
3331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // All done.
3333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
3334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSubString(CallRuntime* expr) {
3340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
3341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SubStringStub stub(isolate());
33423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 3);
33440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
33450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
33460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
3347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
33480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
3353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
3354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegExpExecStub stub(isolate());
33553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 4);
33570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
33580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
33590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
33600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(3));
3361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
33620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
33673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));  // Load the object.
3371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
3373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi return the object.
3374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, &done);
3375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the object.
3376f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_VALUE_TYPE, rbx);
3377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &done);
3378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, FieldOperand(rax, JSValue::kValueOffset));
3379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3380f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
33810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3382f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3383f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3384f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitDateField(CallRuntime* expr) {
33863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
3388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NE(NULL, args->at(1)->AsLiteral());
3389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value()));
33903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitForAccumulatorValue(args->at(0));  // Load the object.
33923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label runtime, done, not_date_object;
33943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = rax;
33953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = rax;
33963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = rcx;
33973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(object, &not_date_object);
33993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpObjectType(object, JS_DATE_TYPE, scratch);
3400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &not_date_object);
34013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (index->value() == 0) {
3403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(result, FieldOperand(object, JSDate::kValueOffset));
3404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done);
34053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
34063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (index->value() < JSDate::kFirstUncachedField) {
34073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
3408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Operand stamp_operand = __ ExternalOperand(stamp);
3409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(scratch, stamp_operand);
3410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmpp(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
34113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(not_equal, &runtime, Label::kNear);
3412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(result, FieldOperand(object, JSDate::kValueOffset +
34133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           kPointerSize * index->value()));
34143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&done);
34153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
34163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&runtime);
34173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ PrepareCallCFunction(2);
3418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(arg_reg_1, object);
3419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(arg_reg_2, index, Assembler::RelocInfoNone());
34203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
3421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done);
34233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&not_date_object);
3426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kThrowNotDateError, 0);
3427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
3428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(rax);
3429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
3433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(3, args->length());
3435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register string = rax;
3437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register index = rbx;
3438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register value = rcx;
3439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(args->at(0));        // index
3441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(args->at(1));        // value
3442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(2));  // string
3443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(value);
3444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(index);
3445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
3447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(__ CheckSmi(value), kNonSmiValue);
3448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(__ CheckSmi(index), kNonSmiValue);
3449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(value, value);
3452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(index, index);
3453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
3455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
3456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
3457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movb(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize),
3460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          value);
3461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(string);
3462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
3466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(3, args->length());
3468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register string = rax;
3470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register index = rbx;
3471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register value = rcx;
3472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(args->at(0));        // index
3474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForStackValue(args->at(1));        // value
3475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(2));  // string
3476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(value);
3477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(index);
3478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
3480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(__ CheckSmi(value), kNonSmiValue);
3481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(__ CheckSmi(index), kNonSmiValue);
3482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(value, value);
3485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(index, index);
3486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
3488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
3489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
3490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movw(FieldOperand(string, index, times_2, SeqTwoByteString::kHeaderSize),
3493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          value);
34943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->Plug(rax);
34953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
34963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
3499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the runtime function.
35003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
35020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
35030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
3504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MathPowStub stub(isolate(), MathPowStub::ON_STACK);
3505e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CallStub(&stub);
35060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
35103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
35113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
3513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
35140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));  // Load the object.
35150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));  // Load the value.
3516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rbx);  // rax = value. rbx = object.
3517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done;
3519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, return the value.
3520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rbx, &done);
3521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the value.
3523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx);
3524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &done);
3525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Store the value.
3527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rbx, JSValue::kValueOffset), rax);
3528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the write barrier.  Save the value as it will be
3529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // overwritten by the write barrier code and is needed afterward.
3530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, rax);
35313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs);
3532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
35340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
35383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
35393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(args->length(), 1);
3541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the argument into rax and call the stub.
3543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(0));
3544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NumberToStringStub stub(isolate());
3546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
35470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
35513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
35523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
3554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
35550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
35577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
35587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharFromCodeGenerator generator(rax, rbx);
35597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
35607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
3561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
35627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
35637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
3564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
35657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
35660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rbx);
35677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
35687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
35713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
35737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
35750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
35767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = rbx;
35787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = rax;
35797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = rdx;
35807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(object);
35827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
35847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
35857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
35867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharCodeAtGenerator generator(object,
35877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      index,
35887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      result,
35897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
35907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
35917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &index_out_of_range,
35927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      STRING_INDEX_IS_NUMBER);
35937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
3594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
3595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
35967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
35977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
35987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // NaN.
35997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kNanValueRootIndex);
36007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
36017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
36027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
36037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move the undefined value into the result register, which will
36047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // trigger conversion.
36057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
36067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
36077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
36087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
36097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
3610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
36120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
3613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
36163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
36173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
36197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
36200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
36210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
36227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
36237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = rbx;
36247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = rax;
36253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = rdx;
36267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = rax;
36277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(object);
36297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
36307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
36317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
36327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
36337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharAtGenerator generator(object,
36347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  index,
36353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  scratch,
36367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  result,
36377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
36387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
36397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &index_out_of_range,
36407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  STRING_INDEX_IS_NUMBER);
36417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
36427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
36437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
36447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
36457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
36467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the empty string.
3647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(result, Heap::kempty_stringRootIndex);
36487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
36497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
36507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
36517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move smi zero into the result register, which will trigger
36527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // conversion.
36537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Move(result, Smi::FromInt(0));
36547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
36557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
36567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
36577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
36587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
36597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
36600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
3661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
36637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
36643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
36653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(2, args->length());
36670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
3668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(1));
3669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rdx);
3671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED);
3672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
36730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
36773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
36783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(2, args->length());
3680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
36810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
36820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
3683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StringCompareStub stub(isolate());
3685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
36860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
36903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
36913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() >= 2);
3693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int arg_count = args->length() - 2;  // 2 ~ receiver and function.
3695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < arg_count + 1; i++) {
3696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VisitForStackValue(args->at(i));
3697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  VisitForAccumulatorValue(args->last());  // Function.
3699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label runtime, done;
3701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for non-function argument (including proxy).
3702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(rax, &runtime);
3703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
3704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &runtime);
37053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // InvokeFunction requires the function in rdi. Move it in there.
3707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, result_register());
3708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ParameterCount count(arg_count);
3709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ InvokeFunction(rdi, count, CALL_FUNCTION, NullCallWrapper());
3710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
37113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&done);
37123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&runtime);
3714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);
37153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallRuntime(Runtime::kCall, args->length());
37163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
37173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3721f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
37223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegExpConstructResultStub stub(isolate());
37243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 3);
37260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
37270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
3728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(args->at(2));
3729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rbx);
3730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rcx);
3731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CallStub(&stub);
37320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
37363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
37373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(2, args->length());
3739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NE(NULL, args->at(0)->AsLiteral());
3741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value();
3742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<FixedArray> jsfunction_result_caches(
3744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate()->native_context()->jsfunction_result_caches());
3745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (jsfunction_result_caches->length() <= cache_id) {
3746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Abort(kAttemptToUseUndefinedCache);
3747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
37480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
3749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
37520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
3753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register key = rax;
3755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register cache = rbx;
3756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register tmp = rcx;
3757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(cache, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX));
3758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(cache,
3759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          FieldOperand(cache, GlobalObject::kNativeContextOffset));
3760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(cache,
376159151504615d929945dc59db37bf1166937748c6Steve Block          ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
3762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(cache,
3763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
3764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done, not_found;
376669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
3768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // tmp now holds finger offset as a smi.
3769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SmiIndex index =
3770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2);
3771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(key, FieldOperand(cache,
3772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.reg,
3773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.scale,
3774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            FixedArray::kHeaderSize));
3775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &not_found, Label::kNear);
3776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, FieldOperand(cache,
3777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.reg,
3778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            index.scale,
3779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            FixedArray::kHeaderSize + kPointerSize));
3780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&done, Label::kNear);
3781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&not_found);
3783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call runtime to perform the lookup.
3784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(cache);
3785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(key);
3786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetFromCache, 2);
3787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
37890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
3790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
37933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
37943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
379680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
37970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
379880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
379980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
380080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
380180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
380280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
38030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
38040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
380580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
380680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ testl(FieldOperand(rax, String::kHashFieldOffset),
380780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           Immediate(String::kContainsCachedArrayIndexMask));
38083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
380980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(zero, if_true);
381080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(if_false);
381180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
38120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
381380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
381480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
381580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
38163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
38173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
38190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
382080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AssertString(rax);
3822e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
382380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movl(rax, FieldOperand(rax, String::kHashFieldOffset));
3824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(String::kHashShift >= kSmiTagSize);
382580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ IndexFromHash(rax, rax);
382680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
38270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
382880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
382980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
383080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) {
383244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label bailout, return_result, done, one_char_separator, long_separator,
383344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      non_trivial_array, not_size_one_array, loop,
383444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
38353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
383744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // We will leave the separator on the stack until the end of the function.
383844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  VisitForStackValue(args->at(1));
383944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load this to rax (= array)
384044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  VisitForAccumulatorValue(args->at(0));
384144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // All aliases of the same register have disjoint lifetimes.
384244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register array = rax;
384344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register elements = no_reg;  // Will be rax.
384444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
384544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register index = rdx;
384644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
384744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register string_length = rcx;
384844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
384944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register string = rsi;
385044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
385144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register scratch = rbx;
385244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
385344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register array_length = rdi;
385444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register result_pos = no_reg;  // Will be rdi.
385544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
385644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand separator_operand =    Operand(rsp, 2 * kPointerSize);
385744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand result_operand =       Operand(rsp, 1 * kPointerSize);
385844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand array_length_operand = Operand(rsp, 0 * kPointerSize);
385944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Separator operand is already pushed. Make room for the two
386044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // other stack fields, and clear the direction flag in anticipation
386144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // of calling CopyBytes.
3862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(rsp, Immediate(2 * kPointerSize));
386344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cld();
386444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the array is a JSArray
386544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ JumpIfSmi(array, &bailout);
386644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
386744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(not_equal, &bailout);
386844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
386944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the array has fast elements.
38703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CheckFastElements(scratch, &bailout);
387144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
387244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Array has fast elements, so its length must be a smi.
387344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If the array has length zero, return the empty string.
3874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(array_length, FieldOperand(array, JSArray::kLengthOffset));
387544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiCompare(array_length, Smi::FromInt(0));
387644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(not_zero, &non_trivial_array);
3877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(rax, Heap::kempty_stringRootIndex);
387844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&return_result);
387944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
388044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Save the array length on the stack.
388144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&non_trivial_array);
388244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiToInteger32(array_length, array_length);
388344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movl(array_length_operand, array_length);
388444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
388544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Save the FixedArray containing array's elements.
388644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // End of array's live range.
388744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  elements = array;
3888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(elements, FieldOperand(array, JSArray::kElementsOffset));
388944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  array = no_reg;
389044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
389144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that all array elements are sequential one-byte strings, and
389344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // accumulate the sum of their lengths, as a smi-encoded value.
389444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Set(index, 0);
389544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Set(string_length, 0);
389644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Loop condition: while (index < array_length).
389744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live loop registers: index(int32), array_length(int32), string(String*),
389844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //                      scratch, string_length(int32), elements(FixedArray*).
3899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (generate_debug_code_) {
3900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpp(index, array_length);
3901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Assert(below, kNoEmptyArraysHereInEmitFastOneByteArrayJoin);
390244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
390344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&loop);
3904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(string, FieldOperand(elements,
390544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               index,
390644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               times_pointer_size,
390744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               FixedArray::kHeaderSize));
390844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ JumpIfSmi(string, &bailout);
3909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(scratch, FieldOperand(string, HeapObject::kMapOffset));
391044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
391144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ andb(scratch, Immediate(
391244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpb(scratch, Immediate(kStringTag | kOneByteStringTag | kSeqStringTag));
391444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(not_equal, &bailout);
391544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ AddSmiField(string_length,
3916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 FieldOperand(string, SeqOneByteString::kLengthOffset));
391744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(overflow, &bailout);
391844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ incl(index);
391944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpl(index, array_length);
392044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(less, &loop);
392144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
392244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live registers:
392344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // string_length: Sum of string lengths.
392444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // elements: FixedArray of strings.
392544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // index: Array length.
392644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // array_length: Array length.
392744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
392844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If array_length is 1, return elements[0], a string.
392944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpl(array_length, Immediate(1));
393044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(not_equal, &not_size_one_array);
3931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, FieldOperand(elements, FixedArray::kHeaderSize));
393244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&return_result);
393344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
393444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&not_size_one_array);
393544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
393644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // End of array_length live range.
393744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  result_pos = array_length;
393844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  array_length = no_reg;
393944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
394044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live registers:
394144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // string_length: Sum of string lengths.
394244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // elements: FixedArray of strings.
394344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // index: Array length.
394444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that the separator is a sequential one-byte string.
3946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(string, separator_operand);
394744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ JumpIfSmi(string, &bailout);
3948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(scratch, FieldOperand(string, HeapObject::kMapOffset));
394944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
395044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ andb(scratch, Immediate(
395144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpb(scratch, Immediate(kStringTag | kOneByteStringTag | kSeqStringTag));
395344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(not_equal, &bailout);
395444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
395544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live registers:
395644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // string_length: Sum of string lengths.
395744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // elements: FixedArray of strings.
395844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // index: Array length.
395944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // string: Separator string.
396044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
396144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Add (separator length times (array_length - 1)) to string_length.
396244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiToInteger32(scratch,
3963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    FieldOperand(string, SeqOneByteString::kLengthOffset));
396444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ decl(index);
396544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ imull(scratch, index);
396644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(overflow, &bailout);
396744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ addl(string_length, scratch);
396844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(overflow, &bailout);
396944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
397044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live registers and stack values:
397144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   string_length: Total length of result string.
397244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   elements: FixedArray of strings.
3973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AllocateOneByteString(result_pos, string_length, scratch, index, string,
3974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           &bailout);
3975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(result_operand, result_pos);
3976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(result_pos, FieldOperand(result_pos, SeqOneByteString::kHeaderSize));
397744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(string, separator_operand);
3979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiCompare(FieldOperand(string, SeqOneByteString::kLengthOffset),
398044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Smi::FromInt(1));
398144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(equal, &one_char_separator);
398244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(greater, &long_separator);
398344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
398444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
398544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Empty separator case:
398644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Set(index, 0);
398744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movl(scratch, array_length_operand);
398844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&loop_1_condition);
398944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Loop condition: while (index < array_length).
399044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&loop_1);
399144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Each iteration of the loop concatenates one string to the result.
399244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live values in registers:
399344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   index: which element of the elements array we are adding to the result.
399444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   result_pos: the position to which we are currently copying characters.
399544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   elements: the FixedArray of strings we are joining.
399644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   scratch: array length.
399744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
399844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get string = array[index].
3999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(string, FieldOperand(elements, index,
400044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               times_pointer_size,
400144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               FixedArray::kHeaderSize));
400244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiToInteger32(string_length,
400344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    FieldOperand(string, String::kLengthOffset));
4004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(string,
4005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(string, SeqOneByteString::kHeaderSize));
400644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ CopyBytes(result_pos, string, string_length);
400744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ incl(index);
400844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&loop_1_condition);
400944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpl(index, scratch);
401044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(less, &loop_1);  // Loop while (index < array_length).
401144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&done);
401244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
401344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Generic bailout code used from several places.
401444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&bailout);
401544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
401644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&return_result);
401744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
401844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
401944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // One-character separator case
402044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&one_char_separator);
4021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the separator one-byte character value.
402244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Register "string" holds the separator.
4023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movzxbl(scratch, FieldOperand(string, SeqOneByteString::kHeaderSize));
402444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Set(index, 0);
402544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Jump into the loop after the code that copies the separator, so the first
402644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // element is not preceded by a separator
402744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&loop_2_entry);
402844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Loop condition: while (index < length).
402944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&loop_2);
403044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Each iteration of the loop concatenates one string to the result.
403144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live values in registers:
403244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   elements: The FixedArray of strings we are joining.
403344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   index: which element of the elements array we are adding to the result.
403444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   result_pos: the position to which we are currently copying characters.
403544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   scratch: Separator character.
403644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
403744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Copy the separator character to the result.
403844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movb(Operand(result_pos, 0), scratch);
4039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ incp(result_pos);
404044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
404144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&loop_2_entry);
404244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get string = array[index].
4043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(string, FieldOperand(elements, index,
404444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               times_pointer_size,
404544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               FixedArray::kHeaderSize));
404644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiToInteger32(string_length,
404744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    FieldOperand(string, String::kLengthOffset));
4048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(string,
4049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(string, SeqOneByteString::kHeaderSize));
405044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ CopyBytes(result_pos, string, string_length);
405144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ incl(index);
405244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpl(index, array_length_operand);
405344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(less, &loop_2);  // End while (index < length).
405444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&done);
405544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
405644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
405744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Long separator case (separator is more than one character).
405844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&long_separator);
405944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
406044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Make elements point to end of elements array, and index
406144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // count from -array_length to zero, so we don't need to maintain
406244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // a loop limit.
406344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movl(index, array_length_operand);
4064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(elements, FieldOperand(elements, index, times_pointer_size,
406544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                FixedArray::kHeaderSize));
4066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ negq(index);
406744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
406844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Replace separator string with pointer to its first character, and
406944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // make scratch be its length.
4070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(string, separator_operand);
407144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiToInteger32(scratch,
407244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    FieldOperand(string, String::kLengthOffset));
4073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(string,
4074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(string, SeqOneByteString::kHeaderSize));
4075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(separator_operand, string);
407644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
407744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Jump into the loop after the code that copies the separator, so the first
407844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // element is not preceded by a separator
407944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ jmp(&loop_3_entry);
408044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Loop condition: while (index < length).
408144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&loop_3);
408244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Each iteration of the loop concatenates one string to the result.
408344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Live values in registers:
408444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   index: which element of the elements array we are adding to the result.
408544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   result_pos: the position to which we are currently copying characters.
408644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   scratch: Separator length.
408744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   separator_operand (rsp[0x10]): Address of first char of separator.
408844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
408944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Copy the separator to the result.
4090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(string, separator_operand);
409144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movl(string_length, scratch);
409244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ CopyBytes(result_pos, string, string_length, 2);
409344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
409444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&loop_3_entry);
409544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get string = array[index].
4096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(string, Operand(elements, index, times_pointer_size, 0));
409744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiToInteger32(string_length,
409844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    FieldOperand(string, String::kLengthOffset));
4099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(string,
4100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(string, SeqOneByteString::kHeaderSize));
410144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ CopyBytes(result_pos, string, string_length);
410244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ incq(index);
410344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ j(not_equal, &loop_3);  // Loop while (index < 0).
410444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
410544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&done);
4106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, result_operand);
410744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
410844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&return_result);
410944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Drop temp values from the stack, and restore context register.
4110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(rsp, Immediate(3 * kPointerSize));
4111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(rax);
4113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
4117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->arguments()->length() == 0);
4118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference debug_is_active =
4119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::debug_is_active_address(isolate());
4120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(kScratchRegister, debug_is_active);
4121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movzxbp(rax, Operand(kScratchRegister, 0));
4122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Integer32ToSmi(rax, rax);
412344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  context()->Plug(rax);
41248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
41258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
41268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4127d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
4128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expr->function() != NULL &&
4129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      expr->function()->intrinsic_type == Runtime::INLINE) {
4130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ InlineRuntimeCall");
4131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitInlineRuntimeCall(expr);
4132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
4133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
4134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
41353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ CallRuntime");
41363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* args = expr->arguments();
4137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int arg_count = args->length();
41383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
4140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push the builtins object as receiver.
4141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rax, GlobalObjectOperand());
4142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
4143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load the function from the receiver.
4145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
4146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(LoadDescriptor::NameRegister(), expr->name());
4147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_vector_ics) {
4148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(VectorLoadICDescriptor::SlotRegister(),
4149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Smi::FromInt(expr->CallRuntimeFeedbackSlot()));
4150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallLoadIC(NOT_CONTEXTUAL);
4151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
4153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
41543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push the target function under the receiver.
4156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(Operand(rsp, 0));
4157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(Operand(rsp, kPointerSize), rax);
4158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push the arguments ("left-to-right").
4160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < arg_count; i++) {
4161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForStackValue(args->at(i));
4162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Record source position of the IC call.
4165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SetSourcePosition(expr->position());
4166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
4167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
4168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallStub(&stub);
4169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Restore context register.
4171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context()->DropAndPlug(1, rax);
4173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
4175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push the arguments ("left-to-right").
4176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < arg_count; i++) {
4177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForStackValue(args->at(i));
4178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Call the C runtime.
4181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(expr->function(), arg_count);
4182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context()->Plug(rax);
4183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
4184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
4185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4187d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
4188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
4189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Token::DELETE: {
4190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
4191589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Property* property = expr->expression()->AsProperty();
4192589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VariableProxy* proxy = expr->expression()->AsVariableProxy();
4193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4194589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (property != NULL) {
4195589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        VisitForStackValue(property->obj());
4196589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        VisitForStackValue(property->key());
4197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Push(Smi::FromInt(strict_mode()));
419869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
419969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        context()->Plug(rax);
4200589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else if (proxy != NULL) {
4201589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Variable* var = proxy->var();
4202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Delete of an unqualified identifier is disallowed in strict mode
4203589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // but "delete this" is allowed.
4204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(strict_mode() == SLOPPY || var->is_this());
4205589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (var->IsUnallocated()) {
4206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Push(GlobalObjectOperand());
4207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ Push(var->name());
4208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Push(Smi::FromInt(SLOPPY));
4209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
4210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(rax);
4211589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        } else if (var->IsStackAllocated() || var->IsContextSlot()) {
4212589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // Result of deleting non-global variables is false.  'this' is
4213589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // not really a variable, though we implement it as one.  The
4214589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // subexpression does not have side effects.
4215589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          context()->Plug(var->is_this());
4216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else {
4217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Non-global variable.  Call the runtime to try to delete from the
4218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // context where the variable was introduced.
4219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Push(context_register());
4220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ Push(var->name());
4221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ CallRuntime(Runtime::kDeleteLookupSlot, 2);
4222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(rax);
4223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
42241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
4225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Result of deleting non-property, non-variable reference is true.
4226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // The subexpression may have side effects.
4227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
4228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        context()->Plug(true);
4229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
4230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
4231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
4232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
4234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
4235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
42360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(Heap::kUndefinedValueRootIndex);
4237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
4241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
4242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (context()->IsEffect()) {
4243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Unary NOT has no side effects so it's only necessary to visit the
4244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // subexpression.  Match the optimizing compiler by not branching.
4245e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
42463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (context()->IsTest()) {
42473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        const TestContext* test = TestContext::cast(context());
42483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The labels are swapped for the recursive call.
42493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VisitForControl(expr->expression(),
42503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->false_label(),
42513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->true_label(),
42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->fall_through());
42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        context()->Plug(test->true_label(), test->false_label());
4254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We handle value contexts explicitly rather than simply visiting
42563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // for control and plugging the control flow into the context,
42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // because we need to prepare a pair of extra administrative AST ids
42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // for the optimizing compiler.
4259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue());
42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label materialize_true, materialize_false, done;
42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VisitForControl(expr->expression(),
42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_false,
42633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_true,
42643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_true);
42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&materialize_true);
42663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
42673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (context()->IsAccumulatorValue()) {
42683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ LoadRoot(rax, Heap::kTrueValueRootIndex);
42693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ PushRoot(Heap::kTrueValueRootIndex);
42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&done, Label::kNear);
42733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&materialize_false);
42743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
42753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (context()->IsAccumulatorValue()) {
42763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ LoadRoot(rax, Heap::kFalseValueRootIndex);
42773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ PushRoot(Heap::kFalseValueRootIndex);
42793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&done);
4281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
4282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
4286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
42870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      { StackValueContext context(this);
42880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForTypeofValue(expr->expression());
42890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
4290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallRuntime(Runtime::kTypeof, 1);
42910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(rax);
4292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
4296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
42973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
42983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
42993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
43003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4301d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
4302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->expression()->IsValidReferenceExpression());
4303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Comment cmnt(masm_, "[ CountOperation");
430580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
4306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Expression can only be a property, a global or a (parameter or local)
43083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot.
4309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
4310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LhsKind assign_type = VARIABLE;
4311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
4312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In case of a property we use the uninitialized expression context
4313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // of the key to detect a named property.
4314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (prop != NULL) {
4315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    assign_type =
4316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
4317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
4318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
4320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
4321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
43220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
43233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    EmitVariableLoad(expr->expression()->AsVariableProxy());
4324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
4325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
43260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (expr->is_postfix() && !context()->IsEffect()) {
4327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ Push(Smi::FromInt(0));
4328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
4329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (assign_type == NAMED_PROPERTY) {
4330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForStackValue(prop->obj());
4331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
4332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitNamedPropertyLoad(prop);
4333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
43343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForStackValue(prop->obj());
4335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForStackValue(prop->key());
4336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Leave receiver on stack
4337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, kPointerSize));
4338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Copy of key, needed for later store.
4339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(LoadDescriptor::NameRegister(), Operand(rsp, 0));
4340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitKeyedPropertyLoad(prop);
4341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
4342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
4343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4344086aeeaae12517475c22695a200be45495516549Ben Murdoch  // We need a second deoptimization point after loading the value
4345086aeeaae12517475c22695a200be45495516549Ben Murdoch  // in case evaluating the property load my have a side effect.
43468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (assign_type == VARIABLE) {
43478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    PrepareForBailout(expr->expression(), TOS_REG);
43488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
4349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrepareForBailoutForId(prop->LoadId(), TOS_REG);
4350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Inline smi case if we are in a loop.
4353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, stub_call;
4354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpPatchSite patch_site(masm_);
4355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (ShouldInlineSmiCase(expr->op())) {
4356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label slow;
4357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patch_site.EmitJumpIfNotSmi(rax, &slow, Label::kNear);
4358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Save result for postfix expressions.
4360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (expr->is_postfix()) {
4361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!context()->IsEffect()) {
4362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Save the result on the stack. If we have a named or keyed property
4363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // we store the result under the receiver that is currently on top
4364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // of the stack.
4365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        switch (assign_type) {
4366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          case VARIABLE:
4367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ Push(rax);
4368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
4369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          case NAMED_PROPERTY:
4370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ movp(Operand(rsp, kPointerSize), rax);
4371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
4372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          case KEYED_PROPERTY:
4373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ movp(Operand(rsp, 2 * kPointerSize), rax);
4374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
4375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
4376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
4377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiOperationExecutionMode mode;
4380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mode.Add(PRESERVE_SOURCE_REGISTER);
4381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mode.Add(BAILOUT_ON_NO_OVERFLOW);
4382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (expr->op() == Token::INC) {
4383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ SmiAddConstant(rax, rax, Smi::FromInt(1), mode, &done, Label::kNear);
4384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ SmiSubConstant(rax, rax, Smi::FromInt(1), mode, &done, Label::kNear);
4386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&stub_call, Label::kNear);
4388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&slow);
43898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
4390086aeeaae12517475c22695a200be45495516549Ben Murdoch
4391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ToNumberStub convert_stub(isolate());
43921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ CallStub(&convert_stub);
4393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
4395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
43960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (!context()->IsEffect()) {
43970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Save the result on the stack. If we have a named or keyed property
43980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // we store the result under the receiver that is currently on top
43990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // of the stack.
44000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
44010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
4402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Push(rax);
44030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
44040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
4405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ movp(Operand(rsp, kPointerSize), rax);
44060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
44070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
4408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ movp(Operand(rsp, 2 * kPointerSize), rax);
44090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
44100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
4411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
4412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
4413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Record position before stub call.
4415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
4416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call stub for +1/-1.
4418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&stub_call);
4419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, rax);
4420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rax, Smi::FromInt(1));
4421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), expr->binary_op(),
4422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              NO_OVERWRITE).code();
4423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(code, expr->CountBinOpFeedbackId());
44243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
4425d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
4426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in rax.
4428e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
4429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case VARIABLE:
4430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
4431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
44320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        { EffectContext context(this);
44330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
44340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                 Token::ASSIGN);
4435086aeeaae12517475c22695a200be45495516549Ben Murdoch          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          context.Plug(rax);
44370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        }
4438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // For all contexts except kEffect: We have the result on
4439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
44400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
44410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
4442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
4443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
4444f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
4445e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
44460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                               Token::ASSIGN);
4447086aeeaae12517475c22695a200be45495516549Ben Murdoch        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        context()->Plug(rax);
4449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
4450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
4451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
4452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(StoreDescriptor::NameRegister(),
4453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              prop->key()->AsLiteral()->value());
4454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(StoreDescriptor::ReceiverRegister());
4455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallStoreIC(expr->CountStoreFeedbackId());
4456086aeeaae12517475c22695a200be45495516549Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
44580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
44590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
4460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
4461e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
44620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(rax);
4463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
4464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
4465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
4466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
4467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(StoreDescriptor::NameRegister());
4468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(StoreDescriptor::ReceiverRegister());
4469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Code> ic =
4470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code();
4471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallIC(ic, expr->CountStoreFeedbackId());
4472086aeeaae12517475c22695a200be45495516549Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4473e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
44740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
44750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
4476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
4477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
44780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(rax);
4479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
4480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
4481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
4482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
4483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4485d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
44860d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
448780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  VariableProxy* proxy = expr->AsVariableProxy();
4488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!context()->IsEffect());
4489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!context()->IsTest());
44900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4491589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (proxy != NULL && proxy->var()->IsUnallocated()) {
4492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment cmnt(masm_, "[ Global variable");
4493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(LoadDescriptor::NameRegister(), proxy->name());
4494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
4495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_vector_ics) {
4496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(VectorLoadICDescriptor::SlotRegister(),
4497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Smi::FromInt(proxy->VariableFeedbackSlot()));
4498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
449980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Use a regular load, not a contextual load, to avoid a reference
450080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // error.
4501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallLoadIC(NOT_CONTEXTUAL);
4502086aeeaae12517475c22695a200be45495516549Ben Murdoch    PrepareForBailout(expr, TOS_REG);
45030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
4504589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
4505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment cmnt(masm_, "[ Lookup slot");
450659151504615d929945dc59db37bf1166937748c6Steve Block    Label done, slow;
450759151504615d929945dc59db37bf1166937748c6Steve Block
450859151504615d929945dc59db37bf1166937748c6Steve Block    // Generate code for loading from variables potentially shadowed
450959151504615d929945dc59db37bf1166937748c6Steve Block    // by eval-introduced variables.
4510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done);
451159151504615d929945dc59db37bf1166937748c6Steve Block
451259151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
4513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rsi);
451480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ Push(proxy->name());
4515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
4516086aeeaae12517475c22695a200be45495516549Ben Murdoch    PrepareForBailout(expr, TOS_REG);
451759151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&done);
451859151504615d929945dc59db37bf1166937748c6Steve Block
45190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
4520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
452180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // This expression cannot throw a reference error at the top level.
45223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitInDuplicateContext(expr);
452380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
452480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
452580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
452680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
45273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
45283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Expression* sub_expr,
45293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Handle<String> check) {
45303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label materialize_true, materialize_false;
45313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* if_true = NULL;
45323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* if_false = NULL;
45333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* fall_through = NULL;
45343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
45353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         &if_true, &if_false, &fall_through);
45363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  { AccumulatorValueContext context(this);
45383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForTypeofValue(sub_expr);
45390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
45403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
45410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate()->factory();
4543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (String::Equals(check, factory->number_string())) {
4544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(rax, if_true);
4545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
454680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
454780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
4548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->string_string())) {
4549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(rax, if_false);
455080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
4551e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
4552e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ j(above_equal, if_false);
455380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
455480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen             Immediate(1 << Map::kIsUndetectable));
4555e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(zero, if_true, if_false, fall_through);
4556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->symbol_string())) {
4557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(rax, if_false);
4558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CmpObjectType(rax, SYMBOL_TYPE, rdx);
4559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Split(equal, if_true, if_false, fall_through);
4560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->boolean_string())) {
456180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
4562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
456380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kFalseValueRootIndex);
456480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
4565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->undefined_string())) {
456680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
4567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
4568e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(rax, if_false);
456980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => true.
4570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdx, FieldOperand(rax, HeapObject::kMapOffset));
457180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
457280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen             Immediate(1 << Map::kIsUndetectable));
457380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(not_zero, if_true, if_false, fall_through);
4574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->function_string())) {
4575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(rax, if_false);
45763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
45773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx);
45783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(equal, if_true);
45793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE);
45803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Split(equal, if_true, if_false, fall_through);
4581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->object_string())) {
4582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(rax, if_false);
4583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(rax, Heap::kNullValueRootIndex);
4584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(equal, if_true);
45853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ CmpObjectType(rax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, rdx);
4586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ j(below, if_false);
45873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
45883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ j(above, if_false);
458980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
459080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
4591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke             Immediate(1 << Map::kIsUndetectable));
4592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(zero, if_true, if_false, fall_through);
459380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
459480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (if_false != fall_through) __ jmp(if_false);
4595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
45963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->Plug(if_true, if_false);
4597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
4598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4600d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
460280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
4603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
46043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First we try a fast inlined version of the compare when one of
46053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the operands is a literal.
46063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (TryLiteralCompare(expr)) return;
46073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
4609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
4610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
4611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
4612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
461380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
46140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
46150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
461680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
46173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Token::Value op = expr->op();
46180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->left());
461980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
4620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
46210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
4622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
46233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
4624d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CompareRoot(rax, Heap::kTrueValueRootIndex);
462580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(equal, if_true, if_false, fall_through);
4626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
46273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4628d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
46290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
4630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      InstanceofStub stub(isolate(), InstanceofStub::kNoFlags);
4631d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
46323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ testp(rax, rax);
463480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen       // The stub returns 0 for true.
463580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(zero, if_true, if_false, fall_through);
4636d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
46400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->right());
4641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Condition cc = CompareIC::ComputeCondition(op);
4642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(rdx);
4643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
46440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      bool inline_smi_code = ShouldInlineSmiCase(op);
46451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      JumpPatchSite patch_site(masm_);
46460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (inline_smi_code) {
4647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Label slow_case;
4648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(rcx, rdx);
4649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ orp(rcx, rax);
4650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
4651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmpp(rdx, rax);
465280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Split(cc, if_true, if_false, NULL);
465380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&slow_case);
465480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
4655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
46561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Record position and call the compare IC.
46571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      SetSourcePosition(expr->position());
4658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
4659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallIC(ic, expr->CompareOperationFeedbackId());
46603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      patch_site.EmitPatchInfo();
4661086aeeaae12517475c22695a200be45495516549Ben Murdoch
46623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ testp(rax, rax);
466480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(cc, if_true, if_false, fall_through);
4665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
46663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
46673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
4669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
46700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
4671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
46743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
46753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              Expression* sub_expr,
46763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              NilValue nil) {
467780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
467880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
467980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
468080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
46810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
46820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
468380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
46843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitForAccumulatorValue(sub_expr);
46853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
46863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expr->op() == Token::EQ_STRICT) {
4687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Heap::RootListIndex nil_value = nil == kNullValue ?
4688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Heap::kNullValueRootIndex :
4689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Heap::kUndefinedValueRootIndex;
4690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(rax, nil_value);
469180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
469280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
4693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
4694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallIC(ic, expr->CompareOperationFeedbackId());
4695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ testp(rax, rax);
469680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(not_zero, if_true, if_false, fall_through);
469780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
46980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
469980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
470080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
470180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
4702d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
47040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
4705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
47080d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() {
47090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return rax;
47100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4712e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
47130d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() {
47140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return rsi;
47150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
47160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
47170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4718d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsAligned(frame_offset, kPointerSize));
4720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(Operand(rbp, frame_offset), value);
47213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
47223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
47233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4724d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
4725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(dst, ContextOperand(rsi, context_index));
4726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
47293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
47303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Scope* declaration_scope = scope()->DeclarationScope();
4731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (declaration_scope->is_global_scope() ||
4732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      declaration_scope->is_module_scope()) {
4733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Contexts nested in the native context have a canonical empty function
47343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // as their closure, not the anonymous closure containing the global
47353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // code.  Pass a smi sentinel and let the runtime look up the empty
47363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // function.
47373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ Push(Smi::FromInt(0));
47383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else if (declaration_scope->is_eval_scope()) {
47393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Contexts created by a call to eval have the same closure as the
47403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // context calling eval, not the anonymous closure containing the eval
47413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // code.  Fetch it from the context.
4742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(ContextOperand(rsi, Context::CLOSURE_INDEX));
47433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
4744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(declaration_scope->is_function_scope());
4745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
47463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
47473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
47483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ----------------------------------------------------------------------------
4751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support.
4752e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4754d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() {
4755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result_register().is(rdx));
4756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result_register().is(rcx));
4757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Cook return address on top of stack (smi encoded Code* delta)
4758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PopReturnAddressTo(rdx);
4759e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, masm_->CodeObject());
4760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(rdx, rcx);
4761e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Integer32ToSmi(rdx, rdx);
4762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rdx);
4763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store result register while executing finally block.
4765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(result_register());
4766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Store pending message while executing finally block.
4768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference pending_message_obj =
4769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_pending_message_obj(isolate());
4770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Load(rdx, pending_message_obj);
4771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rdx);
4772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference has_pending_message =
4774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_has_pending_message(isolate());
4775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Load(rdx, has_pending_message);
4776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Integer32ToSmi(rdx, rdx);
4777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rdx);
4778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference pending_message_script =
4780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_pending_message_script(isolate());
4781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Load(rdx, pending_message_script);
4782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rdx);
4783e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4785e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4786d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() {
4787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result_register().is(rdx));
4788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result_register().is(rcx));
4789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore pending message from stack.
4790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rdx);
4791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference pending_message_script =
4792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_pending_message_script(isolate());
4793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Store(pending_message_script, rdx);
4794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rdx);
4796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(rdx, rdx);
4797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference has_pending_message =
4798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_has_pending_message(isolate());
4799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Store(has_pending_message, rdx);
4800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rdx);
4802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference pending_message_obj =
4803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_pending_message_obj(isolate());
4804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Store(pending_message_obj, rdx);
4805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore result register from stack.
4807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(result_register());
4808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4809e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Uncook return address.
4810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rdx);
4811e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ SmiToInteger32(rdx, rdx);
4812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ Move(rcx, masm_->CodeObject());
4813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(rdx, rcx);
48143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(rdx);
4815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
4816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef __
4819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
482069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#define __ ACCESS_MASM(masm())
482169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
482269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochFullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
482369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int* stack_depth,
482469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int* context_length) {
482569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // The macros used here must preserve the result register.
482669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
482769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Because the handler block contains the context of the finally
482869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // code, we can restore it directly from there for the finally code
482969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // rather than iteratively unwinding contexts via their previous
483069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // links.
483169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ Drop(*stack_depth);  // Down to the handler block.
483269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (*context_length > 0) {
483369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Restore the context to its dedicated register and the stack.
4834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rsi, Operand(rsp, StackHandlerConstants::kContextOffset));
4835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
483669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
483769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ PopTryHandler();
483869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ call(finally_entry_);
483969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
484069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  *stack_depth = 0;
484169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  *context_length = 0;
484269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return previous_;
484369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
484469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
484569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
484669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#undef __
4847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kJnsInstruction = 0x79;
4850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kNopByteOne = 0x66;
4851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kNopByteTwo = 0x90;
4852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
4853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kCallInstruction = 0xe8;
4854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
4855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BackEdgeTable::PatchAt(Code* unoptimized_code,
4858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Address pc,
4859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            BackEdgeState target_state,
4860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Code* replacement_code) {
4861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address call_target_address = pc - kIntSize;
4862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address jns_instr_address = call_target_address - 3;
4863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address jns_offset_address = call_target_address - 2;
4864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (target_state) {
4866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case INTERRUPT:
4867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //     sub <profiling_counter>, <delta>  ;; Not changed
4868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //     jns ok
4869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //     call <interrupt stub>
4870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ok:
4871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *jns_instr_address = kJnsInstruction;
4872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *jns_offset_address = kJnsOffset;
4873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
4874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case ON_STACK_REPLACEMENT:
4875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case OSR_AFTER_STACK_CHECK:
4876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //     sub <profiling_counter>, <delta>  ;; Not changed
4877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //     nop
4878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //     nop
4879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //     call <on-stack replacment>
4880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ok:
4881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *jns_instr_address = kNopByteOne;
4882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *jns_offset_address = kNopByteTwo;
4883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
4884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler::set_target_address_at(call_target_address,
4887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   unoptimized_code,
4888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   replacement_code->entry());
4889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
4890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      unoptimized_code, call_target_address, replacement_code);
4891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
4895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Isolate* isolate,
4896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Code* unoptimized_code,
4897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Address pc) {
4898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address call_target_address = pc - kIntSize;
4899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address jns_instr_address = call_target_address - 3;
4900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(kCallInstruction, *(call_target_address - 1));
4901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (*jns_instr_address == kJnsInstruction) {
4903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(kJnsOffset, *(call_target_address - 2));
4904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(),
4905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Assembler::target_address_at(call_target_address,
4906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           unoptimized_code));
4907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return INTERRUPT;
4908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(kNopByteOne, *jns_instr_address);
4911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(kNopByteTwo, *(call_target_address - 2));
4912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (Assembler::target_address_at(call_target_address,
4914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   unoptimized_code) ==
4915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate->builtins()->OnStackReplacement()->entry()) {
4916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return ON_STACK_REPLACEMENT;
4917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Assembler::target_address_at(call_target_address,
4921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         unoptimized_code));
4922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return OSR_AFTER_STACK_CHECK;
4923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} }  // namespace v8::internal
4927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
4929