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#if V8_TARGET_ARCH_X64
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/assembler-inl.h"
8f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/ast/compile-time-value.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ast/scopes.h"
1062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/builtins/builtins-constructor.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h"
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
14f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/compilation-info.h"
15f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/compiler.h"
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h"
1762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/full-codegen/full-codegen.h"
1862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/heap/heap-inl.h"
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h"
2062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h"
213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 {
233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal {
243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
25109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define __ ACCESS_MASM(masm())
261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass JumpPatchSite BASE_EMBEDDED {
281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
29589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    info_emitted_ = false;
321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ~JumpPatchSite() {
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(patch_site_.is_bound() == info_emitted_);
371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
39257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitJumpIfNotSmi(Register reg,
40257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        Label* target,
41257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        Label::Distance near_jump = Label::kFar) {
421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ testb(reg, Immediate(kSmiTagMask));
43257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EmitJump(not_carry, target, near_jump);   // Always taken before patched.
441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
46257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitJumpIfSmi(Register reg,
47257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     Label* target,
48257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     Label::Distance near_jump = Label::kFar) {
491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ testb(reg, Immediate(kSmiTagMask));
50257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EmitJump(carry, target, near_jump);  // Never taken before patched.
511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EmitPatchInfo() {
543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (patch_site_.is_bound()) {
553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(is_uint8(delta_to_patch_site));
573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ testl(rax, Immediate(delta_to_patch_site));
581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      info_emitted_ = true;
601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ nop();  // Signals no inlined code.
633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // jc will be patched with jz, jnc will become jnz.
68257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitJump(Condition cc, Label* target, Label::Distance near_jump) {
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!patch_site_.is_bound() && !info_emitted_);
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(cc == carry || cc == not_carry);
711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&patch_site_);
72257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(cc, target, near_jump);
731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
75109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  MacroAssembler* masm() { return masm_; }
761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  MacroAssembler* masm_;
771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Label patch_site_;
781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool info_emitted_;
801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function.  On entry to the function the receiver
853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, with the
863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them.  The actual argument count matches the
873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function.
883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are:
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   o rdi: the JS function object being called (i.e. ourselves)
91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//   o rdx: the new target value
923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rsi: our context
933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rbp: our caller's frame pointer
943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o rsp: stack pointer (pointing to return address)
953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame.  Please see JavaScriptFrameConstants in
973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-x64.h for its layout.
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::Generate() {
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompilationInfo* info = info_;
100f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK_EQ(scope(), info->scope());
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  profiling_counter_ = isolate()->factory()->NewCell(
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetFunctionPosition(literal());
1046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comment cmnt(masm_, "[ function compiled by full code generator");
1053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProfileEntryHookStub::MaybeCallEntryHook(masm_);
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    StackArgumentsAccessor args(rsp, info->scope()->num_parameters());
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rcx, args.GetReceiverOperand());
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ AssertNotSmi(rcx);
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CmpObjectType(rcx, FIRST_JS_RECEIVER_TYPE, rcx);
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Assert(above_equal, kSloppyFunctionExpectsJSReceiverReceiver);
114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Open a frame scope to indicate that there is a frame on the stack.  The
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // MANUAL indicates that the scope shouldn't actually generate code to set up
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the frame (that is done below).
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameScope frame_scope(masm_, StackFrame::MANUAL);
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info->set_prologue_offset(masm_->pc_offset());
122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Prologue(info->GeneratePreagedPrologue());
123756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
124f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Increment invocation count for the function.
125f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  {
126f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Comment cmnt(masm_, "[ Increment invocation count");
12762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ movp(rcx, FieldOperand(rdi, JSFunction::kFeedbackVectorOffset));
12862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ movp(rcx, FieldOperand(rcx, Cell::kValueOffset));
129f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    __ SmiAddConstant(
13062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        FieldOperand(rcx, FeedbackVector::kInvocationCountIndex * kPointerSize +
13162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                              FeedbackVector::kHeaderSize),
132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        Smi::FromInt(1));
133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
134f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  { Comment cmnt(masm_, "[ Allocate locals");
1363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int locals_count = info->scope()->num_stack_slots();
137109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    OperandStackDepthIncrement(locals_count);
138756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (locals_count == 1) {
139756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ PushRoot(Heap::kUndefinedValueRootIndex);
140756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else if (locals_count > 1) {
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (locals_count >= 128) {
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label ok;
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(rcx, rsp);
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ subp(rcx, Immediate(locals_count * kPointerSize));
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ CompareRoot(rcx, Heap::kRealStackLimitRootIndex);
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ j(above_equal, &ok, Label::kNear);
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ CallRuntime(Runtime::kThrowStackOverflow);
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ bind(&ok);
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const int kMaxPushes = 32;
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (locals_count >= kMaxPushes) {
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int loop_iterations = locals_count / kMaxPushes;
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(rcx, Immediate(loop_iterations));
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label loop_header;
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ bind(&loop_header);
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Do pushes.
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        for (int i = 0; i < kMaxPushes; i++) {
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ Push(rax);
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Continue loop if not done.
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ decp(rcx);
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ j(not_zero, &loop_header, Label::kNear);
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int remaining = locals_count % kMaxPushes;
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Emit the remaining pushes.
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (int i  = 0; i < remaining; i++) {
168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ Push(rax);
169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
171756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
173756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  bool function_in_register = true;
1744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
175756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate a local context.
176f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (info->scope()->NeedsContext()) {
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment cmnt(masm_, "[ Allocate context");
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool need_write_barrier = true;
179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
180756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Argument to NewContext is the function, which is still in rdi.
181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (info->scope()->is_script_scope()) {
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rdi);
183f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      __ Push(info->scope()->scope_info());
184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ CallRuntime(Runtime::kNewScriptContext);
185bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(BailoutId::ScriptContext(),
186bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             BailoutState::TOS_REGISTER);
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // The new target value is not used, clobbering is safe.
188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK_NULL(info->scope()->new_target_var());
189756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (info->scope()->new_target_var() != nullptr) {
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ Push(rdx);  // Preserve new target.
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
19362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (slots <=
19462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          ConstructorBuiltinsAssembler::MaximumFunctionContextSlots()) {
19562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Callable callable = CodeFactory::FastNewFunctionContext(
19662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            isolate(), info->scope()->scope_type());
197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ Set(FastNewFunctionContextDescriptor::SlotsRegister(), slots);
19862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ Call(callable.code(), RelocInfo::CODE_TARGET);
19962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // Result of the FastNewFunctionContext builtin is always in new space.
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        need_write_barrier = false;
201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ Push(rdi);
20362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ Push(Smi::FromInt(info->scope()->scope_type()));
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ CallRuntime(Runtime::kNewFunctionContext);
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (info->scope()->new_target_var() != nullptr) {
207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ Pop(rdx);  // Restore new target.
208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
209756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
210756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    function_in_register = false;
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Context is returned in rax.  It replaces the context passed to us.
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // It's saved in the stack and kept live in rsi.
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rsi, rax);
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax);
215756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
216756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Copy any necessary parameters into the context.
2173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int num_parameters = info->scope()->num_parameters();
218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int first_parameter = info->scope()->has_this_declaration() ? -1 : 0;
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (int i = first_parameter; i < num_parameters; i++) {
220f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Variable* var =
221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          (i == -1) ? info->scope()->receiver() : info->scope()->parameter(i);
222589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (var->IsContextSlot()) {
223756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
224756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick            (num_parameters - 1 - i) * kPointerSize;
225756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Load parameter from stack.
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(rax, Operand(rbp, parameter_offset));
227756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Store it in the context.
228589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        int context_offset = Context::SlotOffset(var->index());
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(Operand(rsi, context_offset), rax);
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Update the write barrier.  This clobbers rax and rbx.
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (need_write_barrier) {
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ RecordWriteContextSlot(
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              rsi, context_offset, rax, rbx, kDontSaveFPRegs);
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (FLAG_debug_code) {
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Label done;
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ JumpIfInNewSpace(rsi, rax, &done, Label::kNear);
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Abort(kExpectedNewSpaceObject);
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ bind(&done);
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
242756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
2433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Register holding this function and new target are both trashed in case we
245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // bailout here. But since that can happen only when new target is not used
246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // and we allocate a context, the value of |function_in_register| is correct.
247bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(BailoutId::FunctionContext(),
248bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                         BailoutState::NO_REGISTERS);
249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
25062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // We don't support new.target and rest parameters here.
25162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_NULL(info->scope()->new_target_var());
25262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_NULL(info->scope()->rest_parameter());
25362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_NULL(info->scope()->this_function_var());
254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
255756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate an arguments object.
256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK_EQ(scope(), info->scope());
257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Variable* arguments = info->scope()->arguments();
258756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (arguments != NULL) {
259756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Arguments object must be allocated after the context object, in
260756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // case the "arguments" or ".arguments" variables are in the context.
261756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate arguments object");
262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!function_in_register) {
263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
265109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (is_strict(language_mode()) || !has_simple_parameters()) {
26662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ call(isolate()->builtins()->FastNewStrictArguments(),
26762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              RelocInfo::CODE_TARGET);
26862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      RestoreContext();
269109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    } else if (literal()->has_duplicate_parameters()) {
270109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Push(rdi);
271109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ CallRuntime(Runtime::kNewSloppyArguments_Generic);
272109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    } else {
27362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ call(isolate()->builtins()->FastNewSloppyArguments(),
27462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              RelocInfo::CODE_TARGET);
27562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      RestoreContext();
276109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
27744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
278589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SetVar(arguments, rax, rbx, rdx);
279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace) {
282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallRuntime(Runtime::kTraceEnter);
283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Visit the declarations and body unless there is an illegal
286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // redeclaration.
287bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(BailoutId::FunctionEntry(),
288bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                         BailoutState::NO_REGISTERS);
2893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Comment cmnt(masm_, "[ Declarations");
291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    VisitDeclarations(info->scope()->declarations());
2923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
293589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Assert that the declarations do not use ICs. Otherwise the debugger
2953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // won't be able to redirect a PC at an IC to the correct IC in newly
2963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // recompiled code.
2973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(0, ic_total_count_);
2983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
3003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Comment cmnt(masm_, "[ Stack check");
301bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(BailoutId::Declarations(),
302bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           BailoutState::NO_REGISTERS);
3033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Label ok;
3043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
3053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ j(above_equal, &ok, Label::kNear);
3063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET);
3073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ bind(&ok);
3083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
3113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Comment cmnt(masm_, "[ Body");
3123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(loop_depth() == 0);
3133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    VisitStatements(literal()->body());
3143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(loop_depth() == 0);
3153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
3163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Always emit a 'return undefined' in case control fell off the end of
318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the body.
3193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
3203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
3217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    EmitReturnSequence();
322d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
324d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
326db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdochvoid FullCodeGenerator::ClearAccumulator() {
3279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ Set(rax, 0);
328db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch}
329db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
330db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset),
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    Smi::FromInt(-delta));
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitProfilingCounterReset() {
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int reset_value = FLAG_interrupt_budget;
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(kScratchRegister, Smi::FromInt(reset_value));
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister);
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kJnsOffset = kPointerSize == kInt64Size ? 0x1d : 0x14;
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Label* back_edge_target) {
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ Back edge bookkeeping");
352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label ok;
353e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(back_edge_target->is_bound());
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int weight = Min(kMaxBackEdgeWeight,
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Max(1, distance / kCodeSizeMultiplier));
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitProfilingCounterDecrement(weight);
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(positive, &ok, Label::kNear);
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PredictableCodeSizeScope predictible_code_size_scope(masm_, kJnsOffset);
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DontEmitDebugCodeScope dont_emit_debug_code_scope(masm_);
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Record a mapping of this PC offset to the OSR id.  This is used to find
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the AST id from the unoptimized code in order to use it as a key into
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the deoptimization input data found in the optimized code.
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordBackEdge(stmt->OsrEntryId());
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitProfilingCounterReset();
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&ok);
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
375bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
376086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Record a mapping of the OSR id to this PC.  This is used if the OSR
377086aeeaae12517475c22695a200be45495516549Ben Murdoch  // entry becomes the target of a bailout.  We don't expect it to be, but
378086aeeaae12517475c22695a200be45495516549Ben Murdoch  // we want it to work if it is.
379bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
382109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
383109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    bool is_tail_call) {
384109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Pretend that the exit is a backwards jump to the entry.
385109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int weight = 1;
386109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (info_->ShouldSelfOptimize()) {
387109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    weight = FLAG_interrupt_budget / FLAG_self_opt_count;
388109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
389109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int distance = masm_->pc_offset();
390109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    weight = Min(kMaxBackEdgeWeight, Max(1, distance / kCodeSizeMultiplier));
391109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
392109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  EmitProfilingCounterDecrement(weight);
393109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label ok;
394109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ j(positive, &ok, Label::kNear);
395109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Don't need to save result register if we are going to do a tail call.
396109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!is_tail_call) {
397109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Push(rax);
398109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
399109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
400109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!is_tail_call) {
401109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Pop(rax);
402109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
403109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  EmitProfilingCounterReset();
404109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bind(&ok);
405109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() {
408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ jmp(&return_label_);
411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
412d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
4133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rax);
415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ CallRuntime(Runtime::kTraceExit);
4163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
417109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    EmitProfilingCounterHandlingForReturnSequence(false);
4181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SetReturnPosition(literal());
420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ leave();
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int arg_count = info_->scope()->num_parameters() + 1;
423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int arguments_bytes = arg_count * kPointerSize;
424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ret(arguments_bytes, rcx);
4253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
4263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
4273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
428bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid FullCodeGenerator::RestoreContext() {
429bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
430bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
4313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
432589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
434589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand operand = codegen()->VarOperand(var, result_register());
435109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  codegen()->PushOperand(operand);
436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4390d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4430d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
4440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
4450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), index);
4460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4490d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
4500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
451109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  codegen()->OperandStackDepthIncrement(1);
4520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ PushRoot(index);
4530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4560d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
4610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (index == Heap::kUndefinedValueRootIndex ||
4620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kNullValueRootIndex ||
4630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      index == Heap::kFalseValueRootIndex) {
464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (false_label_ != fall_through_) __ jmp(false_label_);
4650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (index == Heap::kTrueValueRootIndex) {
466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (true_label_ != fall_through_) __ jmp(true_label_);
4670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
4680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ LoadRoot(result_register(), index);
4693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    codegen()->DoTest(this);
470e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4740d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
4750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4780d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
4790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Handle<Object> lit) const {
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (lit->IsSmi()) {
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SafeMove(result_register(), Smi::cast(*lit));
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(result_register(), lit);
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4880d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
489109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  codegen()->OperandStackDepthIncrement(1);
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (lit->IsSmi()) {
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SafePush(Smi::cast(*lit));
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(lit);
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4980d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
50362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(lit->IsNullOrUndefined(isolate()) || !lit->IsUndetectable());
50462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (lit->IsNullOrUndefined(isolate()) || lit->IsFalse(isolate())) {
505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (false_label_ != fall_through_) __ jmp(false_label_);
50613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (true_label_ != fall_through_) __ jmp(true_label_);
5080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsString()) {
5090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (String::cast(*lit)->length() == 0) {
510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (false_label_ != fall_through_) __ jmp(false_label_);
5110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ jmp(true_label_);
5130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
5140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsSmi()) {
5150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (Smi::cast(*lit)->value() == 0) {
516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (false_label_ != fall_through_) __ jmp(false_label_);
5170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ jmp(true_label_);
5190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
5200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
5210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // For simplicity we always test the accumulator register.
5220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ Move(result_register(), lit);
5233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    codegen()->DoTest(this);
524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5280d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count,
5290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                       Register reg) const {
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(count > 0);
531109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (count > 1) codegen()->DropOperands(count - 1);
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(Operand(rsp, 0), reg);
533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5360d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
5370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            Label* materialize_false) const {
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(materialize_true == materialize_false);
5390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
5400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
541e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5430d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
5440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
5450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
5470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
54844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(result_register(), isolate()->factory()->true_value());
549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&done, Label::kNear);
5500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
55144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(result_register(), isolate()->factory()->false_value());
5520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5560d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
5570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
5580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
559109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  codegen()->OperandStackDepthIncrement(1);
560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
5610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
56244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Push(isolate()->factory()->true_value());
563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&done, Label::kNear);
5640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
56544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Push(isolate()->factory()->false_value());
5660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
5670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5700d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true,
5710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                          Label* materialize_false) const {
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(materialize_true == true_label_);
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(materialize_false == false_label_);
5740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5770d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
5780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
5790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
5800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadRoot(result_register(), value_root_index);
5810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5840d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const {
585109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  codegen()->OperandStackDepthIncrement(1);
5860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Heap::RootListIndex value_root_index =
5870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
5880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ PushRoot(value_root_index);
5890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5920d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const {
5933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
594086aeeaae12517475c22695a200be45495516549Ben Murdoch                                          true,
595086aeeaae12517475c22695a200be45495516549Ben Murdoch                                          true_label_,
596086aeeaae12517475c22695a200be45495516549Ben Murdoch                                          false_label_);
5970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (flag) {
5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (true_label_ != fall_through_) __ jmp(true_label_);
5990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
6000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (false_label_ != fall_through_) __ jmp(false_label_);
601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
6053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::DoTest(Expression* condition,
6063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               Label* if_true,
60780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* if_false,
60880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* fall_through) {
6093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(ic, condition->test_id());
611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Split(equal, if_true, if_false, fall_through);
61380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
61680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::Split(Condition cc,
61780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_true,
61880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_false,
61980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* fall_through) {
62080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (if_false == fall_through) {
62180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(cc, if_true);
62280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (if_true == fall_through) {
62380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(NegateCondition(cc), if_false);
62480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
62580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(cc, if_true);
62680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ jmp(if_false);
627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
631589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) {
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsStackAllocated());
633589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Offset is negative because higher indexes are at lower addresses.
634589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int offset = -var->index() * kPointerSize;
635589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Adjust by a (parameter or local) base offset.
636589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsParameter()) {
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    offset += kFPOnStackSize + kPCOnStackSize +
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              (info_->scope()->num_parameters() - 1) * kPointerSize;
639589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else {
640589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    offset += JavaScriptFrameConstants::kLocal0Offset;
641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
642589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return Operand(rbp, offset);
643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
644d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
646589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
648589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsContextSlot()) {
649589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    int context_chain_length = scope()->ContextChainLength(var->scope());
650589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ LoadContext(scratch, context_chain_length);
651589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return ContextOperand(scratch, var->index());
652589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else {
653589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return StackOperand(var);
654589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
658589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) {
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
660589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand location = VarOperand(var, dest);
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(dest, location);
662589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
663589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
664589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
665589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::SetVar(Variable* var,
666589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register src,
667589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register scratch0,
668589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register scratch1) {
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch0.is(src));
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch0.is(scratch1));
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch1.is(src));
673589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand location = VarOperand(var, scratch0);
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(location, src);
6753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
677589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsContextSlot()) {
678589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    int offset = Context::SlotOffset(var->index());
6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
681d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     bool should_normalize,
686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_true,
687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_false) {
688086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Only prepare for bailouts before splits if we're in a test
689086aeeaae12517475c22695a200be45495516549Ben Murdoch  // context. Otherwise, we let the Visit function deal with the
690086aeeaae12517475c22695a200be45495516549Ben Murdoch  // preparation to avoid preparing with the same AST id twice.
691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!context()->IsTest()) return;
692086aeeaae12517475c22695a200be45495516549Ben Murdoch
693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label skip;
694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (should_normalize) __ jmp(&skip, Label::kNear);
695bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
696086aeeaae12517475c22695a200be45495516549Ben Murdoch  if (should_normalize) {
697086aeeaae12517475c22695a200be45495516549Ben Murdoch    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
698086aeeaae12517475c22695a200be45495516549Ben Murdoch    Split(equal, if_true, if_false, NULL);
699086aeeaae12517475c22695a200be45495516549Ben Murdoch    __ bind(&skip);
700086aeeaae12517475c22695a200be45495516549Ben Murdoch  }
701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The variable in the declaration always resides in the current context.
706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, scope()->ContextChainLength(variable->scope()));
707109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (FLAG_debug_code) {
708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check that we're not inside a with or catch context.
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rbx, FieldOperand(rsi, HeapObject::kMapOffset));
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(rbx, Heap::kWithContextMapRootIndex);
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(not_equal, kDeclarationInWithContext);
712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(not_equal, kDeclarationInCatchContext);
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitVariableDeclaration(
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VariableDeclaration* declaration) {
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VariableProxy* proxy = declaration->proxy();
721589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Variable* variable = proxy->var();
722589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (variable->location()) {
723f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case VariableLocation::UNALLOCATED: {
724bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      DCHECK(!variable->binding_needs_init());
72562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      globals_->Add(variable->name(), zone());
72662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      FeedbackSlot slot = proxy->VariableFeedbackSlot();
727f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK(!slot.IsInvalid());
728f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
729bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      globals_->Add(isolate()->factory()->undefined_value(), zone());
73062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      globals_->Add(isolate()->factory()->undefined_value(), zone());
731589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
732f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::PARAMETER:
734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::LOCAL:
735f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (variable->binding_needs_init()) {
736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment cmnt(masm_, "[ VariableDeclaration");
73769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(StackOperand(variable), kScratchRegister);
739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
74069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::CONTEXT:
743f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (variable->binding_needs_init()) {
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment cmnt(masm_, "[ VariableDeclaration");
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        EmitDebugCheckDeclarationContext(variable);
74669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(ContextOperand(rsi, variable->index()), kScratchRegister);
74869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // No write barrier since the hole value is in old space.
749bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
75069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
75169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
75362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VariableLocation::LOOKUP:
754f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case VariableLocation::MODULE:
755f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UNREACHABLE();
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitFunctionDeclaration(
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FunctionDeclaration* declaration) {
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VariableProxy* proxy = declaration->proxy();
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Variable* variable = proxy->var();
764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (variable->location()) {
765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::UNALLOCATED: {
76662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      globals_->Add(variable->name(), zone());
76762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      FeedbackSlot slot = proxy->VariableFeedbackSlot();
76862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      DCHECK(!slot.IsInvalid());
76962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
77062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
77162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // We need the slot where the literals array lives, too.
77262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      slot = declaration->fun()->LiteralFeedbackSlot();
773f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK(!slot.IsInvalid());
774f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
77562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<SharedFunctionInfo> function =
777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Check for stack-overflow exception.
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (function.is_null()) return SetStackOverflow();
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      globals_->Add(function, zone());
78169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::PARAMETER:
785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::LOCAL: {
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ FunctionDeclaration");
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(declaration->fun());
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(StackOperand(variable), result_register());
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::CONTEXT: {
793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ FunctionDeclaration");
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitDebugCheckDeclarationContext(variable);
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitForAccumulatorValue(declaration->fun());
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(ContextOperand(rsi, variable->index()), result_register());
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int offset = Context::SlotOffset(variable->index());
798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // We know that we have written a function, which is not a smi.
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ RecordWriteContextSlot(rsi,
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                offset,
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                result_register(),
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                rcx,
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                kDontSaveFPRegs,
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                EMIT_REMEMBERED_SET,
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                OMIT_SMI_CHECK);
806bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
81062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VariableLocation::LOOKUP:
811f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case VariableLocation::MODULE:
812f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UNREACHABLE();
813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
817d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
8183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
8193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Push(pairs);
820589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ Push(Smi::FromInt(DeclareGlobalsFlags()));
82162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ EmitLoadFeedbackVector(rax);
822f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ Push(rax);
823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CallRuntime(Runtime::kDeclareGlobals);
8243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
8253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ SwitchStatement");
830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Breakable nested_statement(this, stmt);
831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
832086aeeaae12517475c22695a200be45495516549Ben Murdoch
833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Keep the switch value on the stack until a case matches.
8340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(stmt->tag());
835bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<CaseClause*>* clauses = stmt->cases();
838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label next_test;  // Recycled for each test.
841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the tests with branches to their bodies.
842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
8448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    clause->body_target()->Unuse();
8451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The default is not a test, but remember it as final fall through.
847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (clause->is_default()) {
848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      default_clause = clause;
849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      continue;
850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case comparison");
853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&next_test);
854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    next_test.Unuse();
855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Compile the label expression.
8570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(clause->label());
858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
85980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Perform the comparison as if via '==='.
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdx, Operand(rsp, 0));  // Switch value.
8610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
8621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    JumpPatchSite patch_site(masm_);
8630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (inline_smi_code) {
864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label slow_case;
865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(rcx, rdx);
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ orp(rcx, rax);
867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
8681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmpp(rdx, rax);
87080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(not_equal, &next_test);
87180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ Drop(1);  // Switch value is no longer needed.
8728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      __ jmp(clause->body_target());
87380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&slow_case);
87480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
8761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Record position before stub call for type feedback.
877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SetExpressionPosition(clause);
878109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Handle<Code> ic =
879109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallIC(ic, clause->CompareId());
8813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    patch_site.EmitPatchInfo();
8821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label skip;
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&skip, Label::kNear);
885bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, &next_test);
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Drop(1);
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(clause->body_target());
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&skip);
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ testp(rax, rax);
893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(not_equal, &next_test);
894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
8958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ jmp(clause->body_target());
896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Discard the test value and jump to the default if present, otherwise to
899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the end of the statement.
900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&next_test);
901109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DropOperands(1);  // Switch value is no longer needed.
902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (default_clause == NULL) {
90369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ jmp(nested_statement.break_label());
904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
9058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ jmp(default_clause->body_target());
906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the case bodies.
909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case body");
911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
9128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ bind(clause->body_target());
913bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitStatements(clause->statements());
915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
91769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(nested_statement.break_label());
918bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ ForInStatement");
924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetStatementPosition(stmt, SKIP_BREAK);
925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
92662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  FeedbackSlot slot = stmt->ForInFeedbackSlot();
927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
928109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Get the object to enumerate over.
929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionAsStatementPosition(stmt->enumerable());
9300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(stmt->enumerable());
9313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  OperandStackDepthIncrement(5);
9323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
9333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label loop, exit;
9343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Iteration loop_statement(this, stmt);
9353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  increment_loop_depth();
9363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
937109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // If the object is null or undefined, skip over the loop, otherwise convert
938109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // it to a JS receiver.  See ECMA-262 version 5, section 12.6.4.
939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label convert, done_convert;
940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ JumpIfSmi(rax, &convert, Label::kNear);
941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rcx);
942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ j(above_equal, &done_convert, Label::kNear);
943109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CompareRoot(rax, Heap::kNullValueRootIndex);
944109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ j(equal, &exit);
945109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
946109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ j(equal, &exit);
947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&convert);
948c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Call(isolate()->builtins()->ToObject(), RelocInfo::CODE_TARGET);
949f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RestoreContext();
950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done_convert);
951bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);
953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
954bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Check cache validity in generated code. If we cannot guarantee cache
955bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // validity, call the runtime system to check cache validity or get the
956bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // property names in a fixed array. Note: Proxies never have an enum cache,
957bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // so will always take the slow path.
958109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label call_runtime;
959109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CheckEnumCache(&call_runtime);
960e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
961e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // The enum cache is valid.  Load the map of the object being
962e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // iterated over and use the cache for the iteration.
963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label use_cache;
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&use_cache, Label::kNear);
966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the set of properties to enumerate.
968e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&call_runtime);
969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);  // Duplicate the enumerable object on the stack.
970109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CallRuntime(Runtime::kForInEnumerate);
971bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If we got a map from the runtime call, we can do a fast
974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // modification check. Otherwise, we got a fixed array, and we have
975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // to do a slow check.
976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fixed_array;
977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 Heap::kMetaMapRootIndex);
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &fixed_array);
980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a map in register rax. Get the enumeration cache from it.
982e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&use_cache);
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_descriptors;
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ EnumLength(rdx, rax);
987c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Cmp(rdx, Smi::kZero);
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &no_descriptors);
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadInstanceDescriptors(rax, rcx);
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheOffset));
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the four remaining stack slots.
995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);  // Map.
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rcx);  // Enumeration cache.
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rdx);  // Number of valid entries for the map in the enum cache.
998c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Push(Smi::kZero);  // Initial index.
999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
1000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&no_descriptors);
1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(rsp, Immediate(kPointerSize));
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&exit);
1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a fixed array in register rax. Iterate through that.
1006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&fixed_array);
10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, Operand(rsp, 0 * kPointerSize));  // Get enumerated object
1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Push(Smi::FromInt(1));                      // Smi(1) indicates slow check
1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);  // Array
1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, FieldOperand(rax, FixedArray::kLengthOffset));
1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);  // Fixed array length (as smi).
1013bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
1014c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Push(Smi::kZero);  // Initial index.
1015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for doing the condition check.
1017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&loop);
1018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionAsStatementPosition(stmt->each());
1019958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, Operand(rsp, 0 * kPointerSize));  // Get the current index.
1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rax, Operand(rsp, 1 * kPointerSize));  // Compare to the array length.
102269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ j(above_equal, loop_statement.break_label());
1023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1024f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Get the current entry of the array into register rax.
1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, Operand(rsp, 2 * kPointerSize));
1026f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2);
1027f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ movp(rax,
1028f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          FieldOperand(rbx, index.reg, index.scale, FixedArray::kHeaderSize));
1029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the expected map from the stack or a smi in the
1031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // permanent slow case into register rdx.
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, Operand(rsp, 3 * kPointerSize));
1033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the expected map still matches that of the enumerable.
10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If not, we may have to filter the key.
1036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label update_each;
1037f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ movp(rbx, Operand(rsp, 4 * kPointerSize));
1038f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ cmpp(rdx, FieldOperand(rbx, HeapObject::kMapOffset));
1039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &update_each, Label::kNear);
1040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // We need to filter the key, record slow-path here.
10423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int const vector_index = SmiFromSlot(slot)->value();
104362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ EmitLoadFeedbackVector(rdx);
1044109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Move(FieldOperand(rdx, FixedArray::OffsetOfElementAt(vector_index)),
104562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          FeedbackVector::MegamorphicSentinel(isolate()));
1046109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1047c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // rax contains the key. The receiver in rbx is the second argument to
1048c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // ForInFilter. ForInFilter returns undefined if the receiver doesn't
1049f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // have the key or returns the name-converted key.
1050c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Call(isolate()->builtins()->ForInFilter(), RelocInfo::CODE_TARGET);
1051f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RestoreContext();
1052bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
1053f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ JumpIfRoot(result_register(), Heap::kUndefinedValueRootIndex,
1054f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                loop_statement.continue_label());
1055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the 'each' property or variable from the possibly filtered
1057f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // entry in register rax.
1058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&update_each);
1059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Perform the assignment as if via '='.
1060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { EffectContext context(this);
1061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
1062bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
1063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
1066bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
1067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the body of the loop.
1068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Visit(stmt->body());
1069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for going to the next element by incrementing the
1071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // index (smi) stored on top of the stack.
107269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.continue_label());
1073f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  PrepareForBailoutForId(stmt->IncrementId(), BailoutState::NO_REGISTERS);
1074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1));
1075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBackEdgeBookkeeping(stmt, &loop);
1077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ jmp(&loop);
1078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Remove the pointers stored on the stack.
108069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.break_label());
10813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DropOperands(5);
1082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Exit and decrement the loop depth.
1084bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
1085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
1086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  decrement_loop_depth();
1087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
10883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
109062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                          FeedbackSlot slot) {
1091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(NeedsHomeObject(initializer));
1092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
1093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ movp(StoreDescriptor::ValueRegister(),
1094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Operand(rsp, offset * kPointerSize));
1095f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CallStoreIC(slot, isolate()->factory()->home_object_symbol());
1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer,
1099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                     int offset,
110062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                     FeedbackSlot slot) {
1101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(NeedsHomeObject(initializer));
1102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ movp(StoreDescriptor::ReceiverRegister(), rax);
1103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ movp(StoreDescriptor::ValueRegister(),
1104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Operand(rsp, offset * kPointerSize));
1105f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CallStoreIC(slot, isolate()->factory()->home_object_symbol());
1106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
1109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                         TypeofMode typeof_mode) {
11103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Record position before possible IC call.
1111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionPosition(proxy);
1112bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
11133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Variable* var = proxy->var();
11143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
111562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Two cases: global variable, and all other types of variables.
1116589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (var->location()) {
1117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::UNALLOCATED: {
1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, "[ Global variable");
1119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      EmitGlobalVariableLoad(proxy, typeof_mode);
1120589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      context()->Plug(rax);
1121589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1122589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
112359151504615d929945dc59db37bf1166937748c6Steve Block
1124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::PARAMETER:
1125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::LOCAL:
1126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case VariableLocation::CONTEXT: {
1127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode);
1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot"
1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               : "[ Stack slot");
1130c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (proxy->hole_check_mode() == HoleCheckMode::kRequired) {
1131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        // Throw a reference error when using an uninitialized let/const
1132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        // binding in harmony mode.
1133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        DCHECK(IsLexicalVariableMode(var->mode()));
1134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Label done;
1135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        GetVar(rax, var);
1136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ j(not_equal, &done, Label::kNear);
1138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ Push(var->name());
1139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ CallRuntime(Runtime::kThrowReferenceError);
1140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ bind(&done);
1141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        context()->Plug(rax);
1142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1143589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      context()->Plug(var);
1145589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1146589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
1147d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
114862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VariableLocation::LOOKUP:
1149f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case VariableLocation::MODULE:
1150f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UNREACHABLE();
11513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
1156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Expression* expression = (property == NULL) ? NULL : property->value();
11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expression == NULL) {
1158109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    OperandStackDepthIncrement(1);
11593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ PushRoot(Heap::kNullValueRootIndex);
11603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
11613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForStackValue(expression);
1162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (NeedsHomeObject(expression)) {
1163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
1164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             property->kind() == ObjectLiteral::Property::SETTER);
1165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
1166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      EmitSetHomeObject(expression, offset, property->GetSlot());
1167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
11683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1172d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
117562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<BoilerplateDescription> constant_properties =
117662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      expr->GetOrBuildConstantProperties(isolate());
1177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int flags = expr->ComputeFlags();
1178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (MustCreateObjectLiteralWithRuntime(expr)) {
1179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
118062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Push(SmiFromSlot(expr->literal_slot()));
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(constant_properties);
1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(Smi::FromInt(flags));
1183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallRuntime(Runtime::kCreateObjectLiteral);
11843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
118662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Move(rbx, SmiFromSlot(expr->literal_slot()));
1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(rcx, constant_properties);
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(rdx, Smi::FromInt(flags));
118962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Callable callable = CodeFactory::FastCloneShallowObject(
119062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate(), expr->properties_count());
119162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Call(callable.code(), RelocInfo::CODE_TARGET);
1192bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    RestoreContext();
1193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1194bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
1195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
1197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in rax.
1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
1199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AccessorTable accessor_table(zone());
120162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  for (int i = 0; i < expr->properties()->length(); i++) {
120262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ObjectLiteral::Property* property = expr->properties()->at(i);
120362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(!property->is_computed_name());
1204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
1205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Literal* key = property->key()->AsLiteral();
1207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
1208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
1209109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(rax);  // Save result on the stack
1210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
1211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
121362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case ObjectLiteral::Property::SPREAD:
1214e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::CONSTANT:
1215e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        UNREACHABLE();
1216e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
1218e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
1220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // It is safe to use [[Put]] here because the boilerplate already
1221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // contains computed properties with an uninitialized value.
1222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if (key->IsStringLiteral()) {
1223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          DCHECK(key->IsPropertyName());
12243e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          if (property->emit_store()) {
1225053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block            VisitForAccumulatorValue(value);
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            DCHECK(StoreDescriptor::ValueRegister().is(rax));
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
122862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            CallStoreIC(property->GetSlot(0), key->value(), true);
1229bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
1230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            if (NeedsHomeObject(value)) {
1232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
1233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            }
1234053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block          } else {
1235053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block            VisitForEffect(value);
12363e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          }
1237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1239109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(Operand(rsp, 0));  // Duplicate receiver.
12400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(key);
12410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(value);
12423e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        if (property->emit_store()) {
1243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (NeedsHomeObject(value)) {
1244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            EmitSetHomeObject(value, 2, property->GetSlot());
1245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
1246109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          PushOperand(Smi::FromInt(SLOPPY));  // Language mode
1247109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          CallRuntimeWithOperands(Runtime::kSetProperty);
12483e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        } else {
1249109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          DropOperands(3);
12503e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        }
1251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case ObjectLiteral::Property::PROTOTYPE:
1253109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        PushOperand(Operand(rsp, 0));  // Duplicate receiver.
1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(value);
1255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(property->emit_store());
1256109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
125762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        PrepareForBailoutForId(expr->GetIdForPropertySet(i),
1258bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                               BailoutState::NO_REGISTERS);
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
126085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      case ObjectLiteral::Property::GETTER:
1261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (property->emit_store()) {
126213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          AccessorTable::Iterator it = accessor_table.lookup(key);
126362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          it->second->bailout_id = expr->GetIdForPropertySet(i);
126413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          it->second->getter = property;
1265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case ObjectLiteral::Property::SETTER:
1268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (property->emit_store()) {
126913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          AccessorTable::Iterator it = accessor_table.lookup(key);
127062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          it->second->bailout_id = expr->GetIdForPropertySet(i);
127113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          it->second->setter = property;
1272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Emit code to define accessors, using only a single call to the runtime for
12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // each pair of corresponding getters and setters.
12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (AccessorTable::Iterator it = accessor_table.begin();
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       it != accessor_table.end();
12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       ++it) {
1282109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(Operand(rsp, 0));  // Duplicate receiver.
12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForStackValue(it->first);
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAccessor(it->second->getter);
12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAccessor(it->second->setter);
1286109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(Smi::FromInt(NONE));
1287109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
128813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
1289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
12920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
12940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
12973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1299d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
13003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
1301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
130262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<ConstantElementsPair> constant_elements =
130362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      expr->GetOrBuildConstantElements(isolate());
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (MustCreateArrayLiteralWithRuntime(expr)) {
1306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
130762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Push(SmiFromSlot(expr->literal_slot()));
1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(constant_elements);
1309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Push(Smi::FromInt(expr->ComputeFlags()));
1310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallRuntime(Runtime::kCreateArrayLiteral);
1311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
131362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Move(rbx, SmiFromSlot(expr->literal_slot()));
1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(rcx, constant_elements);
131562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Callable callable =
131662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        CodeFactory::FastCloneShallowArray(isolate(), TRACK_ALLOCATION_SITE);
131762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Call(callable.code(), RelocInfo::CODE_TARGET);
1318f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    RestoreContext();
13193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1320bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
13213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
1323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneList<Expression*>* subexprs = expr->values();
1324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int length = subexprs->length();
13253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
13273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
1328f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  for (int array_index = 0; array_index < length; array_index++) {
1329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Expression* subexpr = subexprs->at(array_index);
1330109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(!subexpr->IsSpread());
1331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
13323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
13333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
13353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
1337109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(rax);  // array literal
13383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
13393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
13400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(subexpr);
13413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Move(StoreDescriptor::NameRegister(), Smi::FromInt(array_index));
1343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
1344f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    CallKeyedStoreIC(expr->LiteralFeedbackSlot());
1345086aeeaae12517475c22695a200be45495516549Ben Murdoch
1346bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(expr->GetIdForElement(array_index),
1347bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           BailoutState::NO_REGISTERS);
13483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
13510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
13530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(rax);
13543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
13563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1358402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Comment cmnt(masm_, "[ Assignment");
1362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
136380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Property* property = expr->target()->AsProperty();
1364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LhsKind assign_type = Property::GetAssignType(property);
1365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1366402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate LHS expression.
1367402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1368402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Nothing to do here.
1370402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1372402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // We need the receiver both on the stack and in the register.
1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->obj());
1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
1376402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
13770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
1378402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1380086aeeaae12517475c22695a200be45495516549Ben Murdoch    case KEYED_PROPERTY: {
1381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (expr->is_compound()) {
13823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->obj());
1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitForStackValue(property->key());
1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, kPointerSize));
1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(LoadDescriptor::NameRegister(), Operand(rsp, 0));
1386f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else {
13873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->obj());
13883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->key());
1389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
1390402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1391086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
139262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case NAMED_SUPER_PROPERTY:
139362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case KEYED_SUPER_PROPERTY:
139462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      UNREACHABLE();
139562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
1396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
13988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // For compound assignments we need another deoptimization point after the
13998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // variable/property load.
1400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
14010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    { AccumulatorValueContext context(this);
14020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
14030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
14043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          EmitVariableLoad(expr->target()->AsVariableProxy());
1405bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
14060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
14070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
14080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitNamedPropertyLoad(property);
1409bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          PrepareForBailoutForId(property->LoadId(),
1410bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                 BailoutState::TOS_REGISTER);
14110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
14120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
14130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitKeyedPropertyLoad(property);
1414bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          PrepareForBailoutForId(property->LoadId(),
1415bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                 BailoutState::TOS_REGISTER);
14160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
141762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case NAMED_SUPER_PROPERTY:
141862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case KEYED_SUPER_PROPERTY:
141962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          UNREACHABLE();
142062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          break;
14210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
1422402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1423402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
142480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Token::Value op = expr->binary_op();
1425109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(rax);  // Left operand goes on the stack.
1426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    VisitForAccumulatorValue(expr->value());
1427402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
14280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
142980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (ShouldInlineSmiCase(op)) {
1430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitInlineSmiBinaryOp(expr->binary_operation(),
143180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            op,
143280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            expr->target(),
1433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                            expr->value());
143480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    } else {
1435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      EmitBinaryOp(expr->binary_operation(), op);
143680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
1437086aeeaae12517475c22695a200be45495516549Ben Murdoch    // Deoptimization point in case the binary operation may have side effects.
1438bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
143980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
14400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->value());
1441402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1442402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionPosition(expr);
1444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Store the value.
1446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1447c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    case VARIABLE: {
1448c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      VariableProxy* proxy = expr->target()->AsVariableProxy();
1449c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(),
1450c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                             proxy->hole_check_mode());
1451bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
1452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      context()->Plug(rax);
1453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1454c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1455402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitNamedPropertyAssignment(expr);
1457402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1458402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1459402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitKeyedPropertyAssignment(expr);
1460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
146162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case NAMED_SUPER_PROPERTY:
146262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case KEYED_SUPER_PROPERTY:
146362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      UNREACHABLE();
146462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
1465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1466402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1467402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1468402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitYield(Yield* expr) {
147062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Resumable functions are not supported.
147162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  UNREACHABLE();
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1474109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::PushOperand(MemOperand operand) {
1475109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthIncrement(1);
1476109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Push(operand);
1477109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1478109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1479109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::EmitOperandStackDepthCheck() {
1480109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (FLAG_debug_code) {
1481109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp +
1482109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                        operand_stack_depth_ * kPointerSize;
1483109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ movp(rax, rbp);
1484109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ subp(rax, rsp);
1485109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ cmpp(rax, Immediate(expected_diff));
1486109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Assert(equal, kUnexpectedStackDepth);
1487109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
1488109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCreateIteratorResult(bool done) {
1491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label allocate, done_allocate;
1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1493bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &allocate,
1494bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              NO_ALLOCATION_FLAGS);
1495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ jmp(&done_allocate, Label::kNear);
1496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&allocate);
1498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Push(Smi::FromInt(JSIteratorResult::kSize));
1499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace);
1500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&done_allocate);
1502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, rbx);
1503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx);
1504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex);
1505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx);
1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx);
1507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset));
1508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(FieldOperand(rax, JSIteratorResult::kDoneOffset),
1509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex);
1510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
15113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  OperandStackDepthDecrement(1);
1512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
151680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Token::Value op,
151780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Expression* left,
1518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              Expression* right) {
151980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Do combined smi check of the operands. Left operand is on the
152080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // stack (popped into rdx). Right operand is in rax but moved into
152180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rcx to make the shifts easier.
1522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done, stub_call, smi_case;
1523109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(rdx);
1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, rax);
1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ orp(rax, rdx);
15261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  JumpPatchSite patch_site(masm_);
1527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear);
152880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
152980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&stub_call);
1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, rcx);
1531109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(code, expr->BinaryOperationFeedbackId());
15333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
1534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&done, Label::kNear);
153580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
153680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&smi_case);
153780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
153880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SAR:
153980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiShiftArithmeticRight(rax, rdx, rcx);
154080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
154180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHL:
1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ SmiShiftLeft(rax, rdx, rcx, &stub_call);
154380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
154480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHR:
154580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiShiftLogicalRight(rax, rdx, rcx, &stub_call);
154680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
154780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::ADD:
154880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiAdd(rax, rdx, rcx, &stub_call);
154980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
155080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SUB:
155180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiSub(rax, rdx, rcx, &stub_call);
155280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
155380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::MUL:
155480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiMul(rax, rdx, rcx, &stub_call);
155580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
155680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_OR:
155780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiOr(rax, rdx, rcx);
155880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
155980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_AND:
156080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiAnd(rax, rdx, rcx);
156180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
156280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_XOR:
156380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiXor(rax, rdx, rcx);
156480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
156580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    default:
156680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      UNREACHABLE();
156780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
156880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
156980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
157080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&done);
15710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
157280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
157380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
157480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
1576109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(rdx);
1577109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
15783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(code, expr->BinaryOperationFeedbackId());
15803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
15810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
1582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
158462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr, FeedbackSlot slot) {
1585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(expr->IsValidReferenceExpressionOrThis());
1586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = expr->AsProperty();
1588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LhsKind assign_type = Property::GetAssignType(prop);
1589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (assign_type) {
1591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case VARIABLE: {
1592c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      VariableProxy* proxy = expr->AsVariableProxy();
15930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EffectContext context(this);
1594c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot,
1595c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                             proxy->hole_check_mode());
1596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case NAMED_PROPERTY: {
1599109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(rax);  // Preserve value.
16000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(StoreDescriptor::ReceiverRegister(), rax);
1602109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(StoreDescriptor::ValueRegister());  // Restore value.
1603f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      CallStoreIC(slot, prop->key()->AsLiteral()->value());
1604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case KEYED_PROPERTY: {
1607109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PushOperand(rax);  // Preserve value.
16083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForStackValue(prop->obj());
16093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForAccumulatorValue(prop->key());
1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(StoreDescriptor::NameRegister(), rax);
1611109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(StoreDescriptor::ReceiverRegister());
1612109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(StoreDescriptor::ValueRegister());  // Restore value.
1613f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      CallKeyedStoreIC(slot);
1614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
161662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case NAMED_SUPER_PROPERTY:
161762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case KEYED_SUPER_PROPERTY:
161862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      UNREACHABLE();
161962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
1620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(rax);
1622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Variable* var, MemOperand location) {
1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(location, rax);
1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (var->IsContextSlot()) {
1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdx, rax);
1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ RecordWriteContextSlot(
1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
163662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                               FeedbackSlot slot,
1637c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                               HoleCheckMode hole_check_mode) {
1638589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsUnallocated()) {
1639589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Global var, const, or let.
1640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
1641f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    CallStoreIC(slot, var->name());
1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1643f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!var->IsLookupSlot());
1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemOperand location = VarOperand(var, rcx);
1647f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Perform an initialization check for lexically declared variables.
1648c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (hole_check_mode == HoleCheckMode::kRequired) {
1649f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Label assign;
1650f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ movp(rdx, location);
1651f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1652f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ j(not_equal, &assign, Label::kNear);
1653f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ Push(var->name());
1654f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ CallRuntime(Runtime::kThrowReferenceError);
1655f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ bind(&assign);
1656f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1657f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (var->mode() != CONST) {
1658f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      EmitStoreToStackLocalOrContextSlot(var, location);
1659f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    } else if (var->throw_on_const_assignment(language_mode())) {
1660f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      __ CallRuntime(Runtime::kThrowConstAssignError);
1661f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1662014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) {
1664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Initializing assignment to const {this} needs a write barrier.
1665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
1666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label uninitialized_this;
1667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MemOperand location = VarOperand(var, rcx);
1668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ movp(rdx, location);
1669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ j(equal, &uninitialized_this);
1671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Push(var->name());
1672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallRuntime(Runtime::kThrowReferenceError);
1673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&uninitialized_this);
1674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    EmitStoreToStackLocalOrContextSlot(var, location);
1675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1676f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } else {
1677f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK(var->mode() != CONST || op == Token::INIT);
167862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
167962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(!var->IsLookupSlot());
168062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Assignment to var or initializing assignment to let/const in harmony
168162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // mode.
168262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    MemOperand location = VarOperand(var, rcx);
168362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) {
168462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Check for an uninitialized let binding.
168562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ movp(rdx, location);
168662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
168762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Check(equal, kLetBindingReInitialization);
16883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
168962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    EmitStoreToStackLocalOrContextSlot(var, location);
16903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
16913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1694d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
1696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(prop != NULL);
1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(prop->key()->IsLiteral());
1699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1700109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(StoreDescriptor::ReceiverRegister());
1701f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CallStoreIC(expr->AssignmentSlot(), prop->key()->AsLiteral()->value());
1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1703bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
1704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(rax);
1705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1708d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
1710109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(StoreDescriptor::NameRegister());  // Key.
1711109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(StoreDescriptor::ReceiverRegister());
1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(StoreDescriptor::ValueRegister().is(rax));
1713f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CallKeyedStoreIC(expr->AssignmentSlot());
1714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1715bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
1716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->Plug(rax);
1717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC.
1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Expression* callee = expr->expression();
1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the target function.
1724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ConvertReceiverMode convert_mode;
1725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (callee->IsVariableProxy()) {
1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    { StackValueContext context(this);
1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitVariableLoad(callee->AsVariableProxy());
1728bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
17293e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
1730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Push undefined as receiver. This is patched in the Call builtin if it
1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // is a sloppy mode method.
1732109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(isolate()->factory()->undefined_value());
1733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    convert_mode = ConvertReceiverMode::kNullOrUndefined;
1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load the function from the receiver.
1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(callee->IsProperty());
1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!callee->AsProperty()->IsSuperAccess());
1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitNamedPropertyLoad(callee->AsProperty());
1740bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
1741bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           BailoutState::TOS_REGISTER);
1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push the target function under the receiver.
1743109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(Operand(rsp, 0));
1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(Operand(rsp, kPointerSize), rax);
1745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
17463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1748014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitCall(expr, convert_mode);
1749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Common code for calls using the IC.
1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Expression* key) {
17558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the key.
17568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForAccumulatorValue(key);
17578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Expression* callee = expr->expression();
17598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the function from the receiver.
1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(callee->IsProperty());
1762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(LoadDescriptor::NameRegister(), rax);
1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitKeyedPropertyLoad(callee->AsProperty());
1765bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
1766bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                         BailoutState::TOS_REGISTER);
1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push the target function under the receiver.
1769109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushOperand(Operand(rsp, 0));
1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(Operand(rsp, kPointerSize), rax);
1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined);
17739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
17749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
17759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the arguments.
1778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1779d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
1780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (int i = 0; i < arg_count; i++) {
1781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    VisitForStackValue(args->at(i));
1782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1784bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
17853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  SetCallPosition(expr, expr->tail_call_mode());
1786109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (expr->tail_call_mode() == TailCallMode::kAllow) {
1787109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (FLAG_trace) {
1788109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ CallRuntime(Runtime::kTraceTailCall);
1789109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
1790109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Update profiling counters before the tail call since we will
1791109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // not return to this function.
1792109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    EmitProfilingCounterHandlingForReturnSequence(true);
1793109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
1794c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<Code> code =
179562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      CodeFactory::CallICTrampoline(isolate(), mode, expr->tail_call_mode())
179662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          .code();
179762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Set(rdx, IntFromSlot(expr->CallFeedbackICSlot()));
1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
1799c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Set(rax, arg_count);
1800c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CallIC(code);
1801109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(arg_count + 1);
1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1803086aeeaae12517475c22695a200be45495516549Ben Murdoch  RecordJSReturnSite(expr);
1804bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  RestoreContext();
18053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Discard the function left on TOS.
18060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->DropAndPlug(1, rax);
1807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1809d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
1810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
1811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
1812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
1813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
1814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
181580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Push constructor on the stack.  If it's not a function it's used as
181680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
181780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ignored.
1818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!expr->expression()->IsSuperPropertyReference());
1819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForStackValue(expr->expression());
1820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
1822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
1823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
1824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
18250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
18263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
1829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
1830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetConstructCallPosition(expr);
1831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
183280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load function and argument count into rdi and rax.
1833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Set(rax, arg_count);
1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, Operand(rsp, arg_count * kPointerSize));
1835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Record call targets in unoptimized code, but not in the snapshot.
183762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ EmitLoadFeedbackVector(rbx);
1838958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Move(rdx, SmiFromSlot(expr->CallNewFeedbackSlot()));
1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallConstructStub stub(isolate());
1841c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CallIC(stub.GetCode());
1842109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(arg_count + 1);
1843bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
1844bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  RestoreContext();
18450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
18463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
18473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
18493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
1851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
18520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
1853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
185780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
18580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
18590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
1860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
18613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
1862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ JumpIfSmi(rax, if_true);
1863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ jmp(if_false);
1864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
18650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
1866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsJSReceiver(CallRuntime* expr) {
18703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
18723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
18730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
18743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
18753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label materialize_true, materialize_false;
18763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_true = NULL;
18773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_false = NULL;
187880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
18790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
18800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
18813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
18823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ JumpIfSmi(rax, if_false);
1883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rbx);
18843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
188580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(above_equal, if_true, if_false, fall_through);
18863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
18870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
18883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
18893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
18903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
18913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
18923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
1894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
18950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
1896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
190080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
19010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
19020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
1903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
1905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
19063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
190780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
1908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
1910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsTypedArray(CallRuntime* expr) {
19143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
1916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
1918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
192280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
1923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
1924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         &if_false, &fall_through);
1925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ JumpIfSmi(rax, if_false);
1927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CmpObjectType(rax, JS_TYPED_ARRAY_TYPE, rbx);
19283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
192980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
1930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
1932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) {
1936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
1937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(args->length() == 1);
1938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForAccumulatorValue(args->at(0));
1940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
1942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
1943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
194480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
1945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
1946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         &if_false, &fall_through);
1947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ JumpIfSmi(rax, if_false);
1950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CmpObjectType(rax, JS_PROXY_TYPE, rbx);
19513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
195280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
1953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
1955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
19593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 1);
1961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, null, function, non_function_constructor;
1962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
19630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
1964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // If the object is not a JSReceiver, we return null.
1966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ JumpIfSmi(rax, &null, Label::kNear);
1967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
1968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rax);
1969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ j(below, &null, Label::kNear);
1970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
19713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Return 'Function' for JSFunction and JSBoundFunction objects.
19723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ CmpInstanceType(rax, FIRST_FUNCTION_TYPE);
19733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
19743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ j(above_equal, &function, Label::kNear);
19753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the constructor in the map is a JS function.
1977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ GetMapConstructor(rax, rax, rbx);
1978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CmpInstanceType(rbx, JS_FUNCTION_TYPE);
1979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ j(not_equal, &non_function_constructor, Label::kNear);
1980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // rax now contains the constructor function. Grab the
1982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // instance class name from there.
1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset));
1985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ jmp(&done, Label::kNear);
1986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Non-JS objects have class null.
1988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&null);
1989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(rax, Heap::kNullValueRootIndex);
1990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ jmp(&done, Label::kNear);
1991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Functions have class 'Function'.
1993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&function);
1994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(rax, Heap::kFunction_stringRootIndex);
1995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ jmp(&done, Label::kNear);
1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Objects with a non-function constructor have class 'Object'.
1998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&non_function_constructor);
1999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(rax, Heap::kObject_stringRootIndex);
2000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // All done.
2002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(rax);
2005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
20093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
20117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
20120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
20130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
20147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
20157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = rbx;
20167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = rax;
20177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = rdx;
20187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2019109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopOperand(object);
20207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
20217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
20227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
20237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
202413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
202513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                      &need_conversion, &index_out_of_range);
20267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
2027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
20297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
20307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
20317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // NaN.
20327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kNanValueRootIndex);
20337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
20347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
20357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
20367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move the undefined value into the result register, which will
20377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // trigger conversion.
20387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
20397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
20407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
20417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
2042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
2043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
20450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
2046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCall(CallRuntime* expr) {
20503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_LE(2, args->length());
2052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push target, receiver and arguments onto the stack.
2053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (Expression* const arg : *args) {
2054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    VisitForStackValue(arg);
2055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2056bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
2057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Move target to rdi.
2058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int const argc = args->length() - 2;
2059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ movp(rdi, Operand(rsp, (argc + 1) * kPointerSize));
2060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Call the target.
2061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Set(rax, argc);
2062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
2063109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(argc + 1);
2064bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  RestoreContext();
2065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Discard the function left on TOS.
2066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->DropAndPlug(1, rax);
2067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) {
2070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
2071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, args->length());
2072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForAccumulatorValue(args->at(0));
2073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ AssertFunction(rax);
2074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
2075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ movp(rax, FieldOperand(rax, Map::kPrototypeOffset));
2076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->Plug(rax);
2077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expr->arguments()->length() == 0);
2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference debug_is_active =
2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::debug_is_active_address(isolate());
2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(kScratchRegister, debug_is_active);
2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movzxbp(rax, Operand(kScratchRegister, 0));
2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Integer32ToSmi(rax, rax);
208644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  context()->Plug(rax);
20878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
20888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
2091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
2092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(2, args->length());
2093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForStackValue(args->at(0));
2094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitForStackValue(args->at(1));
2095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label runtime, done;
2097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2098bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &runtime,
2099bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              NO_ALLOCATION_FLAGS);
2100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, rbx);
2101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx);
2102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex);
2103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx);
2104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx);
2105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Pop(FieldOperand(rax, JSIteratorResult::kDoneOffset));
2106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset));
2107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
2108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ jmp(&done, Label::kNear);
2109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&runtime);
2111109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CallRuntimeWithOperands(Runtime::kCreateIterResultObject);
2112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&done);
2114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  context()->Plug(rax);
2115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
21193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Push function.
21203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ LoadNativeContextSlot(expr->context_index(), rax);
21213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  PushOperand(rax);
21223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
21233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Push undefined as receiver.
2124109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthIncrement(1);
2125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ PushRoot(Heap::kUndefinedValueRootIndex);
2126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
2130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
2131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int arg_count = args->length();
2132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetCallPosition(expr);
2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Set(rax, arg_count);
2136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          RelocInfo::CODE_TARGET);
2138109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  OperandStackDepthDecrement(arg_count + 1);
2139bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  RestoreContext();
2140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2143d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
2145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Token::DELETE: {
2146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
2147589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Property* property = expr->expression()->AsProperty();
2148589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VariableProxy* proxy = expr->expression()->AsVariableProxy();
2149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2150589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (property != NULL) {
2151589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        VisitForStackValue(property->obj());
2152589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        VisitForStackValue(property->key());
2153109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        CallRuntimeWithOperands(is_strict(language_mode())
2154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                    ? Runtime::kDeleteProperty_Strict
2155109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                    : Runtime::kDeleteProperty_Sloppy);
215669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        context()->Plug(rax);
2157589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else if (proxy != NULL) {
2158589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Variable* var = proxy->var();
2159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Delete of an unqualified identifier is disallowed in strict mode but
2160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // "delete this" is allowed.
2161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        bool is_this = var->is_this();
2162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(is_sloppy(language_mode()) || is_this);
2163f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        if (var->IsUnallocated()) {
2164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ movp(rax, NativeContextOperand());
2165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ Push(ContextOperand(rax, Context::EXTENSION_INDEX));
2166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ Push(var->name());
2167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ CallRuntime(Runtime::kDeleteProperty_Sloppy);
2168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(rax);
216962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        } else {
217062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          DCHECK(!var->IsLookupSlot());
217162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2172589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // Result of deleting non-global variables is false.  'this' is
2173589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // not really a variable, though we implement it as one.  The
2174589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // subexpression does not have side effects.
2175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          context()->Plug(is_this);
2176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
21771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
2178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Result of deleting non-property, non-variable reference is true.
2179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // The subexpression may have side effects.
2180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
2181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        context()->Plug(true);
2182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
2183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
2184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
2185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
2187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
2188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
21890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(Heap::kUndefinedValueRootIndex);
2190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
2194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (context()->IsEffect()) {
2196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Unary NOT has no side effects so it's only necessary to visit the
2197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // subexpression.  Match the optimizing compiler by not branching.
2198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
21993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (context()->IsTest()) {
22003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        const TestContext* test = TestContext::cast(context());
22013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The labels are swapped for the recursive call.
22023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VisitForControl(expr->expression(),
22033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->false_label(),
22043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->true_label(),
22053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->fall_through());
22063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        context()->Plug(test->true_label(), test->false_label());
2207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
22083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We handle value contexts explicitly rather than simply visiting
22093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // for control and plugging the control flow into the context,
22103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // because we need to prepare a pair of extra administrative AST ids
22113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // for the optimizing compiler.
2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue());
22133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label materialize_true, materialize_false, done;
22143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VisitForControl(expr->expression(),
22153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_false,
22163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_true,
22173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_true);
2218109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
22193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&materialize_true);
2220bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        PrepareForBailoutForId(expr->MaterializeTrueId(),
2221bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                               BailoutState::NO_REGISTERS);
22223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (context()->IsAccumulatorValue()) {
22233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ LoadRoot(rax, Heap::kTrueValueRootIndex);
22243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
22253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ PushRoot(Heap::kTrueValueRootIndex);
22263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
22273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&done, Label::kNear);
22283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&materialize_false);
2229bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        PrepareForBailoutForId(expr->MaterializeFalseId(),
2230bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                               BailoutState::NO_REGISTERS);
22313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (context()->IsAccumulatorValue()) {
22323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ LoadRoot(rax, Heap::kFalseValueRootIndex);
22333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
22343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ PushRoot(Heap::kFalseValueRootIndex);
22353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
22363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&done);
2237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
2242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
2243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      {
2244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AccumulatorValueContext context(this);
22450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForTypeofValue(expr->expression());
22460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
2247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ movp(rbx, rax);
2248c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      __ Call(isolate()->builtins()->Typeof(), RelocInfo::CODE_TARGET);
22490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(rax);
2250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
2254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
22553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
22563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
22573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
22583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2259d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
2260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Comment cmnt(masm_, "[ CountOperation");
2263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
2265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LhsKind assign_type = Property::GetAssignType(prop);
2266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
2268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
22700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
22713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    EmitVariableLoad(expr->expression()->AsVariableProxy());
2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
2273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
22740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (expr->is_postfix() && !context()->IsEffect()) {
2275c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      PushOperand(Smi::kZero);
2276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (assign_type) {
2278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case NAMED_PROPERTY: {
2279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        VisitForStackValue(prop->obj());
2280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
2281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        EmitNamedPropertyLoad(prop);
2282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
2283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
2284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case KEYED_PROPERTY: {
2286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        VisitForStackValue(prop->obj());
2287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        VisitForStackValue(prop->key());
2288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Leave receiver on stack
2289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, kPointerSize));
2290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Copy of key, needed for later store.
2291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ movp(LoadDescriptor::NameRegister(), Operand(rsp, 0));
2292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        EmitKeyedPropertyLoad(prop);
2293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
2294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
2295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
229662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case NAMED_SUPER_PROPERTY:
229762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case KEYED_SUPER_PROPERTY:
2298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case VARIABLE:
2299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        UNREACHABLE();
2300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2303086aeeaae12517475c22695a200be45495516549Ben Murdoch  // We need a second deoptimization point after loading the value
2304086aeeaae12517475c22695a200be45495516549Ben Murdoch  // in case evaluating the property load my have a side effect.
23058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (assign_type == VARIABLE) {
2306bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
23078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
2308bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Inline smi case if we are in a loop.
2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, stub_call;
2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpPatchSite patch_site(masm_);
2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (ShouldInlineSmiCase(expr->op())) {
2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label slow;
2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patch_site.EmitJumpIfNotSmi(rax, &slow, Label::kNear);
2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Save result for postfix expressions.
2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (expr->is_postfix()) {
2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!context()->IsEffect()) {
2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Save the result on the stack. If we have a named or keyed property
2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // we store the result under the receiver that is currently on top
2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // of the stack.
2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        switch (assign_type) {
2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          case VARIABLE:
2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ Push(rax);
2327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
2328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          case NAMED_PROPERTY:
2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ movp(Operand(rsp, kPointerSize), rax);
2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          case KEYED_PROPERTY:
2332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ movp(Operand(rsp, 2 * kPointerSize), rax);
2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            break;
233462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          case NAMED_SUPER_PROPERTY:
2335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case KEYED_SUPER_PROPERTY:
233662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            UNREACHABLE();
2337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            break;
2338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
2339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SmiOperationConstraints constraints =
2343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        SmiOperationConstraint::kPreserveSourceRegister |
2344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        SmiOperationConstraint::kBailoutOnNoOverflow;
2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (expr->op() == Token::INC) {
2346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ SmiAddConstant(rax, rax, Smi::FromInt(1), constraints, &done,
2347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        Label::kNear);
2348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ SmiSubConstant(rax, rax, Smi::FromInt(1), constraints, &done,
2350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        Label::kNear);
2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&stub_call, Label::kNear);
2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&slow);
23548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
23553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
23563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Convert old value into a number.
235713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
2358f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RestoreContext();
2359bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
2360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
2362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
23630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (!context()->IsEffect()) {
23640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Save the result on the stack. If we have a named or keyed property
23650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // we store the result under the receiver that is currently on top
23660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // of the stack.
23670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
23680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
2369109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          PushOperand(rax);
23700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
23710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ movp(Operand(rsp, kPointerSize), rax);
23730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
23740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ movp(Operand(rsp, 2 * kPointerSize), rax);
23760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
237762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case NAMED_SUPER_PROPERTY:
2378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        case KEYED_SUPER_PROPERTY:
237962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          UNREACHABLE();
2380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          break;
23810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
2382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SetExpressionPosition(expr);
2386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call stub for +1/-1.
2388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&stub_call);
2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, rax);
2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rax, Smi::FromInt(1));
2391109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Handle<Code> code =
2392109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      CodeFactory::BinaryOpIC(isolate(), expr->binary_op()).code();
2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(code, expr->CountBinOpFeedbackId());
23943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
2395d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
2396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in rax.
2398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
2399c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    case VARIABLE: {
2400c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      VariableProxy* proxy = expr->expression()->AsVariableProxy();
2401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
2402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
24030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        { EffectContext context(this);
2404c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
2405c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                 proxy->hole_check_mode());
2406bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          PrepareForBailoutForId(expr->AssignmentId(),
2407bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                 BailoutState::TOS_REGISTER);
2408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          context.Plug(rax);
24090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        }
2410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // For all contexts except kEffect: We have the result on
2411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
24120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
24130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
2414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
2415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
2416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
2417c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
2418c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                               proxy->hole_check_mode());
2419bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        PrepareForBailoutForId(expr->AssignmentId(),
2420bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                               BailoutState::TOS_REGISTER);
2421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        context()->Plug(rax);
2422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
2423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
2424c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
2425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
2426109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(StoreDescriptor::ReceiverRegister());
2427f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value());
2428bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
24300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
24310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
2432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
2433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
24340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(rax);
2435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
2436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
2437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
2439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(StoreDescriptor::NameRegister());
2440109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(StoreDescriptor::ReceiverRegister());
2441f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      CallKeyedStoreIC(expr->CountSlot());
2442bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
24440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
24450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
2446e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
2447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
24480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(rax);
2449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
2450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      break;
2451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
245262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case NAMED_SUPER_PROPERTY:
245362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case KEYED_SUPER_PROPERTY:
245462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      UNREACHABLE();
245562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
2456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
24603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
24613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Expression* sub_expr,
24623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Handle<String> check) {
24633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label materialize_true, materialize_false;
24643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* if_true = NULL;
24653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* if_false = NULL;
24663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* fall_through = NULL;
24673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         &if_true, &if_false, &fall_through);
24693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  { AccumulatorValueContext context(this);
24713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForTypeofValue(sub_expr);
24720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
24733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
24740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate()->factory();
2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (String::Equals(check, factory->number_string())) {
2477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(rax, if_true);
2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
247980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
248080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->string_string())) {
2482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(rax, if_false);
2483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
2484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Split(below, if_true, if_false, fall_through);
2485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->symbol_string())) {
2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(rax, if_false);
2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CmpObjectType(rax, SYMBOL_TYPE, rdx);
2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Split(equal, if_true, if_false, fall_through);
2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->boolean_string())) {
249080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
2491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
249280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CompareRoot(rax, Heap::kFalseValueRootIndex);
249380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->undefined_string())) {
2495109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ CompareRoot(rax, Heap::kNullValueRootIndex);
2496109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ j(equal, if_false);
2497e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(rax, if_false);
249880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => true.
2499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdx, FieldOperand(rax, HeapObject::kMapOffset));
250080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
250180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen             Immediate(1 << Map::kIsUndetectable));
250280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(not_zero, if_true, if_false, fall_through);
2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->function_string())) {
2504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(rax, if_false);
2505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Check for callable and not undetectable objects => true.
2506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ movp(rdx, FieldOperand(rax, HeapObject::kMapOffset));
2507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ movzxbl(rdx, FieldOperand(rdx, Map::kBitFieldOffset));
2508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ andb(rdx,
2509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
2510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ cmpb(rdx, Immediate(1 << Map::kIsCallable));
25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Split(equal, if_true, if_false, fall_through);
2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(check, factory->object_string())) {
2513e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(rax, if_false);
2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(rax, Heap::kNullValueRootIndex);
2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(equal, if_true);
2516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
2517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rdx);
2518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ j(below, if_false);
2519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Check for callable or undetectable objects => false.
252080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
2521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
2522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(zero, if_true, if_false, fall_through);
252380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
252480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (if_false != fall_through) __ jmp(if_false);
2525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
25263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->Plug(if_true, if_false);
2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2530d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
2531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
2532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
25333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First we try a fast inlined version of the compare when one of
25343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the operands is a literal.
25353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (TryLiteralCompare(expr)) return;
25363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
2538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
254280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
25440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
254580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
25463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Token::Value op = expr->op();
25470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->left());
254880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
2549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
25500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
2551bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      SetExpressionPosition(expr);
2552bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      EmitHasProperty();
25533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
2554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CompareRoot(rax, Heap::kTrueValueRootIndex);
255580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(equal, if_true, if_false, fall_through);
2556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
25573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
2559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      VisitForAccumulatorValue(expr->right());
2560bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      SetExpressionPosition(expr);
2561109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(rdx);
2562c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      __ Call(isolate()->builtins()->InstanceOf(), RelocInfo::CODE_TARGET);
256362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      RestoreContext();
2564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
2565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ CompareRoot(rax, Heap::kTrueValueRootIndex);
2566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Split(equal, if_true, if_false, fall_through);
2567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
2568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
25710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->right());
2572bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      SetExpressionPosition(expr);
2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Condition cc = CompareIC::ComputeCondition(op);
2574109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      PopOperand(rdx);
2575d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
25760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      bool inline_smi_code = ShouldInlineSmiCase(op);
25771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      JumpPatchSite patch_site(masm_);
25780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (inline_smi_code) {
2579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Label slow_case;
2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(rcx, rdx);
2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ orp(rcx, rax);
2582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmpp(rdx, rax);
258480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Split(cc, if_true, if_false, NULL);
258580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&slow_case);
258680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
2587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2588109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallIC(ic, expr->CompareOperationFeedbackId());
25903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      patch_site.EmitPatchInfo();
2591086aeeaae12517475c22695a200be45495516549Ben Murdoch
25923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ testp(rax, rax);
259480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(cc, if_true, if_false, fall_through);
2595d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
25963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
25973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
2599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
26000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
26043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
26053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              Expression* sub_expr,
26063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              NilValue nil) {
260780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
260880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
260980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
261080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
26110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
26120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
261380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
26143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitForAccumulatorValue(sub_expr);
26153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
26163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expr->op() == Token::EQ_STRICT) {
2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Heap::RootListIndex nil_value = nil == kNullValue ?
2618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Heap::kNullValueRootIndex :
2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Heap::kUndefinedValueRootIndex;
2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(rax, nil_value);
262180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
262280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
26233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ JumpIfSmi(rax, if_false);
26243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
26253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ testb(FieldOperand(rax, Map::kBitFieldOffset),
26263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch             Immediate(1 << Map::kIsUndetectable));
26273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Split(not_zero, if_true, if_false, fall_through);
262880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
26290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
263080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
263180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
263280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
26330d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() {
26340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return rax;
26350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
2636d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
26380d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() {
26390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return rsi;
26400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
26410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
26423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid FullCodeGenerator::LoadFromFrameField(int frame_offset, Register value) {
26433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(IsAligned(frame_offset, kPointerSize));
26443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ movp(value, Operand(rbp, frame_offset));
26453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
26460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2647d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsAligned(frame_offset, kPointerSize));
2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(Operand(rbp, frame_offset), value);
26503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
26513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
26523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2653d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(dst, ContextOperand(rsi, context_index));
2655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
26583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
2659f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeclarationScope* closure_scope = scope()->GetClosureScope();
2660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (closure_scope->is_script_scope() ||
2661014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      closure_scope->is_module_scope()) {
2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Contexts nested in the native context have a canonical empty function
26633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // as their closure, not the anonymous closure containing the global
2664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // code.
2665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ movp(rax, NativeContextOperand());
2666109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(ContextOperand(rax, Context::CLOSURE_INDEX));
2667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (closure_scope->is_eval_scope()) {
26683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Contexts created by a call to eval have the same closure as the
26693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // context calling eval, not the anonymous closure containing the eval
26703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // code.  Fetch it from the context.
2671109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(ContextOperand(rsi, Context::CLOSURE_INDEX));
26723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
2673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(closure_scope->is_function_scope());
2674109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PushOperand(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
26753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
26763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
26773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
267969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#undef __
2680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kJnsInstruction = 0x79;
2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kNopByteOne = 0x66;
2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kNopByteTwo = 0x90;
2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kCallInstruction = 0xe8;
2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BackEdgeTable::PatchAt(Code* unoptimized_code,
2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Address pc,
2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            BackEdgeState target_state,
2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Code* replacement_code) {
2694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address call_target_address = pc - kIntSize;
2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address jns_instr_address = call_target_address - 3;
2696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address jns_offset_address = call_target_address - 2;
2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (target_state) {
2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case INTERRUPT:
2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //     sub <profiling_counter>, <delta>  ;; Not changed
2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //     jns ok
2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //     call <interrupt stub>
2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ok:
2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *jns_instr_address = kJnsInstruction;
2705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *jns_offset_address = kJnsOffset;
2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case ON_STACK_REPLACEMENT:
2708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //     sub <profiling_counter>, <delta>  ;; Not changed
2709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //     nop
2710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //     nop
2711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //     call <on-stack replacment>
2712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //   ok:
2713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *jns_instr_address = kNopByteOne;
2714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *jns_offset_address = kNopByteTwo;
2715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Assembler::set_target_address_at(unoptimized_code->GetIsolate(),
2719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   call_target_address, unoptimized_code,
2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   replacement_code->entry());
2721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      unoptimized_code, call_target_address, replacement_code);
2723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
2727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Isolate* isolate,
2728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Code* unoptimized_code,
2729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Address pc) {
2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address call_target_address = pc - kIntSize;
2731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address jns_instr_address = call_target_address - 3;
2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(kCallInstruction, *(call_target_address - 1));
2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (*jns_instr_address == kJnsInstruction) {
2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(kJnsOffset, *(call_target_address - 2));
2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(),
2737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Assembler::target_address_at(call_target_address,
2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           unoptimized_code));
2739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return INTERRUPT;
2740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(kNopByteOne, *jns_instr_address);
2743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(kNopByteTwo, *(call_target_address - 2));
2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
27453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(
27463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      isolate->builtins()->OnStackReplacement()->entry(),
27473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Assembler::target_address_at(call_target_address, unoptimized_code));
27483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return ON_STACK_REPLACEMENT;
2749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
2752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
2753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
2755