1864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
2864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be
3864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// found in the LICENSE file.
4864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
6864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
7864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#if V8_TARGET_ARCH_X87
8864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
9b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org#include "src/code-factory.h"
10196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/code-stubs.h"
11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/codegen.h"
12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/compiler.h"
13196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/debug.h"
14196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/full-codegen.h"
15a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org#include "src/ic/ic.h"
16196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/isolate-inl.h"
17196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/parser.h"
18196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/scopes.h"
19864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
20864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgnamespace v8 {
21864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgnamespace internal {
22864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
23864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#define __ ACCESS_MASM(masm_)
24864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
25864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
26864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgclass JumpPatchSite BASE_EMBEDDED {
27864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org public:
28864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
29864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef DEBUG
30864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    info_emitted_ = false;
31864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
32864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
33864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
34864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ~JumpPatchSite() {
35e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(patch_site_.is_bound() == info_emitted_);
36864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
37864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
38864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void EmitJumpIfNotSmi(Register reg,
39864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        Label* target,
40864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        Label::Distance distance = Label::kFar) {
41864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(reg, Immediate(kSmiTagMask));
42864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitJump(not_carry, target, distance);  // Always taken before patched.
43864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
44864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
45864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void EmitJumpIfSmi(Register reg,
46864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     Label* target,
47864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     Label::Distance distance = Label::kFar) {
48864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(reg, Immediate(kSmiTagMask));
49864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitJump(carry, target, distance);  // Never taken before patched.
50864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
51864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
52864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void EmitPatchInfo() {
53864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (patch_site_.is_bound()) {
54864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
55e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(is_uint8(delta_to_patch_site));
56864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ test(eax, Immediate(delta_to_patch_site));
57864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef DEBUG
58864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      info_emitted_ = true;
59864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
60864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
61864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ nop();  // Signals no inlined code.
62864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
63864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
64864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
65864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org private:
66864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // jc will be patched with jz, jnc will become jnz.
67864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void EmitJump(Condition cc, Label* target, Label::Distance distance) {
68e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!patch_site_.is_bound() && !info_emitted_);
69e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(cc == carry || cc == not_carry);
70864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&patch_site_);
71864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(cc, target, distance);
72864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
73864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
74864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  MacroAssembler* masm_;
75864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label patch_site_;
76864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef DEBUG
77864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool info_emitted_;
78864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
79864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org};
80864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
81864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
82864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Generate code for a JS function.  On entry to the function the receiver
83864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// and arguments have been pushed on the stack left to right, with the
84864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// return address on top of them.  The actual argument count matches the
85864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// formal parameter count expected by the function.
86864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org//
87864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// The live registers are:
88864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org//   o edi: the JS function object being called (i.e. ourselves)
89864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org//   o esi: our context
90864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org//   o ebp: our caller's frame pointer
91864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org//   o esp: stack pointer (pointing to return address)
92864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org//
93864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// The function builds a JS frame.  Please see JavaScriptFrameConstants in
94864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// frames-x87.h for its layout.
95864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::Generate() {
96864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CompilationInfo* info = info_;
97864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  handler_table_ =
98864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
99864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  profiling_counter_ = isolate()->factory()->NewCell(
101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SetFunctionPosition(function());
103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ function compiled by full code generator");
104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ProfileEntryHookStub::MaybeCallEntryHook(masm_);
106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef DEBUG
108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (strlen(FLAG_stop_at) > 0 &&
109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ int3();
111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Sloppy mode functions and builtins need to replace the receiver with the
115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // global proxy when called as functions (without an explicit receiver
116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // object).
117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (info->strict_mode() == SLOPPY && !info->is_native()) {
118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label ok;
119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // +1 for return address.
120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize;
121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ecx, Operand(esp, receiver_offset));
122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(ecx, isolate()->factory()->undefined_value());
124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_equal, &ok, Label::kNear);
125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ecx, GlobalObjectOperand());
127d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalProxyOffset));
128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(Operand(esp, receiver_offset), ecx);
130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&ok);
132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Open a frame scope to indicate that there is a frame on the stack.  The
135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // MANUAL indicates that the scope shouldn't actually generate code to set up
136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the frame (that is done below).
137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  FrameScope frame_scope(masm_, StackFrame::MANUAL);
138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  info->set_prologue_offset(masm_->pc_offset());
140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Prologue(info->IsCodePreAgingActive());
141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  info->AddNoFrameRange(0, masm_->pc_offset());
142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  { Comment cmnt(masm_, "[ Allocate locals");
144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int locals_count = info->scope()->num_stack_slots();
145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Generators allocate locals, if any, in context slots.
146e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!info->function()->is_generator() || locals_count == 0);
147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (locals_count == 1) {
148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Immediate(isolate()->factory()->undefined_value()));
149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (locals_count > 1) {
150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (locals_count >= 128) {
1513ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        Label ok;
1523ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        __ mov(ecx, esp);
1533ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        __ sub(ecx, Immediate(locals_count * kPointerSize));
1543ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        ExternalReference stack_limit =
1553ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org            ExternalReference::address_of_real_stack_limit(isolate());
1563ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        __ cmp(ecx, Operand::StaticVariable(stack_limit));
1573ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        __ j(above_equal, &ok, Label::kNear);
1583ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1593ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        __ bind(&ok);
160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(eax, Immediate(isolate()->factory()->undefined_value()));
162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      const int kMaxPushes = 32;
163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (locals_count >= kMaxPushes) {
164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        int loop_iterations = locals_count / kMaxPushes;
165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(ecx, loop_iterations);
166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Label loop_header;
167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ bind(&loop_header);
168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Do pushes.
169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        for (int i = 0; i < kMaxPushes; i++) {
170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ push(eax);
171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ dec(ecx);
173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(not_zero, &loop_header, Label::kNear);
174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      int remaining = locals_count % kMaxPushes;
176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Emit the remaining pushes.
177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      for (int i  = 0; i < remaining; i++) {
178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(eax);
179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool function_in_register = true;
184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Possibly allocate a local context.
186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (heap_slots > 0) {
188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Comment cmnt(masm_, "[ Allocate context");
189d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org    bool need_write_barrier = true;
190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Argument to NewContext is the function, which is still in edi.
191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(edi);
193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ Push(info->scope()->GetScopeInfo());
19447390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org      __ CallRuntime(Runtime::kNewGlobalContext, 2);
195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FastNewContextStub stub(isolate(), heap_slots);
197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ CallStub(&stub);
198d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org      // Result of FastNewContextStub is always in new space.
199d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org      need_write_barrier = false;
200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(edi);
20247390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org      __ CallRuntime(Runtime::kNewFunctionContext, 1);
203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    function_in_register = false;
205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Context is returned in eax.  It replaces the context passed to us.
206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // It's saved in the stack and kept live in esi.
207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(esi, eax);
208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax);
209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Copy parameters into context if necessary.
211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int num_parameters = info->scope()->num_parameters();
212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    for (int i = 0; i < num_parameters; i++) {
213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Variable* var = scope()->parameter(i);
214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (var->IsContextSlot()) {
215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            (num_parameters - 1 - i) * kPointerSize;
217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Load parameter from stack.
218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(eax, Operand(ebp, parameter_offset));
219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Store it in the context.
220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        int context_offset = Context::SlotOffset(var->index());
221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(Operand(esi, context_offset), eax);
222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Update the write barrier. This clobbers eax and ebx.
223d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org        if (need_write_barrier) {
22406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org          __ RecordWriteContextSlot(esi, context_offset, eax, ebx,
22506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                    kDontSaveFPRegs);
226d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org        } else if (FLAG_debug_code) {
227d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org          Label done;
228d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org          __ JumpIfInNewSpace(esi, eax, &done, Label::kNear);
229d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org          __ Abort(kExpectedNewSpaceObject);
230d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org          __ bind(&done);
231d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org        }
232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Variable* arguments = scope()->arguments();
237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (arguments != NULL) {
238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Function uses arguments object.
239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Comment cmnt(masm_, "[ Allocate arguments object");
240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (function_in_register) {
241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(edi);
242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Receiver is just before the parameters on the caller's stack.
246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int num_parameters = info->scope()->num_parameters();
247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int offset = num_parameters * kPointerSize;
248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ lea(edx,
249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(edx);
251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(Smi::FromInt(num_parameters)));
252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Arguments to ArgumentsAccessStub:
253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    //   function, receiver address, parameter count.
254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // The stub will rewrite receiver and parameter count if the previous
255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // stack frame was an arguments adapter frame.
256864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ArgumentsAccessStub::Type type;
257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (strict_mode() == STRICT) {
258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      type = ArgumentsAccessStub::NEW_STRICT;
259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (function()->has_duplicate_parameters()) {
260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ArgumentsAccessStub stub(isolate(), type);
265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CallStub(&stub);
266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    SetVar(arguments, eax, ebx, edx);
268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_trace) {
271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CallRuntime(Runtime::kTraceEnter, 0);
272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Visit the declarations and body unless there is an illegal
275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // redeclaration.
276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (scope()->HasIllegalRedeclaration()) {
277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Comment cmnt(masm_, "[ Declarations");
278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    scope()->VisitIllegalRedeclaration(this);
279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    { Comment cmnt(masm_, "[ Declarations");
283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // For named function expressions, declare the function name as a
284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // constant.
285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (scope()->is_function_scope() && scope()->function() != NULL) {
286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VariableDeclaration* function = scope()->function();
287e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(function->proxy()->var()->mode() == CONST ||
288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org               function->proxy()->var()->mode() == CONST_LEGACY);
289e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED);
290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitVariableDeclaration(function);
291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitDeclarations(scope()->declarations());
293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    { Comment cmnt(masm_, "[ Stack check");
296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
2973ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org      Label ok;
2983ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org      ExternalReference stack_limit
2993ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org          = ExternalReference::address_of_stack_limit(isolate());
3003ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org      __ cmp(esp, Operand::StaticVariable(stack_limit));
3013ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org      __ j(above_equal, &ok, Label::kNear);
3023ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org      __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET);
3033ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org      __ bind(&ok);
304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    { Comment cmnt(masm_, "[ Body");
307e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(loop_depth() == 0);
308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitStatements(function()->body());
309e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(loop_depth() == 0);
310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Always emit a 'return undefined' in case control fell off the end of
314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the body.
315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  { Comment cmnt(masm_, "[ return <undefined>;");
316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(eax, isolate()->factory()->undefined_value());
317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitReturnSequence();
318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::ClearAccumulator() {
323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(eax, Immediate(Smi::FromInt(0)));
324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, Immediate(profiling_counter_));
329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ sub(FieldOperand(ebx, Cell::kValueOffset),
330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         Immediate(Smi::FromInt(delta)));
331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitProfilingCounterReset() {
335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int reset_value = FLAG_interrupt_budget;
336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, Immediate(profiling_counter_));
337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(FieldOperand(ebx, Cell::kValueOffset),
338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         Immediate(Smi::FromInt(reset_value)));
339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                Label* back_edge_target) {
344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ Back edge bookkeeping");
345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label ok;
346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
347e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(back_edge_target->is_bound());
348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int weight = Min(kMaxBackEdgeWeight,
350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   Max(1, distance / kCodeSizeMultiplier));
351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitProfilingCounterDecrement(weight);
352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(positive, &ok, Label::kNear);
353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Record a mapping of this PC offset to the OSR id.  This is used to find
356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the AST id from the unoptimized code in order to use it as a key into
357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the deoptimization input data found in the optimized code.
358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RecordBackEdge(stmt->OsrEntryId());
359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitProfilingCounterReset();
361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&ok);
363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Record a mapping of the OSR id to this PC.  This is used if the OSR
365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // entry becomes the target of a bailout.  We don't expect it to be, but
366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // we want it to work if it is.
367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitReturnSequence() {
372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ Return sequence");
373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (return_label_.is_bound()) {
374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&return_label_);
375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Common return label
377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&return_label_);
378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (FLAG_trace) {
379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(eax);
380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ CallRuntime(Runtime::kTraceExit, 1);
381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Pretend that the exit is a backwards jump to the entry.
383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int weight = 1;
384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (info_->ShouldSelfOptimize()) {
385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      weight = FLAG_interrupt_budget / FLAG_self_opt_count;
386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      int distance = masm_->pc_offset();
388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      weight = Min(kMaxBackEdgeWeight,
389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   Max(1, distance / kCodeSizeMultiplier));
390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitProfilingCounterDecrement(weight);
392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label ok;
393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(positive, &ok, Label::kNear);
394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(eax);
395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ call(isolate()->builtins()->InterruptCheck(),
396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            RelocInfo::CODE_TARGET);
397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ pop(eax);
398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitProfilingCounterReset();
399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&ok);
400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef DEBUG
401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Add a label for checking the size of the code used for returning.
402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label check_exit_codesize;
403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    masm_->bind(&check_exit_codesize);
404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    SetSourcePosition(function()->end_position() - 1);
406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ RecordJSReturn();
407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Do not use the leave instruction here because it is too short to
408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // patch with the code required by the debugger.
409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(esp, ebp);
410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int no_frame_start = masm_->pc_offset();
411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ pop(ebp);
412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize;
414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Ret(arguments_bytes, ecx);
415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Check that the size of the code used for returning is large enough
416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // for the debugger's requirements.
417e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(Assembler::kJSReturnSequenceLength <=
418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EffectContext::Plug(Variable* var) const {
425e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
429864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
430e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  codegen()->GetVar(result_register(), var);
432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
436e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  MemOperand operand = codegen()->VarOperand(var, result_register());
438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Memory operands can be pushed directly.
439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(operand);
440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::TestContext::Plug(Variable* var) const {
444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // For simplicity we always test the accumulator register.
445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  codegen()->GetVar(result_register(), var);
446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  codegen()->DoTest(this);
448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  UNREACHABLE();  // Not used on X87.
453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::AccumulatorValueContext::Plug(
457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Heap::RootListIndex index) const {
458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  UNREACHABLE();  // Not used on X87.
459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::StackValueContext::Plug(
463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Heap::RootListIndex index) const {
464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  UNREACHABLE();  // Not used on X87.
465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  UNREACHABLE();  // Not used on X87.
470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
474864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
477864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::AccumulatorValueContext::Plug(
478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<Object> lit) const {
479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (lit->IsSmi()) {
480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ SafeMove(result_register(), Immediate(lit));
481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Move(result_register(), Immediate(lit));
483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (lit->IsSmi()) {
489864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ SafePush(Immediate(lit));
490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(lit));
492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  codegen()->PrepareForBailoutBeforeSplit(condition(),
498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          true,
499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          true_label_,
500864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          false_label_);
501e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!lit->IsUndetectableObject());  // There are no undetectable literals.
502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (false_label_ != fall_through_) __ jmp(false_label_);
504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (lit->IsTrue() || lit->IsJSObject()) {
505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (true_label_ != fall_through_) __ jmp(true_label_);
506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (lit->IsString()) {
507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (String::cast(*lit)->length() == 0) {
508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (false_label_ != fall_through_) __ jmp(false_label_);
509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (true_label_ != fall_through_) __ jmp(true_label_);
511864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (lit->IsSmi()) {
513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (Smi::cast(*lit)->value() == 0) {
514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (false_label_ != fall_through_) __ jmp(false_label_);
515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (true_label_ != fall_through_) __ jmp(true_label_);
517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // For simplicity we always test the accumulator register.
520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(result_register(), lit);
521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    codegen()->DoTest(this);
522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EffectContext::DropAndPlug(int count,
527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                   Register reg) const {
528e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(count > 0);
529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Drop(count);
530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int count,
535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register reg) const {
536e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(count > 0);
537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Drop(count);
538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(result_register(), reg);
539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
542864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count,
543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                       Register reg) const {
544e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(count > 0);
545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (count > 1) __ Drop(count - 1);
546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(Operand(esp, 0), reg);
547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
548864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
550864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::TestContext::DropAndPlug(int count,
551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                 Register reg) const {
552e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(count > 0);
553864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // For simplicity we always test the accumulator register.
554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Drop(count);
555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(result_register(), reg);
556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  codegen()->DoTest(this);
558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                            Label* materialize_false) const {
563e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(materialize_true == materialize_false);
564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(materialize_true);
565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::AccumulatorValueContext::Plug(
569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label* materialize_true,
570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label* materialize_false) const {
571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(materialize_true);
573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result_register(), isolate()->factory()->true_value());
574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done, Label::kNear);
575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(materialize_false);
576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result_register(), isolate()->factory()->false_value());
577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
579864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::StackValueContext::Plug(
582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label* materialize_true,
583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label* materialize_false) const {
584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(materialize_true);
586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(isolate()->factory()->true_value()));
587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done, Label::kNear);
588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(materialize_false);
589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(isolate()->factory()->false_value()));
590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true,
595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          Label* materialize_false) const {
596e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(materialize_true == true_label_);
597e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(materialize_false == false_label_);
598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EffectContext::Plug(bool flag) const {
602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Object> value = flag
607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ? isolate()->factory()->true_value()
608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      : isolate()->factory()->false_value();
609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result_register(), value);
610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const {
614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Object> value = flag
615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ? isolate()->factory()->true_value()
616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      : isolate()->factory()->false_value();
617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(value));
618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
621864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::TestContext::Plug(bool flag) const {
622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  codegen()->PrepareForBailoutBeforeSplit(condition(),
623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          true,
624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          true_label_,
625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          false_label_);
626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (flag) {
627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (true_label_ != fall_through_) __ jmp(true_label_);
628864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (false_label_ != fall_through_) __ jmp(false_label_);
630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::DoTest(Expression* condition,
635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Label* if_true,
636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Label* if_false,
637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Label* fall_through) {
638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallIC(ic, condition->test_id());
640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(result_register(), result_register());
641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The stub returns nonzero for true.
642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Split(not_zero, if_true, if_false, fall_through);
643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::Split(Condition cc,
647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Label* if_true,
648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Label* if_false,
649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Label* fall_through) {
650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (if_false == fall_through) {
651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(cc, if_true);
652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (if_true == fall_through) {
653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(NegateCondition(cc), if_false);
654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(cc, if_true);
656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(if_false);
657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgMemOperand FullCodeGenerator::StackOperand(Variable* var) {
662e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(var->IsStackAllocated());
663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Offset is negative because higher indexes are at lower addresses.
664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int offset = -var->index() * kPointerSize;
665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Adjust by a (parameter or local) base offset.
666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (var->IsParameter()) {
667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    offset += JavaScriptFrameConstants::kLocal0Offset;
670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return Operand(ebp, offset);
672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
676e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (var->IsContextSlot()) {
678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int context_chain_length = scope()->ContextChainLength(var->scope());
679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ LoadContext(scratch, context_chain_length);
680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return ContextOperand(scratch, var->index());
681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return StackOperand(var);
683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
684864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::GetVar(Register dest, Variable* var) {
688e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  MemOperand location = VarOperand(var, dest);
690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(dest, location);
691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
694864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::SetVar(Variable* var,
695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Register src,
696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Register scratch0,
697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Register scratch1) {
698e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
699e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!scratch0.is(src));
700e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!scratch0.is(scratch1));
701e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!scratch1.is(src));
702864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  MemOperand location = VarOperand(var, scratch0);
703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(location, src);
704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Emit the write barrier code if the location is in the heap.
706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (var->IsContextSlot()) {
707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int offset = Context::SlotOffset(var->index());
708e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi));
70906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
714864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                     bool should_normalize,
716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                     Label* if_true,
717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                     Label* if_false) {
718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Only prepare for bailouts before splits if we're in a test
719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // context. Otherwise, we let the Visit function deal with the
720864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // preparation to avoid preparing with the same AST id twice.
721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!context()->IsTest() || !info_->IsOptimizable()) return;
722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
723864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label skip;
724864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (should_normalize) __ jmp(&skip, Label::kNear);
725864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailout(expr, TOS_REG);
726864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (should_normalize) {
727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(eax, isolate()->factory()->true_value());
728864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Split(equal, if_true, if_false, NULL);
729864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&skip);
730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
731864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
732864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
733864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
734864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
735864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The variable in the declaration always resides in the current context.
736e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, scope()->ContextChainLength(variable->scope()));
737864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (generate_debug_code_) {
738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Check that we're not inside a with or catch context.
739864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset));
740864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(ebx, isolate()->factory()->with_context_map());
741864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Check(not_equal, kDeclarationInWithContext);
742864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(ebx, isolate()->factory()->catch_context_map());
743864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Check(not_equal, kDeclarationInCatchContext);
744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitVariableDeclaration(
749864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    VariableDeclaration* declaration) {
750864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If it was not possible to allocate the variable at compile time, we
751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // need to "declare" it at runtime to make sure it actually exists in the
752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // local context.
753864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VariableProxy* proxy = declaration->proxy();
754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VariableMode mode = declaration->mode();
755864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Variable* variable = proxy->var();
756864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (variable->location()) {
758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::UNALLOCATED:
759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      globals_->Add(variable->name(), zone());
760864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      globals_->Add(variable->binding_needs_init()
761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        ? isolate()->factory()->the_hole_value()
762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        : isolate()->factory()->undefined_value(), zone());
763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
765864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::PARAMETER:
766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::LOCAL:
767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (hole_init) {
768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Comment cmnt(masm_, "[ VariableDeclaration");
769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(StackOperand(variable),
770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org               Immediate(isolate()->factory()->the_hole_value()));
771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::CONTEXT:
775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (hole_init) {
776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Comment cmnt(masm_, "[ VariableDeclaration");
777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        EmitDebugCheckDeclarationContext(variable);
778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(ContextOperand(esi, variable->index()),
779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org               Immediate(isolate()->factory()->the_hole_value()));
780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // No write barrier since the hole value is in old space.
781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::LOOKUP: {
786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Comment cmnt(masm_, "[ VariableDeclaration");
787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(esi);
788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Immediate(variable->name()));
789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // VariableDeclaration nodes are always introduced in one of four modes.
790e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(IsDeclaredVariableMode(mode));
791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      PropertyAttributes attr =
792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          IsImmutableVariableMode(mode) ? READ_ONLY : NONE;
793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Immediate(Smi::FromInt(attr)));
794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Push initial value, if any.
795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Note: For variables we must not push an initial value (such as
796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // 'undefined') because we may have a (legal) redeclaration and we
797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // must not destroy the current value.
798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (hole_init) {
799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(Immediate(isolate()->factory()->the_hole_value()));
800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(Immediate(Smi::FromInt(0)));  // Indicates no initial value.
802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
803d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org      __ CallRuntime(Runtime::kDeclareLookupSlot, 4);
804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitFunctionDeclaration(
811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    FunctionDeclaration* declaration) {
812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VariableProxy* proxy = declaration->proxy();
813864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Variable* variable = proxy->var();
814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (variable->location()) {
815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::UNALLOCATED: {
816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      globals_->Add(variable->name(), zone());
817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Handle<SharedFunctionInfo> function =
8187c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org          Compiler::BuildFunctionInfo(declaration->fun(), script(), info_);
819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Check for stack-overflow exception.
820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (function.is_null()) return SetStackOverflow();
821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      globals_->Add(function, zone());
822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::PARAMETER:
826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::LOCAL: {
827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Comment cmnt(masm_, "[ FunctionDeclaration");
828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForAccumulatorValue(declaration->fun());
829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(StackOperand(variable), result_register());
830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
833864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::CONTEXT: {
834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Comment cmnt(masm_, "[ FunctionDeclaration");
835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitDebugCheckDeclarationContext(variable);
836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForAccumulatorValue(declaration->fun());
837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(ContextOperand(esi, variable->index()), result_register());
838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // We know that we have written a function, which is not a smi.
83906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ RecordWriteContextSlot(esi, Context::SlotOffset(variable->index()),
84006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                result_register(), ecx, kDontSaveFPRegs,
84106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::LOOKUP: {
847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Comment cmnt(masm_, "[ FunctionDeclaration");
848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(esi);
849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Immediate(variable->name()));
850864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Immediate(Smi::FromInt(NONE)));
851864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForStackValue(declaration->fun());
852d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org      __ CallRuntime(Runtime::kDeclareLookupSlot, 4);
853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
856864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
857864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Variable* variable = declaration->proxy()->var();
861e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(variable->location() == Variable::CONTEXT);
862e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(variable->interface()->IsFrozen());
863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ ModuleDeclaration");
865864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitDebugCheckDeclarationContext(variable);
866864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load instance object.
868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ LoadContext(eax, scope_->ContextChainLength(scope_->GlobalScope()));
869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, ContextOperand(eax, variable->interface()->Index()));
870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, ContextOperand(eax, Context::EXTENSION_INDEX));
871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Assign it.
873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ContextOperand(esi, variable->index()), eax);
874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // We know that we have written a module, which is not a smi.
87506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ RecordWriteContextSlot(esi, Context::SlotOffset(variable->index()), eax,
87606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                            ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                            OMIT_SMI_CHECK);
878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS);
879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
880864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Traverse into body.
881864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Visit(declaration->module());
882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
884864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
886864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VariableProxy* proxy = declaration->proxy();
887864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Variable* variable = proxy->var();
888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (variable->location()) {
889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::UNALLOCATED:
890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // TODO(rossberg)
891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::CONTEXT: {
894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Comment cmnt(masm_, "[ ImportDeclaration");
895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitDebugCheckDeclarationContext(variable);
896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // TODO(rossberg)
897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::PARAMETER:
901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::LOCAL:
902864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::LOOKUP:
903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      UNREACHABLE();
904864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
905864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
906864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
907864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) {
909864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // TODO(rossberg)
910864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
911864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
914864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Call the runtime to declare the globals.
915864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(esi);  // The context is the first argument.
916864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Push(pairs);
917864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Push(Smi::FromInt(DeclareGlobalsFlags()));
91847390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  __ CallRuntime(Runtime::kDeclareGlobals, 3);
919864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Return value is ignored.
920864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
921864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
922864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
923864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) {
924864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Call the runtime to declare the modules.
925864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Push(descriptions);
92647390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  __ CallRuntime(Runtime::kDeclareModules, 1);
927864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Return value is ignored.
928864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
929864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
930864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
931864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
932864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ SwitchStatement");
933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Breakable nested_statement(this, stmt);
934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SetStatementPosition(stmt);
935864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
936864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Keep the switch value on the stack until a case matches.
937864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(stmt->tag());
938864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<CaseClause*>* clauses = stmt->cases();
941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
942864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
943864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label next_test;  // Recycled for each test.
944864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Compile all the tests with branches to their bodies.
945864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < clauses->length(); i++) {
946864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CaseClause* clause = clauses->at(i);
947864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    clause->body_target()->Unuse();
948864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
949864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // The default is not a test, but remember it as final fall through.
950864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (clause->is_default()) {
951864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      default_clause = clause;
952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      continue;
953864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
954864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
955864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Comment cmnt(masm_, "[ Case comparison");
956864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&next_test);
957864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    next_test.Unuse();
958864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
959864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Compile the label expression.
960864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    VisitForAccumulatorValue(clause->label());
961864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
962864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Perform the comparison as if via '==='.
963864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(edx, Operand(esp, 0));  // Switch value.
964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    JumpPatchSite patch_site(masm_);
966864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (inline_smi_code) {
967864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label slow_case;
968864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(ecx, edx);
969864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ or_(ecx, eax);
970864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
971864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
972864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(edx, eax);
973864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(not_equal, &next_test);
974864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ Drop(1);  // Switch value is no longer needed.
975864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(clause->body_target());
976864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&slow_case);
977864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
978864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
979864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Record position before stub call for type feedback.
980864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    SetSourcePosition(clause->position());
981b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    Handle<Code> ic =
982b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org        CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
983864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallIC(ic, clause->CompareId());
984864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    patch_site.EmitPatchInfo();
985864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
986864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label skip;
987864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&skip, Label::kNear);
988864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PrepareForBailout(clause, TOS_REG);
989864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(eax, isolate()->factory()->true_value());
990864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_equal, &next_test);
991864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Drop(1);
992864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(clause->body_target());
993864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&skip);
994864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
995864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(eax, eax);
996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_equal, &next_test);
997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Drop(1);  // Switch value is no longer needed.
998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(clause->body_target());
999864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1000864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1001864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Discard the test value and jump to the default if present, otherwise to
1002864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the end of the statement.
1003864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&next_test);
1004864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Drop(1);  // Switch value is no longer needed.
1005864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (default_clause == NULL) {
1006864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(nested_statement.break_label());
1007864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(default_clause->body_target());
1009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1011864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Compile all the case bodies.
1012864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < clauses->length(); i++) {
1013864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Comment cmnt(masm_, "[ Case body");
1014864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CaseClause* clause = clauses->at(i);
1015864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(clause->body_target());
1016864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
1017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    VisitStatements(clause->statements());
1018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(nested_statement.break_label());
1021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1022864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1023864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1024864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1025864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1026864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ ForInStatement");
1027864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int slot = stmt->ForInFeedbackSlot();
1028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SetStatementPosition(stmt);
1030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1031864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label loop, exit;
1032864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ForIn loop_statement(this, stmt);
1033864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  increment_loop_depth();
1034864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1035864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the object to enumerate over. If the object is null or undefined, skip
1036864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // over the loop.  See ECMA-262 version 5, section 12.6.4.
1037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(stmt->enumerable());
1038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(eax, isolate()->factory()->undefined_value());
1039864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, &exit);
1040864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(eax, isolate()->factory()->null_value());
1041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, &exit);
1042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1043864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
1044864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1045864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Convert the object to a JS object.
1046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label convert, done_convert;
1047864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(eax, &convert, Label::kNear);
1048864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
1049864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(above_equal, &done_convert, Label::kNear);
1050864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&convert);
1051864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(eax);
1052864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1053864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done_convert);
1054864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(eax);
1055864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1056864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for proxies.
1057864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label call_runtime, use_cache, fixed_array;
1058864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1059864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx);
1060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(below_equal, &call_runtime);
1061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check cache validity in generated code. This is a fast case for
1063864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
1064864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // guarantee cache validity, call the runtime system to check cache
1065864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // validity or get the property names in a fixed array.
1066864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CheckEnumCache(&call_runtime);
1067864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1068864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
1069864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&use_cache, Label::kNear);
1070864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the set of properties to enumerate.
1072864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&call_runtime);
1073864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(eax);
1074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
1076864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         isolate()->factory()->meta_map());
1077864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &fixed_array);
1078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // We got a map in register eax. Get the enumeration cache from it.
1081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label no_descriptors;
1082864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&use_cache);
1083864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1084864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ EnumLength(edx, eax);
1085864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(edx, Immediate(Smi::FromInt(0)));
1086864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, &no_descriptors);
1087864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1088864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ LoadInstanceDescriptors(eax, ecx);
1089864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumCacheOffset));
1090864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1091864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1092864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set up the four remaining stack slots.
1093864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(eax);  // Map.
1094864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(ecx);  // Enumeration cache.
1095864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(edx);  // Number of valid entries for the map in the enum cache.
1096864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(Smi::FromInt(0)));  // Initial index.
1097864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&loop);
1098864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1099864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&no_descriptors);
1100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(esp, Immediate(kPointerSize));
1101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&exit);
1102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // We got a fixed array in register eax. Iterate through that.
1104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label non_proxy;
1105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&fixed_array);
1106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // No need for a write barrier, we are storing a Smi in the feedback vector.
1108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ LoadHeapObject(ebx, FeedbackVector());
1109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(FieldOperand(ebx, FixedArray::OffsetOfElementAt(slot)),
1110a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org         Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate())));
1111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, Immediate(Smi::FromInt(1)));  // Smi indicates slow check
1113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ecx, Operand(esp, 0 * kPointerSize));  // Get enumerated object
1114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(ecx, LAST_JS_PROXY_TYPE, ecx);
1116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(above, &non_proxy);
1117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(ebx, Immediate(Smi::FromInt(0)));  // Zero indicates proxy
1118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&non_proxy);
1119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(ebx);  // Smi
1120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(eax);  // Array
1121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
1122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(eax);  // Fixed array length (as smi).
1123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(Smi::FromInt(0)));  // Initial index.
1124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Generate code for doing the condition check.
1126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&loop);
1128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, Operand(esp, 0 * kPointerSize));  // Get the current index.
1129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(eax, Operand(esp, 1 * kPointerSize));  // Compare to the array length.
1130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(above_equal, loop_statement.break_label());
1131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the current entry of the array into register ebx.
1133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, Operand(esp, 2 * kPointerSize));
1134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize));
1135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the expected map from the stack or a smi in the
1137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // permanent slow case into register edx.
1138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx, Operand(esp, 3 * kPointerSize));
1139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check if the expected map still matches that of the enumerable.
1141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If not, we may have to filter the key.
1142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label update_each;
1143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ecx, Operand(esp, 4 * kPointerSize));
1144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset));
1145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, &update_each, Label::kNear);
1146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // For proxies, no filtering is done.
1148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
1149e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(Smi::FromInt(0) == 0);
1150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(edx, edx);
1151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(zero, &update_each);
1152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Convert the entry to a string or null if it isn't a property
1154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // anymore. If the property has been removed while iterating, we
1155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // just skip it.
1156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(ecx);  // Enumerable.
1157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(ebx);  // Current entry.
1158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(eax, eax);
1160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, loop_statement.continue_label());
1161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, eax);
1162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Update the 'each' property or variable from the possibly filtered
1164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // entry in register ebx.
1165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&update_each);
1166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result_register(), ebx);
1167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Perform the assignment as if via '='.
1168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  { EffectContext context(this);
1169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitAssignment(stmt->each());
1170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Generate code for the body of the loop.
1173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Visit(stmt->body());
1174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Generate code for going to the next element by incrementing the
1176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // index (smi) stored on top of the stack.
1177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(loop_statement.continue_label());
1178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
1179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitBackEdgeBookkeeping(stmt, &loop);
1181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&loop);
1182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Remove the pointers stored on the stack.
1184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(loop_statement.break_label());
1185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(esp, Immediate(5 * kPointerSize));
1186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Exit and decrement the loop depth.
1188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&exit);
1190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  decrement_loop_depth();
1191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
1195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ ForOfStatement");
1196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SetStatementPosition(stmt);
1197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Iteration loop_statement(this, stmt);
1199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  increment_loop_depth();
1200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
12011845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  // var iterator = iterable[Symbol.iterator]();
12021845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  VisitForEffect(stmt->assign_iterator());
1203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Loop entry.
1205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(loop_statement.continue_label());
1206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // result = iterator.next()
1208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForEffect(stmt->next_result());
1209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // if (result.done) break;
1211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label result_not_done;
1212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForControl(stmt->result_done(),
1213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                  loop_statement.break_label(),
1214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                  &result_not_done,
1215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                  &result_not_done);
1216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&result_not_done);
1217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // each = result.value
1219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForEffect(stmt->assign_each());
1220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Generate code for the body of the loop.
1222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Visit(stmt->body());
1223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check stack before looping.
1225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
1226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
1227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(loop_statement.continue_label());
1228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Exit and decrement the loop depth.
1230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(loop_statement.break_label());
1232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  decrement_loop_depth();
1233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
1237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                       bool pretenure) {
1238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Use the fast case closure allocation code that allocates in new
1239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // space for nested functions that don't need literals cloning. If
1240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // we're running with the --always-opt or the --prepare-always-opt
1241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // flag, we need to use the runtime function so that the new function
1242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // we are creating here gets a chance to have its code optimized and
1243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // doesn't just get a copy of the existing unoptimized code.
1244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!FLAG_always_opt &&
1245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      !FLAG_prepare_always_opt &&
1246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      !pretenure &&
1247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      scope()->is_function_scope() &&
1248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      info->num_literals() == 0) {
12492c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
1250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ebx, Immediate(info));
1251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CallStub(&stub);
1252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(esi);
1254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(info));
1255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(pretenure
1256864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      ? isolate()->factory()->true_value()
1257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      : isolate()->factory()->false_value()));
125847390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org    __ CallRuntime(Runtime::kNewClosure, 3);
1259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
1261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
1265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ VariableProxy");
1266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitVariableLoad(expr);
1267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1270a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgvoid FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
1271a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Comment cnmt(masm_, "[ SuperReference ");
1272a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
1273a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ mov(LoadDescriptor::ReceiverRegister(),
1274a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org         Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1275a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
1276a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
1277a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ mov(LoadDescriptor::NameRegister(), home_object_symbol);
1278a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
1279a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
1280a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
1281a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ cmp(eax, isolate()->factory()->undefined_value());
1282a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Label done;
1283a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ j(not_equal, &done);
1284a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ CallRuntime(Runtime::kThrowNonMethodError, 0);
1285a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ bind(&done);
1286a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org}
1287a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
1288a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
12897c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.orgvoid FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
1290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                      TypeofState typeof_state,
1291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                      Label* slow) {
1292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register context = esi;
1293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp = edx;
1294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Scope* s = scope();
1296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  while (s != NULL) {
1297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (s->num_heap_slots() > 0) {
1298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (s->calls_sloppy_eval()) {
1299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Check that extension is NULL.
1300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ cmp(ContextOperand(context, Context::EXTENSION_INDEX),
1301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org               Immediate(0));
1302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(not_equal, slow);
1303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
1304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Load next context in chain.
1305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Walk the rest of the chain without clobbering esi.
1307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      context = temp;
1308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // If no outer scope calls eval, we do not need to check more
1310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // context extensions.  If we have reached an eval scope, we check
1311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // all extensions from this point.
1312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break;
1313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    s = s->outer_scope();
1314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (s != NULL && s->is_eval_scope()) {
1317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Loop up the context chain.  There is no frame effect so it is
1318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // safe to use raw labels here.
1319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label next, fast;
1320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (!context.is(temp)) {
1321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(temp, context);
1322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&next);
1324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Terminate at native context.
1325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(FieldOperand(temp, HeapObject::kMapOffset),
1326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           Immediate(isolate()->factory()->native_context_map()));
1327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(equal, &fast, Label::kNear);
1328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Check that extension is NULL.
1329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
1330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_equal, slow);
1331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Load next context in chain.
1332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(temp, ContextOperand(temp, Context::PREVIOUS_INDEX));
1333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&next);
1334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&fast);
1335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // All extension objects were empty and it is safe to use a global
1338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // load IC call.
133942ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
134042ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  __ mov(LoadDescriptor::NameRegister(), proxy->var()->name());
13417c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  if (FLAG_vector_ics) {
134242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org    __ mov(VectorLoadICDescriptor::SlotRegister(),
13437c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org           Immediate(Smi::FromInt(proxy->VariableFeedbackSlot())));
13447c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  }
13457c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org
1346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
1347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ? NOT_CONTEXTUAL
1348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      : CONTEXTUAL;
1349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallLoadIC(mode);
1351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                                Label* slow) {
1356e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(var->IsContextSlot());
1357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register context = esi;
1358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp = ebx;
1359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
1361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (s->num_heap_slots() > 0) {
1362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (s->calls_sloppy_eval()) {
1363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Check that extension is NULL.
1364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ cmp(ContextOperand(context, Context::EXTENSION_INDEX),
1365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org               Immediate(0));
1366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(not_equal, slow);
1367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
1368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Walk the rest of the chain without clobbering esi.
1370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      context = temp;
1371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that last extension is NULL.
1374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
1375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, slow);
1376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // This function is used only for loads, not stores, so it's safe to
1378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // return an esi-based operand (the write barrier cannot be allowed to
1379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // destroy the esi register).
1380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return ContextOperand(context, var->index());
1381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
13847c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.orgvoid FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
1385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                  TypeofState typeof_state,
1386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                  Label* slow,
1387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                  Label* done) {
1388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Generate fast-case code for variables that might be shadowed by
1389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // eval-introduced variables.  Eval is used a lot without
1390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // introducing variables.  In those cases, we do not want to
1391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // perform a runtime call for all variables in the scope
1392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // containing the eval.
13937c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  Variable* var = proxy->var();
1394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (var->mode() == DYNAMIC_GLOBAL) {
13957c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org    EmitLoadGlobalCheckExtensions(proxy, typeof_state, slow);
1396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(done);
1397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (var->mode() == DYNAMIC_LOCAL) {
1398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Variable* local = var->local_if_not_shadowed();
1399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(eax, ContextSlotOperandCheckExtensions(local, slow));
1400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (local->mode() == LET || local->mode() == CONST ||
1401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        local->mode() == CONST_LEGACY) {
1402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(eax, isolate()->factory()->the_hole_value());
1403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(not_equal, done);
1404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (local->mode() == CONST_LEGACY) {
1405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(eax, isolate()->factory()->undefined_value());
1406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {  // LET || CONST
1407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(Immediate(var->name()));
140847390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org        __ CallRuntime(Runtime::kThrowReferenceError, 1);
1409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
1410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(done);
1412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
1417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Record position before possible IC call.
1418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SetSourcePosition(proxy->position());
1419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Variable* var = proxy->var();
1420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Three cases: global variables, lookup variables, and all other types of
1422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // variables.
1423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (var->location()) {
1424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::UNALLOCATED: {
1425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Comment cmnt(masm_, "[ Global variable");
142642ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
142742ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ mov(LoadDescriptor::NameRegister(), var->name());
14287c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org      if (FLAG_vector_ics) {
142942ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org        __ mov(VectorLoadICDescriptor::SlotRegister(),
14307c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org               Immediate(Smi::FromInt(proxy->VariableFeedbackSlot())));
14317c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org      }
1432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      CallLoadIC(CONTEXTUAL);
1433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      context()->Plug(eax);
1434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
1435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::PARAMETER:
1438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::LOCAL:
1439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::CONTEXT: {
1440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
1441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                               : "[ Stack variable");
1442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (var->binding_needs_init()) {
1443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // var->scope() may be NULL when the proxy is located in eval code and
1444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // refers to a potential outside binding. Currently those bindings are
1445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // always looked up dynamically, i.e. in that case
1446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        //     var->location() == LOOKUP.
1447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // always holds.
1448e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(var->scope() != NULL);
1449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Check if the binding really needs an initialization check. The check
1451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // can be skipped in the following situation: we have a LET or CONST
1452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // binding in harmony mode, both the Variable and the VariableProxy have
1453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // the same declaration scope (i.e. they are both in global code, in the
1454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // same function or in the same eval code) and the VariableProxy is in
1455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // the source physically located after the initializer of the variable.
1456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        //
1457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // We cannot skip any initialization checks for CONST in non-harmony
1458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // mode because const variables may be declared but never initialized:
1459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        //   if (false) { const x; }; var y = x;
1460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        //
1461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // The condition on the declaration scopes is a conservative check for
1462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // nested functions that access a binding and are called before the
1463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // binding is initialized:
1464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        //   function() { f(); let x = 1; function f() { x = 2; } }
1465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        //
1466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        bool skip_init_check;
1467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
1468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          skip_init_check = false;
1469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        } else {
1470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          // Check that we always have valid source position.
1471e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org          DCHECK(var->initializer_position() != RelocInfo::kNoPosition);
1472e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org          DCHECK(proxy->position() != RelocInfo::kNoPosition);
1473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          skip_init_check = var->mode() != CONST_LEGACY &&
1474864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org              var->initializer_position() < proxy->position();
1475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
1476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1477864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (!skip_init_check) {
1478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          // Let and const need a read barrier.
1479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          Label done;
1480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          GetVar(eax, var);
1481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ cmp(eax, isolate()->factory()->the_hole_value());
1482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ j(not_equal, &done, Label::kNear);
1483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          if (var->mode() == LET || var->mode() == CONST) {
1484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            // Throw a reference error when using an uninitialized let/const
1485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            // binding in harmony mode.
1486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            __ push(Immediate(var->name()));
148747390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org            __ CallRuntime(Runtime::kThrowReferenceError, 1);
1488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          } else {
1489864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            // Uninitalized const bindings outside of harmony mode are unholed.
1490e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org            DCHECK(var->mode() == CONST_LEGACY);
1491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            __ mov(eax, isolate()->factory()->undefined_value());
1492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          }
1493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ bind(&done);
1494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          context()->Plug(eax);
1495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
1496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
1497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
1498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      context()->Plug(var);
1499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
1500864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1501864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Variable::LOOKUP: {
1503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Comment cmnt(masm_, "[ Lookup variable");
1504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label done, slow;
1505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Generate code for loading from variables potentially shadowed
1506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // by eval-introduced variables.
15077c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org      EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
1508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&slow);
1509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(esi);  // Context.
1510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Immediate(var->name()));
15114c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org      __ CallRuntime(Runtime::kLoadLookupSlot, 2);
1512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&done);
1513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      context()->Plug(eax);
1514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
1515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ RegExpLiteral");
1522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialized;
1523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Registers will be used as follows:
1524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // edi = JS function.
1525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // ecx = literals array.
1526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // ebx = regexp literal.
1527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // eax = regexp literal clone.
1528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset));
1530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int literal_offset =
1531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, FieldOperand(ecx, literal_offset));
1533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(ebx, isolate()->factory()->undefined_value());
1534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &materialized, Label::kNear);
1535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Create regexp literal using runtime function
1537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Result will be in eax.
1538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(ecx);
1539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(Smi::FromInt(expr->literal_index())));
1540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(expr->pattern()));
1541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(expr->flags()));
154247390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, eax);
1544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&materialized);
1546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label allocated, runtime_allocate;
1548864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
1549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&allocated);
1550864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&runtime_allocate);
1552864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(ebx);
1553864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(Smi::FromInt(size)));
155447390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(ebx);
1556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&allocated);
1558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Copy the content into the newly allocated memory.
1559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // (Unroll copy loop once for better throughput).
1560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
1561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(edx, FieldOperand(ebx, i));
1562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ecx, FieldOperand(ebx, i + kPointerSize));
1563864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(FieldOperand(eax, i), edx);
1564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(FieldOperand(eax, i + kPointerSize), ecx);
1565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if ((size % (2 * kPointerSize)) != 0) {
1567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(edx, FieldOperand(ebx, size - kPointerSize));
1568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(FieldOperand(eax, size - kPointerSize), edx);
1569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
1571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitAccessor(Expression* expression) {
1575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (expression == NULL) {
1576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(isolate()->factory()->null_value()));
1577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    VisitForStackValue(expression);
1579864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ ObjectLiteral");
1585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  expr->BuildConstantProperties(isolate());
1587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<FixedArray> constant_properties = expr->constant_properties();
1588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int flags = expr->fast_elements()
1589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ? ObjectLiteral::kFastElements
1590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      : ObjectLiteral::kNoFlags;
1591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  flags |= expr->has_function()
1592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ? ObjectLiteral::kHasFunction
1593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      : ObjectLiteral::kNoFlags;
1594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int properties_count = constant_properties->length() / 2;
1595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (expr->may_store_doubles() || expr->depth() > 1 ||
1596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      masm()->serializer_enabled() ||
1597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      flags != ObjectLiteral::kFastElements ||
1598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
1599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(FieldOperand(edi, JSFunction::kLiteralsOffset));
1601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(Smi::FromInt(expr->literal_index())));
1602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(constant_properties));
1603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(Smi::FromInt(flags)));
160447390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
1605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(eax, FieldOperand(edi, JSFunction::kLiteralsOffset));
1608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index())));
1609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ecx, Immediate(constant_properties));
1610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(edx, Immediate(Smi::FromInt(flags)));
1611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    FastCloneShallowObjectStub stub(isolate(), properties_count);
1612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CallStub(&stub);
1613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If result_saved is true the result is on top of the stack.  If
1616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // result_saved is false the result is in eax.
1617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool result_saved = false;
1618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Mark all computed expressions that are bound to a key that
1620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // is shadowed by a later occurrence of the same key. For the
1621864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // marked expressions, no store code is emitted.
1622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  expr->CalculateEmitStore(zone());
1623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  AccessorTable accessor_table(zone());
1625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < expr->properties()->length(); i++) {
1626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ObjectLiteral::Property* property = expr->properties()->at(i);
1627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (property->IsCompileTimeValue()) continue;
1628864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Literal* key = property->key();
1630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Expression* value = property->value();
1631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (!result_saved) {
1632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(eax);  // Save result on the stack
1633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      result_saved = true;
1634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    switch (property->kind()) {
1636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case ObjectLiteral::Property::CONSTANT:
1637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        UNREACHABLE();
1638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1639e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
1640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Fall through.
1641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case ObjectLiteral::Property::COMPUTED:
1642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (key->value()->IsInternalizedString()) {
1643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          if (property->emit_store()) {
1644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            VisitForAccumulatorValue(value);
164542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org            DCHECK(StoreDescriptor::ValueRegister().is(eax));
164642ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org            __ mov(StoreDescriptor::NameRegister(), Immediate(key->value()));
164742ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org            __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
1648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            CallStoreIC(key->LiteralFeedbackId());
1649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            PrepareForBailoutForId(key->id(), NO_REGISTERS);
1650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          } else {
1651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            VisitForEffect(value);
1652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          }
1653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
1654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
1655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(Operand(esp, 0));  // Duplicate receiver.
1656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForStackValue(key);
1657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForStackValue(value);
1658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (property->emit_store()) {
165960fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org          __ push(Immediate(Smi::FromInt(SLOPPY)));  // Strict mode
166060fc910a49e86bb7faeeee0017abbd1ca05d16e8machenbach@chromium.org          __ CallRuntime(Runtime::kSetProperty, 4);
1661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        } else {
1662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ Drop(3);
1663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
1664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case ObjectLiteral::Property::PROTOTYPE:
1666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(Operand(esp, 0));  // Duplicate receiver.
1667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForStackValue(value);
1668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (property->emit_store()) {
1669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ CallRuntime(Runtime::kSetPrototype, 2);
1670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        } else {
1671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ Drop(2);
1672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
1673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case ObjectLiteral::Property::GETTER:
1675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        accessor_table.lookup(key)->second->getter = value;
1676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case ObjectLiteral::Property::SETTER:
1678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        accessor_table.lookup(key)->second->setter = value;
1679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Emit code to define accessors, using only a single call to the runtime for
1684864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // each pair of corresponding getters and setters.
1685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (AccessorTable::Iterator it = accessor_table.begin();
1686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       it != accessor_table.end();
1687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       ++it) {
1688864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Operand(esp, 0));  // Duplicate receiver.
1689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    VisitForStackValue(it->first);
1690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitAccessor(it->second->getter);
1691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitAccessor(it->second->setter);
1692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(Smi::FromInt(NONE)));
1693248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org    __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
1694864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (expr->has_function()) {
1697e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(result_saved);
1698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Operand(esp, 0));
1699864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CallRuntime(Runtime::kToFastProperties, 1);
1700864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1701864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1702864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (result_saved) {
1703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    context()->PlugTOS();
1704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    context()->Plug(eax);
1706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1709864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ ArrayLiteral");
1712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  expr->BuildConstantElements(isolate());
1714864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int flags = expr->depth() == 1
1715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ? ArrayLiteral::kShallowElements
1716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      : ArrayLiteral::kNoFlags;
1717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* subexprs = expr->values();
1719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int length = subexprs->length();
1720864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<FixedArray> constant_elements = expr->constant_elements();
1721e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(2, constant_elements->length());
1722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ElementsKind constant_elements_kind =
1723864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
1724864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool has_constant_fast_elements =
1725864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      IsFastObjectElementsKind(constant_elements_kind);
1726864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<FixedArrayBase> constant_elements_values(
1727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FixedArrayBase::cast(constant_elements->get(1)));
1728864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1729864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
1731864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // If the only customer of allocation sites is transitioning, then
1732864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // we can turn it off if we don't have anywhere else to transition to.
1733864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1734864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1735864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1736e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) {
1737864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
1739864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(Smi::FromInt(expr->literal_index())));
1740864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(constant_elements));
1741864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(Smi::FromInt(flags)));
174247390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org    __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
1743864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(eax, FieldOperand(ebx, JSFunction::kLiteralsOffset));
1746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index())));
1747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ecx, Immediate(constant_elements));
1748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
1749864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CallStub(&stub);
1750864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool result_saved = false;  // Is the result saved to the stack?
1753864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Emit code to evaluate all the non-constant subexpressions and to store
1755864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // them into the newly cloned array.
1756864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < length; i++) {
1757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Expression* subexpr = subexprs->at(i);
1758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // If the subexpression is a literal or a simple materialized literal it
1759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // is already set in the cloned array.
1760864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (!result_saved) {
1763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(eax);  // array literal.
1764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Immediate(Smi::FromInt(expr->literal_index())));
1765864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      result_saved = true;
1766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    VisitForAccumulatorValue(subexpr);
1768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (IsFastObjectElementsKind(constant_elements_kind)) {
1770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they
1771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // cannot transition and don't need to call the runtime stub.
1772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(ebx, Operand(esp, kPointerSize));  // Copy of array literal.
1774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
1775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Store the subexpression value in the array's elements.
1776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(FieldOperand(ebx, offset), result_register());
1777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Update the write barrier for the array store.
177806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ RecordWriteField(ebx, offset, result_register(), ecx, kDontSaveFPRegs,
177906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                          EMIT_REMEMBERED_SET, INLINE_SMI_CHECK);
1780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
1781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Store the subexpression value in the array's elements.
1782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(ecx, Immediate(Smi::FromInt(i)));
1783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      StoreArrayLiteralElementStub stub(isolate());
1784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ CallStub(&stub);
1785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
1788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (result_saved) {
1791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ add(esp, Immediate(kPointerSize));  // literal index
1792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    context()->PlugTOS();
1793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    context()->Plug(eax);
1795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1800e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(expr->target()->IsValidReferenceExpression());
1801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ Assignment");
1803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Left-hand side can only be a property, a global or a (parameter or local)
1805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // slot.
1806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LhsKind assign_type = VARIABLE;
1808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Property* property = expr->target()->AsProperty();
1809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (property != NULL) {
1810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    assign_type = (property->key()->IsPropertyName())
1811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        ? NAMED_PROPERTY
1812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : KEYED_PROPERTY;
1813864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Evaluate LHS expression.
1816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (assign_type) {
1817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case VARIABLE:
1818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Nothing to do here.
1819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
1820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case NAMED_PROPERTY:
1821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expr->is_compound()) {
182258a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org        // We need the receiver both on the stack and in the register.
1823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForStackValue(property->obj());
182442ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org        __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
1825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
1826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForStackValue(property->obj());
1827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
1828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
1829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case KEYED_PROPERTY: {
1830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expr->is_compound()) {
1831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForStackValue(property->obj());
1832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForStackValue(property->key());
183342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org        __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, kPointerSize));
183442ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org        __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0));
1835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
1836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForStackValue(property->obj());
1837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForStackValue(property->key());
1838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
1839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
1840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // For compound assignments we need another deoptimization point after the
1844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // variable/property load.
1845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (expr->is_compound()) {
1846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    AccumulatorValueContext result_context(this);
1847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    { AccumulatorValueContext left_operand_context(this);
1848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      switch (assign_type) {
1849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        case VARIABLE:
1850864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          EmitVariableLoad(expr->target()->AsVariableProxy());
1851864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          PrepareForBailout(expr->target(), TOS_REG);
1852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
1853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        case NAMED_PROPERTY:
1854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          EmitNamedPropertyLoad(property);
1855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          PrepareForBailoutForId(property->LoadId(), TOS_REG);
1856864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
1857864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        case KEYED_PROPERTY:
1858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          EmitKeyedPropertyLoad(property);
1859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          PrepareForBailoutForId(property->LoadId(), TOS_REG);
1860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
1861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
1862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Token::Value op = expr->binary_op();
1865864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(eax);  // Left operand goes on the stack.
1866864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    VisitForAccumulatorValue(expr->value());
1867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
1869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        ? OVERWRITE_RIGHT
1870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : NO_OVERWRITE;
1871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    SetSourcePosition(expr->position() + 1);
1872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (ShouldInlineSmiCase(op)) {
1873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitInlineSmiBinaryOp(expr->binary_operation(),
1874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                            op,
1875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                            mode,
1876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                            expr->target(),
1877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                            expr->value());
1878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
1879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitBinaryOp(expr->binary_operation(), op, mode);
1880864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1881864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Deoptimization point in case the binary operation may have side effects.
1883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PrepareForBailout(expr->binary_operation(), TOS_REG);
1884864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    VisitForAccumulatorValue(expr->value());
1886864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1887864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Record source position before possible IC call.
1889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SetSourcePosition(expr->position());
1890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Store the value.
1892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (assign_type) {
1893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case VARIABLE:
1894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                             expr->op());
1896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      context()->Plug(eax);
1898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
1899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case NAMED_PROPERTY:
1900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitNamedPropertyAssignment(expr);
1901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
1902864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case KEYED_PROPERTY:
1903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitKeyedPropertyAssignment(expr);
1904864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
1905864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1906864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1907864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1909864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitYield(Yield* expr) {
1910864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ Yield");
1911864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Evaluate yielded value first; the initial iterator definition depends on
1912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // this.  It stays on the stack while we update the iterator.
1913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(expr->expression());
1914864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1915864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (expr->yield_kind()) {
191621d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    case Yield::kSuspend:
1917864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Pop value from top-of-stack slot; box result into result register.
1918864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitCreateIteratorResult(false);
1919864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(result_register());
1920864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Fall through.
192121d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    case Yield::kInitial: {
1922864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label suspend, continuation, post_runtime, resume;
1923864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1924864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&suspend);
1925864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1926864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&continuation);
1927864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&resume);
1928864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1929864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&suspend);
1930864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForAccumulatorValue(expr->generator_object());
1931e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
1932864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset),
1933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             Immediate(Smi::FromInt(continuation.pos())));
1934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi);
1935864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(ecx, esi);
193606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx,
193706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                          kDontSaveFPRegs);
1938864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset));
1939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(esp, ebx);
1940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(equal, &post_runtime);
1941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(eax);  // generator object
194247390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org      __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
1943864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(context_register(),
1944864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             Operand(ebp, StandardFrameConstants::kContextOffset));
1945864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&post_runtime);
1946864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ pop(result_register());
1947864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitReturnSequence();
1948864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1949864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&resume);
1950864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      context()->Plug(result_register());
1951864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
1952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1953864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
195421d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    case Yield::kFinal: {
1955864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForAccumulatorValue(expr->generator_object());
1956864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(FieldOperand(result_register(),
1957864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                          JSGeneratorObject::kContinuationOffset),
1958864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
1959864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Pop value from top-of-stack slot, box result into result register.
1960864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitCreateIteratorResult(true);
1961864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitUnwindBeforeReturn();
1962864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitReturnSequence();
1963864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
1964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
196621d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    case Yield::kDelegating: {
1967864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForStackValue(expr->generator_object());
1968864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1969864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Initial stack layout is as follows:
1970864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // [sp + 1 * kPointerSize] iter
1971864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // [sp + 0 * kPointerSize] g
1972864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1973864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label l_catch, l_try, l_suspend, l_continuation, l_resume;
1974864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label l_next, l_call, l_loop;
197542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      Register load_receiver = LoadDescriptor::ReceiverRegister();
197642ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      Register load_name = LoadDescriptor::NameRegister();
197758a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org
1978864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Initial send value is undefined.
1979864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(eax, isolate()->factory()->undefined_value());
1980864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&l_next);
1981864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1982864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
1983864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&l_catch);
1984864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
198558a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org      __ mov(load_name, isolate()->factory()->throw_string());  // "throw"
198658a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org      __ push(load_name);                                       // "throw"
198758a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org      __ push(Operand(esp, 2 * kPointerSize));                  // iter
198858a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org      __ push(eax);                                             // exception
1989864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&l_call);
1990864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1991864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // try { received = %yield result }
1992864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Shuffle the received result above a try handler and yield it without
1993864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // re-boxing.
1994864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&l_try);
1995864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ pop(eax);                                       // result
1996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ PushTryHandler(StackHandler::CATCH, expr->index());
1997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      const int handler_size = StackHandlerConstants::kSize;
1998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(eax);                                      // result
1999864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&l_suspend);
2000864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&l_continuation);
2001864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&l_resume);
2002864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&l_suspend);
2003864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      const int generator_object_depth = kPointerSize + handler_size;
2004864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(eax, Operand(esp, generator_object_depth));
2005864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(eax);                                      // g
2006e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
2007864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset),
2008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             Immediate(Smi::FromInt(l_continuation.pos())));
2009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi);
2010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(ecx, esi);
201106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx,
201206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                          kDontSaveFPRegs);
201347390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org      __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2014864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(context_register(),
2015864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             Operand(ebp, StandardFrameConstants::kContextOffset));
2016864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ pop(eax);                                       // result
2017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitReturnSequence();
2018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&l_resume);                                // received in eax
2019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ PopTryHandler();
2020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // receiver = iter; f = iter.next; arg = received;
2022864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&l_next);
2023248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org
202458a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org      __ mov(load_name, isolate()->factory()->next_string());
202558a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org      __ push(load_name);                           // "next"
202658a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org      __ push(Operand(esp, 2 * kPointerSize));      // iter
202758a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org      __ push(eax);                                 // received
2028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // result = receiver[f](arg);
2030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&l_call);
203158a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org      __ mov(load_receiver, Operand(esp, kPointerSize));
20327c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org      if (FLAG_vector_ics) {
203342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org        __ mov(VectorLoadICDescriptor::SlotRegister(),
20347c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org               Immediate(Smi::FromInt(expr->KeyedLoadFeedbackSlot())));
20357c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org      }
2036b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
2037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      CallIC(ic, TypeFeedbackId::None());
2038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(edi, eax);
2039864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(Operand(esp, 2 * kPointerSize), edi);
2040864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
2041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ CallStub(&stub);
2042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2043864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2044864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ Drop(1);  // The function is still on the stack; drop it.
2045864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // if (!result.done) goto l_try;
2047864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&l_loop);
2048864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(eax);                                      // save result
204958a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org      __ Move(load_receiver, eax);                       // result
2050248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org      __ mov(load_name,
2051248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org             isolate()->factory()->done_string());       // "done"
20527c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org      if (FLAG_vector_ics) {
205342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org        __ mov(VectorLoadICDescriptor::SlotRegister(),
20547c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org               Immediate(Smi::FromInt(expr->DoneFeedbackSlot())));
20557c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org      }
2056864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      CallLoadIC(NOT_CONTEXTUAL);                        // result.done in eax
2057864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
2058864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      CallIC(bool_ic);
2059864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ test(eax, eax);
2060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(zero, &l_try);
2061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // result.value
2063248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org      __ pop(load_receiver);                              // result
2064248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org      __ mov(load_name,
2065248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org             isolate()->factory()->value_string());       // "value"
20667c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org      if (FLAG_vector_ics) {
206742ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org        __ mov(VectorLoadICDescriptor::SlotRegister(),
20687c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org               Immediate(Smi::FromInt(expr->ValueFeedbackSlot())));
20697c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org      }
2070864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      CallLoadIC(NOT_CONTEXTUAL);                         // result.value in eax
2071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      context()->DropAndPlug(2, eax);                     // drop iter and g
2072864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2073864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2076864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2077864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitGeneratorResume(Expression *generator,
2079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Expression *value,
2080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    JSGeneratorObject::ResumeMode resume_mode) {
2081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The value stays in eax, and is ultimately read by the resumed generator, as
208247390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
2083864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // is read to throw the value when the resumed generator is already closed.
2084864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // ebx will hold the generator object until the activation has been resumed.
2085864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(generator);
2086864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(value);
2087864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(ebx);
2088864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2089864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check generator state.
2090864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label wrong_state, closed_state, done;
2091864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
2092864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
2093864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(FieldOperand(ebx, JSGeneratorObject::kContinuationOffset),
2094864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         Immediate(Smi::FromInt(0)));
2095864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, &closed_state);
2096864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(less, &wrong_state);
2097864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2098864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load suspended function and context.
2099864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(esi, FieldOperand(ebx, JSGeneratorObject::kContextOffset));
2100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset));
2101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Push receiver.
2103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(FieldOperand(ebx, JSGeneratorObject::kReceiverOffset));
2104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Push holes for arguments to generator function.
2106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx,
2108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
2109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ecx, isolate()->factory()->the_hole_value());
2110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label push_argument_holes, push_frame;
2111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&push_argument_holes);
2112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ sub(edx, Immediate(Smi::FromInt(1)));
2113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(carry, &push_frame);
2114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(ecx);
2115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&push_argument_holes);
2116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Enter a new JavaScript frame, and initialize its slots as they were when
2118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the generator was suspended.
2119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label resume_frame;
2120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&push_frame);
2121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ call(&resume_frame);
2122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
2123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&resume_frame);
2124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(ebp);  // Caller's frame pointer.
2125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebp, esp);
2126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(esi);  // Callee's context.
2127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(edi);  // Callee's JS Function.
2128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the operand stack size.
2130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx, FieldOperand(ebx, JSGeneratorObject::kOperandStackOffset));
2131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx, FieldOperand(edx, FixedArray::kLengthOffset));
2132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiUntag(edx);
2133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If we are sending a value and there is no operand stack, we can jump back
2135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // in directly.
2136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (resume_mode == JSGeneratorObject::NEXT) {
2137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label slow_resume;
2138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(edx, Immediate(0));
2139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_zero, &slow_resume);
2140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
2141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ecx, FieldOperand(ebx, JSGeneratorObject::kContinuationOffset));
2142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ SmiUntag(ecx);
2143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ add(edx, ecx);
2144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(FieldOperand(ebx, JSGeneratorObject::kContinuationOffset),
2145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
2146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(edx);
2147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&slow_resume);
2148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Otherwise, we push holes for the operand stack and call the runtime to fix
2151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // up the stack and the handlers.
2152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label push_operand_holes, call_resume;
2153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&push_operand_holes);
2154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ sub(edx, Immediate(1));
2155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(carry, &call_resume);
2156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(ecx);
2157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&push_operand_holes);
2158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&call_resume);
2159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(ebx);
2160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(result_register());
2161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Push(Smi::FromInt(resume_mode));
216247390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3);
2163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Not reached: the runtime call returns elsewhere.
2164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Abort(kGeneratorFailedToResume);
2165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Reach here when generator is closed.
2167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&closed_state);
2168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (resume_mode == JSGeneratorObject::NEXT) {
2169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Return completed iterator result when generator is closed.
2170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(isolate()->factory()->undefined_value()));
2171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Pop value from top-of-stack slot; box result into result register.
2172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitCreateIteratorResult(true);
2173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Throw the provided value.
2175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(eax);
217647390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org    __ CallRuntime(Runtime::kThrow, 1);
2177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
2179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Throw error if we attempt to operate on a running generator.
2181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&wrong_state);
2182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(ebx);
218347390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  __ CallRuntime(Runtime::kThrowGeneratorStateError, 1);
2184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
2186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(result_register());
2187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitCreateIteratorResult(bool done) {
2191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label gc_required;
2192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label allocated;
2193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2194b1d9f4b46c9d3041103c0d47fada41ea1ee9c839weiliang.lin@intel.com  const int instance_size = 5 * kPointerSize;
2195b1d9f4b46c9d3041103c0d47fada41ea1ee9c839weiliang.lin@intel.com  DCHECK_EQ(isolate()->native_context()->iterator_result_map()->instance_size(),
2196b1d9f4b46c9d3041103c0d47fada41ea1ee9c839weiliang.lin@intel.com            instance_size);
2197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2198b1d9f4b46c9d3041103c0d47fada41ea1ee9c839weiliang.lin@intel.com  __ Allocate(instance_size, eax, ecx, edx, &gc_required, TAG_OBJECT);
2199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&allocated);
2200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&gc_required);
2202b1d9f4b46c9d3041103c0d47fada41ea1ee9c839weiliang.lin@intel.com  __ Push(Smi::FromInt(instance_size));
220347390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(context_register(),
2205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         Operand(ebp, StandardFrameConstants::kContextOffset));
2206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&allocated);
2208b1d9f4b46c9d3041103c0d47fada41ea1ee9c839weiliang.lin@intel.com  __ mov(ebx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
2209b1d9f4b46c9d3041103c0d47fada41ea1ee9c839weiliang.lin@intel.com  __ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset));
2210b1d9f4b46c9d3041103c0d47fada41ea1ee9c839weiliang.lin@intel.com  __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX));
2211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(ecx);
2212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx, isolate()->factory()->ToBoolean(done));
2213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx);
2214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
2215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         isolate()->factory()->empty_fixed_array());
2216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(FieldOperand(eax, JSObject::kElementsOffset),
2217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         isolate()->factory()->empty_fixed_array());
2218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(FieldOperand(eax, JSGeneratorObject::kResultValuePropertyOffset), ecx);
2219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(FieldOperand(eax, JSGeneratorObject::kResultDonePropertyOffset), edx);
2220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Only the value field needs a write barrier, as the other values are in the
2222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // root set.
222306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset, ecx,
222406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                      edx, kDontSaveFPRegs);
2225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
2229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SetSourcePosition(prop->position());
2230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Literal* key = prop->key()->AsLiteral();
2231e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!key->value()->IsSmi());
223242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  __ mov(LoadDescriptor::NameRegister(), Immediate(key->value()));
22337c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  if (FLAG_vector_ics) {
223442ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org    __ mov(VectorLoadICDescriptor::SlotRegister(),
22357c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org           Immediate(Smi::FromInt(prop->PropertyFeedbackSlot())));
22367c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org    CallLoadIC(NOT_CONTEXTUAL);
22377c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  } else {
22387c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org    CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
22397c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  }
2240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2243a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgvoid FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
2244a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  SetSourcePosition(prop->position());
2245a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Literal* key = prop->key()->AsLiteral();
2246a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  DCHECK(!key->value()->IsSmi());
2247a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  DCHECK(prop->IsSuperAccess());
2248a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
2249a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  SuperReference* super_ref = prop->obj()->AsSuperReference();
2250a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  EmitLoadHomeObject(super_ref);
2251a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ push(eax);
2252a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  VisitForStackValue(super_ref->this_var());
2253a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ push(Immediate(key->value()));
2254a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ CallRuntime(Runtime::kLoadFromSuper, 3);
2255a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org}
2256a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
2257a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
2258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
2259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SetSourcePosition(prop->position());
2260b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
22617c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  if (FLAG_vector_ics) {
226242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org    __ mov(VectorLoadICDescriptor::SlotRegister(),
22637c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org           Immediate(Smi::FromInt(prop->PropertyFeedbackSlot())));
22647c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org    CallIC(ic);
22657c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  } else {
22667c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org    CallIC(ic, prop->PropertyFeedbackId());
22677c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  }
2268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
2272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                              Token::Value op,
2273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                              OverwriteMode mode,
2274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                              Expression* left,
2275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                              Expression* right) {
2276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Do combined smi check of the operands. Left operand is on the
2277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // stack. Right operand is in eax.
2278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label smi_case, done, stub_call;
2279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(edx);
2280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ecx, eax);
2281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ or_(eax, edx);
2282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  JumpPatchSite patch_site(masm_);
2283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear);
2284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&stub_call);
2286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, ecx);
2287b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code();
2288b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  CallIC(code, expr->BinaryOperationFeedbackId());
2289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  patch_site.EmitPatchInfo();
2290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done, Label::kNear);
2291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Smi case.
2293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&smi_case);
2294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, edx);  // Copy left operand in case of a stub call.
2295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (op) {
2297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::SAR:
2298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ SmiUntag(ecx);
2299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ sar_cl(eax);  // No checks of result necessary
2300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ and_(eax, Immediate(~kSmiTagMask));
2301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::SHL: {
2303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label result_ok;
2304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ SmiUntag(eax);
2305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ SmiUntag(ecx);
2306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ shl_cl(eax);
2307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Check that the *signed* result fits in a smi.
2308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(eax, 0xc0000000);
2309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(positive, &result_ok);
2310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ SmiTag(ecx);
2311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&stub_call);
2312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&result_ok);
2313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ SmiTag(eax);
2314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::SHR: {
2317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label result_ok;
2318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ SmiUntag(eax);
2319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ SmiUntag(ecx);
2320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ shr_cl(eax);
2321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ test(eax, Immediate(0xc0000000));
2322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(zero, &result_ok);
2323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ SmiTag(ecx);
2324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&stub_call);
2325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&result_ok);
2326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ SmiTag(eax);
2327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::ADD:
2330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ add(eax, ecx);
2331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(overflow, &stub_call);
2332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::SUB:
2334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ sub(eax, ecx);
2335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(overflow, &stub_call);
2336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::MUL: {
2338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ SmiUntag(eax);
2339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ imul(eax, ecx);
2340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(overflow, &stub_call);
2341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ test(eax, eax);
2342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(not_zero, &done, Label::kNear);
2343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(ebx, edx);
2344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ or_(ebx, ecx);
2345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(negative, &stub_call);
2346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::BIT_OR:
2349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ or_(eax, ecx);
2350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::BIT_AND:
2352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ and_(eax, ecx);
2353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::BIT_XOR:
2355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ xor_(eax, ecx);
2356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    default:
2358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      UNREACHABLE();
2359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
2362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
2363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
2367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                     Token::Value op,
2368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                     OverwriteMode mode) {
2369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(edx);
2370b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code();
2371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
2372b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  CallIC(code, expr->BinaryOperationFeedbackId());
2373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  patch_site.EmitPatchInfo();
2374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
2375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitAssignment(Expression* expr) {
2379e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(expr->IsValidReferenceExpression());
2380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Left-hand side can only be a property, a global or a (parameter or local)
2382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // slot.
2383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
2384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LhsKind assign_type = VARIABLE;
2385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Property* prop = expr->AsProperty();
2386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (prop != NULL) {
2387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    assign_type = (prop->key()->IsPropertyName())
2388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        ? NAMED_PROPERTY
2389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : KEYED_PROPERTY;
2390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (assign_type) {
2393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case VARIABLE: {
2394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Variable* var = expr->AsVariableProxy()->var();
2395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EffectContext context(this);
2396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitVariableAssignment(var, Token::ASSIGN);
2397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case NAMED_PROPERTY: {
2400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(eax);  // Preserve value.
2401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForAccumulatorValue(prop->obj());
240242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ Move(StoreDescriptor::ReceiverRegister(), eax);
240342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ pop(StoreDescriptor::ValueRegister());  // Restore value.
240442ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ mov(StoreDescriptor::NameRegister(),
24057b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org             prop->key()->AsLiteral()->value());
2406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      CallStoreIC();
2407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case KEYED_PROPERTY: {
2410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(eax);  // Preserve value.
2411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForStackValue(prop->obj());
2412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForAccumulatorValue(prop->key());
241342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ Move(StoreDescriptor::NameRegister(), eax);
241442ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ pop(StoreDescriptor::ReceiverRegister());  // Receiver.
241542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ pop(StoreDescriptor::ValueRegister());     // Restore value.
2416b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org      Handle<Code> ic =
2417b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org          CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code();
2418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      CallIC(ic);
2419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
2423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Variable* var, MemOperand location) {
2428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(location, eax);
2429864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (var->IsContextSlot()) {
2430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(edx, eax);
2431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int offset = Context::SlotOffset(var->index());
243206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs);
2433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitVariableAssignment(Variable* var,
2438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                               Token::Value op) {
2439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (var->IsUnallocated()) {
2440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Global var, const, or let.
244142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org    __ mov(StoreDescriptor::NameRegister(), var->name());
244242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org    __ mov(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
2443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallStoreIC();
2444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (op == Token::INIT_CONST_LEGACY) {
2446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Const initializers need a write barrier.
2447e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!var->IsParameter());  // No const parameters.
2448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (var->IsLookupSlot()) {
2449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(eax);
2450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(esi);
2451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Immediate(var->name()));
2452d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org      __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3);
2453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
2454e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(var->IsStackLocal() || var->IsContextSlot());
2455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label skip;
2456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      MemOperand location = VarOperand(var, ecx);
2457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(edx, location);
2458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(edx, isolate()->factory()->the_hole_value());
2459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(not_equal, &skip, Label::kNear);
2460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitStoreToStackLocalOrContextSlot(var, location);
2461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&skip);
2462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (var->mode() == LET && op != Token::INIT_LET) {
2465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Non-initializing assignment to let variable needs a write barrier.
2466e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!var->IsLookupSlot());
2467e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2468d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org    Label assign;
2469d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org    MemOperand location = VarOperand(var, ecx);
2470d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org    __ mov(edx, location);
2471d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org    __ cmp(edx, isolate()->factory()->the_hole_value());
2472d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org    __ j(not_equal, &assign, Label::kNear);
2473d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org    __ push(Immediate(var->name()));
2474d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org    __ CallRuntime(Runtime::kThrowReferenceError, 1);
2475d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org    __ bind(&assign);
2476d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org    EmitStoreToStackLocalOrContextSlot(var, location);
2477864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
2479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (var->IsLookupSlot()) {
2480d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org      // Assignment to var.
2481d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org      __ push(eax);  // Value.
2482d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org      __ push(esi);  // Context.
2483d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org      __ push(Immediate(var->name()));
2484d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org      __ push(Immediate(Smi::FromInt(strict_mode())));
2485d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org      __ CallRuntime(Runtime::kStoreLookupSlot, 4);
2486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
2487d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org      // Assignment to var or initializing assignment to let/const in harmony
2488d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org      // mode.
2489e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      MemOperand location = VarOperand(var, ecx);
2491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (generate_debug_code_ && op == Token::INIT_LET) {
2492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Check for an uninitialized let binding.
2493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(edx, location);
2494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ cmp(edx, isolate()->factory()->the_hole_value());
2495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ Check(equal, kLetBindingReInitialization);
2496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
2497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitStoreToStackLocalOrContextSlot(var, location);
2498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2500864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Non-initializing assignments to consts are ignored.
2501864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Assignment to a property, using a named store IC.
2506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // eax    : value
2507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // esp[0] : receiver
2508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Property* prop = expr->target()->AsProperty();
2510e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(prop != NULL);
2511e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(prop->key()->IsLiteral());
2512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Record source code position before IC call.
2514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SetSourcePosition(expr->position());
251542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  __ mov(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value());
251642ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  __ pop(StoreDescriptor::ReceiverRegister());
2517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallStoreIC(expr->AssignmentFeedbackId());
2518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
2520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Assignment to a property, using a keyed store IC.
2525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // eax               : value
2526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // esp[0]            : key
2527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // esp[kPointerSize] : receiver
2528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
252942ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  __ pop(StoreDescriptor::NameRegister());  // Key.
253042ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  __ pop(StoreDescriptor::ReceiverRegister());
253142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  DCHECK(StoreDescriptor::ValueRegister().is(eax));
2532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Record source code position before IC call.
2533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SetSourcePosition(expr->position());
2534b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Handle<Code> ic = CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code();
2535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallIC(ic, expr->AssignmentFeedbackId());
2536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
2539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2542864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitProperty(Property* expr) {
2543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ Property");
2544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Expression* key = expr->key();
2545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (key->IsPropertyName()) {
2547a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    if (!expr->IsSuperAccess()) {
2548a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      VisitForAccumulatorValue(expr->obj());
2549a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ Move(LoadDescriptor::ReceiverRegister(), result_register());
2550a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      EmitNamedPropertyLoad(expr);
2551a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    } else {
2552a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      EmitNamedSuperPropertyLoad(expr);
2553a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    }
2554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PrepareForBailoutForId(expr->LoadId(), TOS_REG);
2555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    context()->Plug(eax);
2556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    VisitForStackValue(expr->obj());
2558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    VisitForAccumulatorValue(expr->key());
255942ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org    __ pop(LoadDescriptor::ReceiverRegister());                  // Object.
256042ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org    __ Move(LoadDescriptor::NameRegister(), result_register());  // Key.
2561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitKeyedPropertyLoad(expr);
2562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    context()->Plug(eax);
2563864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::CallIC(Handle<Code> code,
2568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               TypeFeedbackId ast_id) {
2569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ic_total_count_++;
2570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ call(code, RelocInfo::CODE_TARGET, ast_id);
2571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Code common for calls using the IC.
2575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
2576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Expression* callee = expr->expression();
2577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2578a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  CallICState::CallType call_type =
2579a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD;
2580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the target function.
2581a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  if (call_type == CallICState::FUNCTION) {
2582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    { StackValueContext context(this);
2583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitVariableLoad(callee->AsVariableProxy());
2584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      PrepareForBailout(callee, NO_REGISTERS);
2585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Push undefined as receiver. This is patched in the method prologue if it
2587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // is a sloppy mode method.
2588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(isolate()->factory()->undefined_value()));
2589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Load the function from the receiver.
2591e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(callee->IsProperty());
2592a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    DCHECK(!callee->AsProperty()->IsSuperAccess());
259342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org    __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
2594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitNamedPropertyLoad(callee->AsProperty());
2595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Push the target function under the receiver.
2597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Operand(esp, 0));
2598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(Operand(esp, kPointerSize), eax);
2599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitCall(expr, call_type);
2602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2605a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgvoid FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
2606a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Expression* callee = expr->expression();
2607a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  DCHECK(callee->IsProperty());
2608a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Property* prop = callee->AsProperty();
2609a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  DCHECK(prop->IsSuperAccess());
2610a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
2611a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  SetSourcePosition(prop->position());
2612a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Literal* key = prop->key()->AsLiteral();
2613a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  DCHECK(!key->value()->IsSmi());
2614a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // Load the function from the receiver.
2615a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
2616a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  EmitLoadHomeObject(super_ref);
2617a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ push(eax);
2618a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  VisitForAccumulatorValue(super_ref->this_var());
2619a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ push(eax);
2620a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ push(Operand(esp, kPointerSize));
2621a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ push(eax);
2622a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ push(Immediate(key->value()));
2623a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // Stack here:
2624a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  //  - home_object
2625a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  //  - this (receiver)
2626a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  //  - home_object <-- LoadFromSuper will pop here and below.
2627a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  //  - this (receiver)
2628a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  //  - key
2629a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ CallRuntime(Runtime::kLoadFromSuper, 3);
2630a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
2631a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // Replace home_object with target function.
2632a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  __ mov(Operand(esp, kPointerSize), eax);
2633a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
2634a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // Stack here:
2635a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // - target function
2636a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // - this (receiver)
2637a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  EmitCall(expr, CallICState::METHOD);
2638a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org}
2639a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
2640a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
2641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Code common for calls using the IC.
2642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                Expression* key) {
2644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the key.
2645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(key);
2646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Expression* callee = expr->expression();
2648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the function from the receiver.
2650e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(callee->IsProperty());
265142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
265242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  __ mov(LoadDescriptor::NameRegister(), eax);
2653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitKeyedPropertyLoad(callee->AsProperty());
2654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Push the target function under the receiver.
2657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Operand(esp, 0));
2658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(Operand(esp, kPointerSize), eax);
2659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2660a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  EmitCall(expr, CallICState::METHOD);
2661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2664a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgvoid FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
2665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the arguments.
2666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
2667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int arg_count = args->length();
2668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  { PreservePositionScope scope(masm()->positions_recorder());
2669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    for (int i = 0; i < arg_count; i++) {
2670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForStackValue(args->at(i));
2671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Record source position of the IC call.
2675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SetSourcePosition(expr->position());
2676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Code> ic = CallIC::initialize_stub(
2677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      isolate(), arg_count, call_type);
2678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(edx, Immediate(Smi::FromInt(expr->CallFeedbackSlot())));
2679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Don't assign a type feedback id to the IC, since type feedback is provided
2681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // by the vector above.
2682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallIC(ic);
2683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2684864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RecordJSReturnSite(expr);
2685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Restore context register.
2687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2688864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->DropAndPlug(1, eax);
2690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2694864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Push copy of the first argument or undefined if it doesn't exist.
2695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (arg_count > 0) {
2696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Operand(esp, arg_count * kPointerSize));
2697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(isolate()->factory()->undefined_value()));
2699864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2700864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2701b1d9f4b46c9d3041103c0d47fada41ea1ee9c839weiliang.lin@intel.com  // Push the enclosing function.
2702b1d9f4b46c9d3041103c0d47fada41ea1ee9c839weiliang.lin@intel.com  __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
2703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Push the receiver of the enclosing function.
2704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize));
2705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Push the language mode.
2706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(Smi::FromInt(strict_mode())));
2707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Push the start position of the scope the calls resides in.
2709864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(Smi::FromInt(scope()->start_position())));
2710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Do the runtime call.
2712b1d9f4b46c9d3041103c0d47fada41ea1ee9c839weiliang.lin@intel.com  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
2713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2714864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitCall(Call* expr) {
2717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef DEBUG
2718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // We want to verify that RecordJSReturnSite gets called on all paths
2719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // through this function.  Avoid early returns.
2720864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  expr->return_is_recorded_ = false;
2721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
2722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2723864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ Call");
2724864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Expression* callee = expr->expression();
2725864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Call::CallType call_type = expr->GetCallType(isolate());
2726864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (call_type == Call::POSSIBLY_EVAL_CALL) {
2728864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
2729864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // to resolve the function we need to call and the receiver of the call.
2730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Then we call the resolved function using the given arguments.
2731864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ZoneList<Expression*>* args = expr->arguments();
2732864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int arg_count = args->length();
2733864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    { PreservePositionScope pos_scope(masm()->positions_recorder());
2734864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForStackValue(callee);
2735864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Reserved receiver slot.
2736864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Immediate(isolate()->factory()->undefined_value()));
2737864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Push the arguments.
2738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      for (int i = 0; i < arg_count; i++) {
2739864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForStackValue(args->at(i));
2740864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
2741864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2742864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Push a copy of the function (found below the arguments) and
2743864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // resolve eval.
2744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Operand(esp, (arg_count + 1) * kPointerSize));
2745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitResolvePossiblyDirectEval(arg_count);
2746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // The runtime call returns a pair of values in eax (function) and
2748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // edx (receiver). Touch up the stack with the right values.
2749864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
2750864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
2751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Record source position for debugger.
2753864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    SetSourcePosition(expr->position());
2754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
2755864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2756864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CallStub(&stub);
2757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    RecordJSReturnSite(expr);
2758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Restore context register.
2759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2760864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    context()->DropAndPlug(1, eax);
2761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (call_type == Call::GLOBAL_CALL) {
2763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitCallWithLoadIC(expr);
2764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2765864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (call_type == Call::LOOKUP_SLOT_CALL) {
2766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Call to a lookup slot (dynamically introduced variable).
2767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    VariableProxy* proxy = callee->AsVariableProxy();
2768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label slow, done;
2769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    { PreservePositionScope scope(masm()->positions_recorder());
2770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Generate code for loading from variables potentially shadowed by
2771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // eval-introduced variables.
27727c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org      EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
2773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&slow);
2775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Call the runtime to find the function to call (returned in eax) and
2776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // the object holding it (returned in edx).
2777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(context_register());
2778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(proxy->name()));
27794c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org    __ CallRuntime(Runtime::kLoadLookupSlot, 2);
2780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(eax);  // Function.
2781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(edx);  // Receiver.
2782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // If fast case code has been generated, emit code to push the function
2784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // and receiver and have the slow path jump around this code.
2785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (done.is_linked()) {
2786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label call;
2787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&call, Label::kNear);
2788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&done);
2789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Push function.
2790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(eax);
2791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // The receiver is implicitly the global receiver. Indicate this by
2792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // passing the hole to the call function stub.
2793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Immediate(isolate()->factory()->undefined_value()));
2794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&call);
2795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // The receiver is either the global receiver or an object found by
2798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // LoadContextSlot.
2799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitCall(expr);
2800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (call_type == Call::PROPERTY_CALL) {
2802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Property* property = callee->AsProperty();
2803a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    bool is_named_call = property->key()->IsPropertyName();
2804a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    // super.x() is handled in EmitCallWithLoadIC.
2805a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    if (property->IsSuperAccess() && is_named_call) {
2806a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      EmitSuperCallWithLoadIC(expr);
2807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
2808a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      {
2809a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org        PreservePositionScope scope(masm()->positions_recorder());
2810a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org        VisitForStackValue(property->obj());
2811a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      }
2812a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      if (is_named_call) {
2813a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org        EmitCallWithLoadIC(expr);
2814a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      } else {
2815a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org        EmitKeyedCallWithLoadIC(expr, property->key());
2816a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      }
2817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2819e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(call_type == Call::OTHER_CALL);
2820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Call to an arbitrary expression not handled specially above.
2821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    { PreservePositionScope scope(masm()->positions_recorder());
2822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForStackValue(callee);
2823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(isolate()->factory()->undefined_value()));
2825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Emit function call.
2826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitCall(expr);
2827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef DEBUG
2830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // RecordJSReturnSite should have been called.
2831e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(expr->return_is_recorded_);
2832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
2833864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
2837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ CallNew");
2838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // According to ECMA-262, section 11.2.2, page 44, the function
2839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // expression in new calls must be evaluated before the
2840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // arguments.
2841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Push constructor on the stack.  If it's not a function it's used as
2843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
2844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // ignored.
2845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(expr->expression());
2846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Push the arguments ("left-to-right") on the stack.
2848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
2849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int arg_count = args->length();
2850864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < arg_count; i++) {
2851864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    VisitForStackValue(args->at(i));
2852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Call the construct call builtin that handles allocation and
2855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // constructor invocation.
2856864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SetSourcePosition(expr->position());
2857864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load function and argument count into edi and eax.
2859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(eax, Immediate(arg_count));
2860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edi, Operand(esp, arg_count * kPointerSize));
2861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Record call targets in unoptimized code.
2863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_pretenuring_call_new) {
2864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot());
2865e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(expr->AllocationSiteFeedbackSlot() ==
2866864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           expr->CallNewFeedbackSlot() + 1);
2867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ LoadHeapObject(ebx, FeedbackVector());
2870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot())));
2871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET);
2873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
2874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
2875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
2876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2880864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
2881e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
2882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
2884864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false;
2886864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
2887864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
2888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
2889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
2890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
2891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(eax, Immediate(kSmiTagMask));
2894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Split(zero, if_true, if_false, fall_through);
2895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
2897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
2901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
2902e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
2903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2904864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
2905864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2906864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false;
2907864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
2908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
2909864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
2910864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
2911864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
2912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2914864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(eax, Immediate(kSmiTagMask | 0x80000000));
2915864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Split(zero, if_true, if_false, fall_through);
2916864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2917864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
2918864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2919864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2920864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2921864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
2922864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
2923e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
2924864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2925864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
2926864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2927864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false;
2928864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
2929864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
2930864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
2931864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
2932864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
2933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(eax, if_false);
2935864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(eax, isolate()->factory()->null_value());
2936864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, if_true);
2937864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2938864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Undetectable objects behave like undefined when tested with typeof.
2939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset));
2940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(ecx, Immediate(1 << Map::kIsUndetectable));
2941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_zero, if_false);
2942864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset));
2943864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(ecx, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
2944864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(below, if_false);
2945864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
2946864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2947864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Split(below_equal, if_true, if_false, fall_through);
2948864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2949864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
2950864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2951864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2953864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
2954864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
2955e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
2956864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2957864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
2958864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2959864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false;
2960864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
2961864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
2962864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
2963864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
2964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
2965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2966864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(eax, if_false);
2967864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx);
2968864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2969864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Split(above_equal, if_true, if_false, fall_through);
2970864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2971864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
2972864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2973864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2974864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2975864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
2976864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
2977e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
2978864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2979864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
2980864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2981864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false;
2982864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
2983864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
2984864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
2985864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
2986864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
2987864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2988864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(eax, if_false);
2989864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2990864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
2991864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(ebx, Immediate(1 << Map::kIsUndetectable));
2992864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2993864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Split(not_zero, if_true, if_false, fall_through);
2994864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2995864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
2996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2999864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
3000864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallRuntime* expr) {
3001864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3002e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
3003864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3004864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
3005864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3006864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false, skip_lookup;
3007864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
3008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
3009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
3010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
3011864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
3012864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3013864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ AssertNotSmi(eax);
3014864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3015864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check whether this map has already been checked to be safe for default
3016864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // valueOf.
3017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
3018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test_b(FieldOperand(ebx, Map::kBitField2Offset),
3019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            1 << Map::kStringWrapperSafeForDefaultValueOf);
3020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_zero, &skip_lookup);
3021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3022864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for fast case object. Return false for slow case objects.
3023864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ecx, FieldOperand(eax, JSObject::kPropertiesOffset));
3024864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
3025864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(ecx, isolate()->factory()->hash_table_map());
3026864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, if_false);
3027864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Look for valueOf string in the descriptor array, and indicate false if
3029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // found. Since we omit an enumeration index check, if it is added via a
3030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // transition that shares its descriptor array, this is a false positive.
3031864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label entry, loop, done;
3032864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3033864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Skip loop if no descriptors are valid.
3034864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ NumberOfOwnDescriptors(ecx, ebx);
3035864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(ecx, 0);
3036864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, &done);
3037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ LoadInstanceDescriptors(ebx, ebx);
3039864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // ebx: descriptor array.
3040864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // ecx: valid entries in the descriptor array.
3041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Calculate the end of the descriptor array.
3042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(kSmiTag == 0);
3043864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(kSmiTagSize == 1);
3044864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(kPointerSize == 4);
3045864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ imul(ecx, ecx, DescriptorArray::kDescriptorSize);
3046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ lea(ecx, Operand(ebx, ecx, times_4, DescriptorArray::kFirstOffset));
3047864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Calculate location of the first key name.
3048864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(ebx, Immediate(DescriptorArray::kFirstOffset));
3049864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Loop through all the keys in the descriptor array. If one of these is the
3050864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // internalized string "valueOf" the result is false.
3051864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&entry);
3052864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&loop);
3053864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx, FieldOperand(ebx, 0));
3054864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(edx, isolate()->factory()->value_of_string());
3055864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, if_false);
3056864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(ebx, Immediate(DescriptorArray::kDescriptorSize * kPointerSize));
3057864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&entry);
3058864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(ebx, ecx);
3059864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &loop);
3060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
3062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3063864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Reload map as register ebx was used as temporary above.
3064864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
3065864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3066864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set the bit in the map to indicate that there is no local valueOf field.
3067864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ or_(FieldOperand(ebx, Map::kBitField2Offset),
3068864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
3069864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3070864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&skip_lookup);
3071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3072864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If a valueOf property is not found on the object check that its
3073864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // prototype is the un-modified String prototype. If not result is false.
3074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
3075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(ecx, if_false);
3076864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
3077864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
3078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx,
3079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(edx, GlobalObject::kNativeContextOffset));
3080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(ecx,
3081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         ContextOperand(edx,
3082864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
3083864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3084864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Split(equal, if_true, if_false, fall_through);
3085864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3086864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
3087864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3088864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3089864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3090864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
3091864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3092e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
3093864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3094864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
3095864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3096864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false;
3097864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
3098864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
3099864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
3100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
3101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
3102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(eax, if_false);
3104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
3105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Split(equal, if_true, if_false, fall_through);
3107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
3109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
3113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3114e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
3115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
3117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false;
3119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
3120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
3121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
3122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
3123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
3124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
3126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CheckMap(eax, map, if_false, DO_SMI_CHECK);
3127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check if the exponent half is 0x80000000. Comparing against 1 and
3128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // checking for overflow is the shortest possible encoding.
3129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(FieldOperand(eax, HeapNumber::kExponentOffset), Immediate(0x1));
3130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(no_overflow, if_false);
3131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(FieldOperand(eax, HeapNumber::kMantissaOffset), Immediate(0x0));
3132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Split(equal, if_true, if_false, fall_through);
3134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
3136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
3141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3142e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
3143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
3145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false;
3147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
3148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
3149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
3150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
3151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
3152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(eax, if_false);
3154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
3155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Split(equal, if_true, if_false, fall_through);
3157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
3159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
3163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3164e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
3165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
3167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false;
3169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
3170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
3171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
3172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
3173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
3174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(eax, if_false);
3176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx);
3177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Split(equal, if_true, if_false, fall_through);
3179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
3181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
3186e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(expr->arguments()->length() == 0);
3187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false;
3189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
3190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
3191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
3192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
3193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
3194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the frame pointer for the calling frame.
3196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
3197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Skip the arguments adaptor frame if it exists.
3199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label check_frame_marker;
3200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(Operand(eax, StandardFrameConstants::kContextOffset),
3201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &check_frame_marker);
3203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, Operand(eax, StandardFrameConstants::kCallerFPOffset));
3204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check the marker in the calling frame.
3206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&check_frame_marker);
3207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset),
3208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
3209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Split(equal, if_true, if_false, fall_through);
3211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
3213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
3217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3218e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 2);
3219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the two objects into registers and perform the comparison.
3221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(0));
3222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(1));
3223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false;
3225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
3226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
3227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
3228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
3229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
3230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(ebx);
3232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(eax, ebx);
3233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Split(equal, if_true, if_false, fall_through);
3235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
3237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitArguments(CallRuntime* expr) {
3241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3242e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
3243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // ArgumentsAccessStub expects the key in edx and the formal
3245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // parameter count in eax.
3246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
3247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx, eax);
3248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters())));
3249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT);
3250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CallStub(&stub);
3251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
3252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
3256e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(expr->arguments()->length() == 0);
3257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label exit;
3259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the number of formal parameters.
3260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters())));
3261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check if the calling frame is an arguments adaptor frame.
3263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
3264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset),
3265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &exit);
3267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Arguments adaptor case: Read the arguments length from the
3269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // adaptor frame.
3270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
3271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&exit);
3273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ AssertSmi(eax);
3274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
3275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
3279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3280e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
3281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done, null, function, non_function_constructor;
3282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
3284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the object is a smi, we return null.
3286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(eax, &null);
3287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that the object is a JS object but take special care of JS
3289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // functions to make sure they have 'Function' as their class.
3290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Assume that there are only two callable types, and one of them is at
3291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // either end of the type range for JS object types. Saves extra comparisons.
3292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
3293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, eax);
3294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Map is now in eax.
3295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(below, &null);
3296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
3297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                FIRST_SPEC_OBJECT_TYPE + 1);
3298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, &function);
3299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpInstanceType(eax, LAST_SPEC_OBJECT_TYPE);
3301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
3302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                LAST_SPEC_OBJECT_TYPE - 1);
3303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, &function);
3304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Assume that there is no larger type.
3305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
3306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check if the constructor in the map is a JS function.
3308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, FieldOperand(eax, Map::kConstructorOffset));
3309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
3310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &non_function_constructor);
3311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // eax now contains the constructor function. Grab the
3313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // instance class name from there.
3314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
3315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset));
3316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
3317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Functions have class 'Function'.
3319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&function);
33205e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  __ mov(eax, isolate()->factory()->Function_string());
3321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
3322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Objects with a non-function constructor have class 'Object'.
3324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&non_function_constructor);
3325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, isolate()->factory()->Object_string());
3326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
3327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Non-JS objects have class null.
3329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&null);
3330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, isolate()->factory()->null_value());
3331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // All done.
3333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
3334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
3336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitSubString(CallRuntime* expr) {
3340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the arguments on the stack and call the stub.
3341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SubStringStub stub(isolate());
3342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3343e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 3);
3344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(0));
3345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(1));
3346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(2));
3347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CallStub(&stub);
3348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
3349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
3353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the arguments on the stack and call the stub.
3354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RegExpExecStub stub(isolate());
3355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3356e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 4);
3357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(0));
3358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(1));
3359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(2));
3360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(3));
3361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CallStub(&stub);
3362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
3363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
3367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3368e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
3369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));  // Load the object.
3371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
3373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the object is a smi return the object.
3374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(eax, &done, Label::kNear);
3375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the object is not a value type, return the object.
3376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(eax, JS_VALUE_TYPE, ebx);
3377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &done, Label::kNear);
3378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, FieldOperand(eax, JSValue::kValueOffset));
3379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
3381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
3382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitDateField(CallRuntime* expr) {
3386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3387e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 2);
3388e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_NE(NULL, args->at(1)->AsLiteral());
3389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value()));
3390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));  // Load the object.
3392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label runtime, done, not_date_object;
3394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register object = eax;
3395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = eax;
3396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register scratch = ecx;
3397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(object, &not_date_object);
3399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(object, JS_DATE_TYPE, scratch);
3400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &not_date_object);
3401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (index->value() == 0) {
3403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(result, FieldOperand(object, JSDate::kValueOffset));
3404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&done);
3405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
3406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (index->value() < JSDate::kFirstUncachedField) {
3407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
3408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(scratch, Operand::StaticVariable(stamp));
3409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
3410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(not_equal, &runtime, Label::kNear);
3411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(result, FieldOperand(object, JSDate::kValueOffset +
3412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          kPointerSize * index->value()));
3413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&done);
3414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
3415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&runtime);
3416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ PrepareCallCFunction(2, scratch);
3417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(Operand(esp, 0), object);
3418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(Operand(esp, 1 * kPointerSize), Immediate(index));
3419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
3420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&done);
3421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&not_date_object);
342447390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  __ CallRuntime(Runtime::kThrowNotDateError, 0);
3425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
3426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(result);
3427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3429864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
3431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3432e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(3, args->length());
3433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register string = eax;
3435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register index = ebx;
3436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register value = ecx;
3437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3438b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  VisitForStackValue(args->at(0));        // index
3439b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  VisitForStackValue(args->at(1));        // value
3440b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  VisitForAccumulatorValue(args->at(2));  // string
3441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(value);
3443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(index);
3444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_debug_code) {
3446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(value, Immediate(kSmiTagMask));
3447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Check(zero, kNonSmiValue);
3448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(index, Immediate(kSmiTagMask));
3449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Check(zero, kNonSmiValue);
3450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiUntag(value);
3453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiUntag(index);
3454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_debug_code) {
3456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
3457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
3458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov_b(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize),
3461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           value);
3462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(string);
3463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
3467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3468e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(3, args->length());
3469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register string = eax;
3471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register index = ebx;
3472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register value = ecx;
3473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3474b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  VisitForStackValue(args->at(0));        // index
3475b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  VisitForStackValue(args->at(1));        // value
3476b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  VisitForAccumulatorValue(args->at(2));  // string
3477864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(value);
3478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(index);
3479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_debug_code) {
3481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(value, Immediate(kSmiTagMask));
3482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Check(zero, kNonSmiValue);
3483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(index, Immediate(kSmiTagMask));
3484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Check(zero, kNonSmiValue);
3485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ SmiUntag(index);
3486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
3487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
3488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ SmiTag(index);
3489864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiUntag(value);
3492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // No need to untag a smi for two-byte addressing.
3493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize),
3494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           value);
3495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(string);
3496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
3500864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the arguments on the stack and call the runtime function.
3501864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3502e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 2);
3503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(0));
3504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(1));
3505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
350647390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  __ CallRuntime(Runtime::kMathPowSlow, 2);
3507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
3508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3511864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
3512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3513e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 2);
3514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(0));  // Load the object.
3516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(1));  // Load the value.
3517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(ebx);  // eax = value. ebx = object.
3518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
3520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the object is a smi, return the value.
3521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(ebx, &done, Label::kNear);
3522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the object is not a value type, return the value.
3524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx);
3525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &done, Label::kNear);
3526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Store the value.
3528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax);
3529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Update the write barrier.  Save the value as it will be
3531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // overwritten by the write barrier code and is needed afterward.
3532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx, eax);
353306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs);
3534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
3536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
3537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
3541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3542e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(args->length(), 1);
3543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the argument into eax and call the stub.
3545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
3546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  NumberToStringStub stub(isolate());
3548864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CallStub(&stub);
3549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
3550864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3552864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3553864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
3554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3555e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
3556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
3558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
3560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  StringCharFromCodeGenerator generator(eax, ebx);
3561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  generator.GenerateFast(masm_);
3562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
3563864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  NopRuntimeCallHelper call_helper;
3565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  generator.GenerateSlow(masm_, call_helper);
3566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
3568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(ebx);
3569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
3573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3574e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 2);
3575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(0));
3577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(1));
3578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3579864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register object = ebx;
3580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register index = eax;
3581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = edx;
3582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(object);
3584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label need_conversion;
3586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label index_out_of_range;
3587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
3588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  StringCharCodeAtGenerator generator(object,
3589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      index,
3590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      result,
3591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      &need_conversion,
3592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      &need_conversion,
3593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      &index_out_of_range,
3594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      STRING_INDEX_IS_NUMBER);
3595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  generator.GenerateFast(masm_);
3596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
3597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&index_out_of_range);
3599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // When the index is out of range, the spec requires us to return
3600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // NaN.
3601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(result, Immediate(isolate()->factory()->nan_value()));
3602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
3603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&need_conversion);
3605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Move the undefined value into the result register, which will
3606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // trigger conversion.
3607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(result, Immediate(isolate()->factory()->undefined_value()));
3608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
3609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  NopRuntimeCallHelper call_helper;
3611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  generator.GenerateSlow(masm_, call_helper);
3612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
3614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(result);
3615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
3619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3620e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 2);
3621864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(0));
3623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(1));
3624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register object = ebx;
3626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register index = eax;
3627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register scratch = edx;
3628864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = eax;
3629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(object);
3631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label need_conversion;
3633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label index_out_of_range;
3634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
3635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  StringCharAtGenerator generator(object,
3636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                  index,
3637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                  scratch,
3638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                  result,
3639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                  &need_conversion,
3640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                  &need_conversion,
3641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                  &index_out_of_range,
3642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                  STRING_INDEX_IS_NUMBER);
3643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  generator.GenerateFast(masm_);
3644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
3645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&index_out_of_range);
3647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // When the index is out of range, the spec requires us to return
3648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the empty string.
3649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(result, Immediate(isolate()->factory()->empty_string()));
3650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
3651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&need_conversion);
3653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Move smi zero into the result register, which will trigger
3654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // conversion.
3655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(result, Immediate(Smi::FromInt(0)));
3656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
3657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  NopRuntimeCallHelper call_helper;
3659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  generator.GenerateSlow(masm_, call_helper);
3660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
3662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(result);
3663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3668e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(2, args->length());
3669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(0));
3670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(1));
3671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(edx);
3673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED);
3674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CallStub(&stub);
3675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
3676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3681e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(2, args->length());
3682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(0));
3684864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(1));
3685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  StringCompareStub stub(isolate());
3687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CallStub(&stub);
3688864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
3689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
3693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3694e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() >= 2);
3695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int arg_count = args->length() - 2;  // 2 ~ receiver and function.
3697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < arg_count + 1; ++i) {
3698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    VisitForStackValue(args->at(i));
3699864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3700864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->last());  // Function.
3701864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3702864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label runtime, done;
3703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for non-function argument (including proxy).
3704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(eax, &runtime);
3705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
3706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &runtime);
3707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // InvokeFunction requires the function in edi. Move it in there.
3709864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edi, result_register());
3710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ParameterCount count(arg_count);
3711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ InvokeFunction(edi, count, CALL_FUNCTION, NullCallWrapper());
3712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
3714864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&runtime);
3716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(eax);
3717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CallRuntime(Runtime::kCall, args->length());
3718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
3719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3720864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
3721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3723864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3724864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3725864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the arguments on the stack and call the stub.
3726864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RegExpConstructResultStub stub(isolate());
3727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3728e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 3);
3729864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(0));
3730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(1));
3731864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(2));
3732864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(ebx);
3733864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(ecx);
3734864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CallStub(&stub);
3735864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
3736864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3737864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3739864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3740864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3741e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(2, args->length());
3742864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3743e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_NE(NULL, args->at(0)->AsLiteral());
3744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value();
3745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<FixedArray> jsfunction_result_caches(
3747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      isolate()->native_context()->jsfunction_result_caches());
3748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (jsfunction_result_caches->length() <= cache_id) {
3749864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Abort(kAttemptToUseUndefinedCache);
3750864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(eax, isolate()->factory()->undefined_value());
3751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    context()->Plug(eax);
3752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
3753864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3755864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(1));
3756864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register key = eax;
3758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register cache = ebx;
3759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register tmp = ecx;
3760864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(cache, ContextOperand(esi, Context::GLOBAL_OBJECT_INDEX));
3761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(cache,
3762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(cache, GlobalObject::kNativeContextOffset));
3763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
3764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(cache,
3765864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
3766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done, not_found;
3768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
3770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // tmp now holds finger offset as a smi.
3771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(key, FixedArrayElementOperand(cache, tmp));
3772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &not_found);
3773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, FixedArrayElementOperand(cache, tmp, 1));
3775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
3776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&not_found);
3778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Call runtime to perform the lookup.
3779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(cache);
3780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(key);
378147390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  __ CallRuntime(Runtime::kGetFromCache, 2);
3782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
3784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
3785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3790e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
3791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
3793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ AssertString(eax);
3795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false;
3797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
3798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
3799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
3800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
3801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
3802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(FieldOperand(eax, String::kHashFieldOffset),
3804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          Immediate(String::kContainsCachedArrayIndexMask));
3805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Split(zero, if_true, if_false, fall_through);
3807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
3809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
3813864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3814e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 1);
3815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
3816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ AssertString(eax);
3818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
3820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ IndexFromHash(eax, eax);
3821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
3823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3826b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) {
3827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label bailout, done, one_char_separator, long_separator,
3828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      non_trivial_array, not_size_one_array, loop,
3829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
3830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3832e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(args->length() == 2);
3833864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // We will leave the separator on the stack until the end of the function.
3834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(args->at(1));
3835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load this to eax (= array)
3836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
3837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // All aliases of the same register have disjoint lifetimes.
3838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register array = eax;
3839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register elements = no_reg;  // Will be eax.
3840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register index = edx;
3842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register string_length = ecx;
3844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register string = esi;
3846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register scratch = ebx;
3848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register array_length = edi;
3850864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result_pos = no_reg;  // Will be edi.
3851864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Separator operand is already pushed.
3853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand separator_operand = Operand(esp, 2 * kPointerSize);
3854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand result_operand = Operand(esp, 1 * kPointerSize);
3855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand array_length_operand = Operand(esp, 0);
3856864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ sub(esp, Immediate(2 * kPointerSize));
3857864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cld();
3858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that the array is a JSArray
3859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(array, &bailout);
3860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
3861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &bailout);
3862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that the array has fast elements.
3864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CheckFastElements(scratch, &bailout);
3865864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3866864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the array has length zero, return the empty string.
3867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset));
3868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiUntag(array_length);
3869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_zero, &non_trivial_array);
3870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result_operand, isolate()->factory()->empty_string());
3871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
3872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Save the array length.
3874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&non_trivial_array);
3875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(array_length_operand, array_length);
3876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Save the FixedArray containing array's elements.
3878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // End of array's live range.
3879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  elements = array;
3880864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(elements, FieldOperand(array, JSArray::kElementsOffset));
3881864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  array = no_reg;
3882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3884b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // Check that all array elements are sequential one-byte strings, and
3885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // accumulate the sum of their lengths, as a smi-encoded value.
3886864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(index, Immediate(0));
3887864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(string_length, Immediate(0));
3888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Loop condition: while (index < length).
3889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Live loop registers: index, array_length, string,
3890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //                      scratch, string_length, elements.
3891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (generate_debug_code_) {
3892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(index, array_length);
3893b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    __ Assert(less, kNoEmptyArraysHereInEmitFastOneByteArrayJoin);
3894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&loop);
3896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(string, FieldOperand(elements,
3897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              index,
3898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              times_pointer_size,
3899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              FixedArray::kHeaderSize));
3900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(string, &bailout);
3901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3902864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ and_(scratch, Immediate(
3904864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3905864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(scratch, kStringTag | kOneByteStringTag | kSeqStringTag);
3906864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &bailout);
3907864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(string_length,
3908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(string, SeqOneByteString::kLengthOffset));
3909864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(overflow, &bailout);
3910864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(index, Immediate(1));
3911864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(index, array_length);
3912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(less, &loop);
3913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3914864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If array_length is 1, return elements[0], a string.
3915864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(array_length, 1);
3916864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &not_size_one_array);
3917864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize));
3918864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result_operand, scratch);
3919864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
3920864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3921864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&not_size_one_array);
3922864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3923864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // End of array_length live range.
3924864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  result_pos = array_length;
3925864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  array_length = no_reg;
3926864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3927864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Live registers:
3928864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // string_length: Sum of string lengths, as a smi.
3929864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // elements: FixedArray of strings.
3930864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3931b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // Check that the separator is a flat one-byte string.
3932864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(string, separator_operand);
3933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(string, &bailout);
3934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3935864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3936864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ and_(scratch, Immediate(
3937864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3938864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(scratch, kStringTag | kOneByteStringTag | kSeqStringTag);
3939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &bailout);
3940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Add (separator length times array_length) - separator length
3942864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // to string_length.
3943864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(scratch, separator_operand);
3944864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(scratch, FieldOperand(scratch, SeqOneByteString::kLengthOffset));
3945864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ sub(string_length, scratch);  // May be negative, temporarily.
3946864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ imul(scratch, array_length_operand);
3947864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(overflow, &bailout);
3948864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(string_length, scratch);
3949864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(overflow, &bailout);
3950864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3951864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ shr(string_length, 1);
3952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Live registers and stack values:
3953864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //   string_length
3954864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //   elements
3955b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  __ AllocateOneByteString(result_pos, string_length, scratch, index, string,
3956b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                           &bailout);
3957864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result_operand, result_pos);
3958864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ lea(result_pos, FieldOperand(result_pos, SeqOneByteString::kHeaderSize));
3959864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3960864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3961864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(string, separator_operand);
3962864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(FieldOperand(string, SeqOneByteString::kLengthOffset),
3963864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         Immediate(Smi::FromInt(1)));
3964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, &one_char_separator);
3965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(greater, &long_separator);
3966864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3967864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3968864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Empty separator case
3969864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(index, Immediate(0));
3970864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&loop_1_condition);
3971864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Loop condition: while (index < length).
3972864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&loop_1);
3973864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Each iteration of the loop concatenates one string to the result.
3974864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Live values in registers:
3975864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //   index: which element of the elements array we are adding to the result.
3976864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //   result_pos: the position to which we are currently copying characters.
3977864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //   elements: the FixedArray of strings we are joining.
3978864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3979864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get string = array[index].
3980864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(string, FieldOperand(elements, index,
3981864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              times_pointer_size,
3982864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              FixedArray::kHeaderSize));
3983864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(string_length,
3984864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(string, String::kLengthOffset));
3985864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ shr(string_length, 1);
3986864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ lea(string,
3987864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(string, SeqOneByteString::kHeaderSize));
3988864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CopyBytes(string, result_pos, string_length, scratch);
3989864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(index, Immediate(1));
3990864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&loop_1_condition);
3991864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(index, array_length_operand);
3992864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(less, &loop_1);  // End while (index < length).
3993864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
3994864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3995864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // One-character separator case
3998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&one_char_separator);
3999b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // Replace separator with its one-byte character value.
4000864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov_b(scratch, FieldOperand(string, SeqOneByteString::kHeaderSize));
4001864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov_b(separator_operand, scratch);
4002864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4003864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(index, Immediate(0));
4004864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Jump into the loop after the code that copies the separator, so the first
4005864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // element is not preceded by a separator
4006864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&loop_2_entry);
4007864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Loop condition: while (index < length).
4008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&loop_2);
4009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Each iteration of the loop concatenates one string to the result.
4010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Live values in registers:
4011864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //   index: which element of the elements array we are adding to the result.
4012864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //   result_pos: the position to which we are currently copying characters.
4013864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4014864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Copy the separator character to the result.
4015864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov_b(scratch, separator_operand);
4016864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov_b(Operand(result_pos, 0), scratch);
4017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ inc(result_pos);
4018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&loop_2_entry);
4020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get string = array[index].
4021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(string, FieldOperand(elements, index,
4022864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              times_pointer_size,
4023864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              FixedArray::kHeaderSize));
4024864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(string_length,
4025864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(string, String::kLengthOffset));
4026864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ shr(string_length, 1);
4027864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ lea(string,
4028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(string, SeqOneByteString::kHeaderSize));
4029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CopyBytes(string, result_pos, string_length, scratch);
4030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(index, Immediate(1));
4031864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4032864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(index, array_length_operand);
4033864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(less, &loop_2);  // End while (index < length).
4034864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
4035864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4036864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Long separator case (separator is more than one character).
4038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&long_separator);
4039864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4040864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(index, Immediate(0));
4041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Jump into the loop after the code that copies the separator, so the first
4042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // element is not preceded by a separator
4043864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&loop_3_entry);
4044864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Loop condition: while (index < length).
4045864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&loop_3);
4046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Each iteration of the loop concatenates one string to the result.
4047864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Live values in registers:
4048864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //   index: which element of the elements array we are adding to the result.
4049864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //   result_pos: the position to which we are currently copying characters.
4050864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4051864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Copy the separator to the result.
4052864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(string, separator_operand);
4053864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(string_length,
4054864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(string, String::kLengthOffset));
4055864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ shr(string_length, 1);
4056864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ lea(string,
4057864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(string, SeqOneByteString::kHeaderSize));
4058864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CopyBytes(string, result_pos, string_length, scratch);
4059864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&loop_3_entry);
4061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get string = array[index].
4062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(string, FieldOperand(elements, index,
4063864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              times_pointer_size,
4064864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              FixedArray::kHeaderSize));
4065864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(string_length,
4066864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(string, String::kLengthOffset));
4067864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ shr(string_length, 1);
4068864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ lea(string,
4069864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(string, SeqOneByteString::kHeaderSize));
4070864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CopyBytes(string, result_pos, string_length, scratch);
4071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(index, Immediate(1));
4072864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4073864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(index, array_length_operand);
4074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(less, &loop_3);  // End while (index < length).
4075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done);
4076864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4077864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&bailout);
4079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result_operand, isolate()->factory()->undefined_value());
4080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
4081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, result_operand);
4082864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Drop temp values from the stack, and restore context register.
4083864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(esp, Immediate(3 * kPointerSize));
4084864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4085864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4086864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
4087864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4088864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4089864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4090975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.orgvoid FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
4091e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(expr->arguments()->length() == 0);
4092975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  ExternalReference debug_is_active =
4093975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org      ExternalReference::debug_is_active_address(isolate());
4094975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  __ movzx_b(eax, Operand::StaticVariable(debug_is_active));
4095975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  __ SmiTag(eax);
4096975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  context()->Plug(eax);
4097975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org}
4098975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org
4099975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org
4100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
4101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (expr->function() != NULL &&
4102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      expr->function()->intrinsic_type == Runtime::INLINE) {
4103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Comment cmnt(masm_, "[ InlineRuntimeCall");
4104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitInlineRuntimeCall(expr);
4105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
4106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ CallRuntime");
4109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
4110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (expr->is_jsruntime()) {
4112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Push the builtins object as receiver.
4113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(eax, GlobalObjectOperand());
4114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
4115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Load the function from the receiver.
411742ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org    __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
411842ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org    __ mov(LoadDescriptor::NameRegister(), Immediate(expr->name()));
41197c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org    if (FLAG_vector_ics) {
412042ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ mov(VectorLoadICDescriptor::SlotRegister(),
41217c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org             Immediate(Smi::FromInt(expr->CallRuntimeFeedbackSlot())));
41227c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org      CallLoadIC(NOT_CONTEXTUAL);
41237c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org    } else {
41247c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org      CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
41257c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org    }
4126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Push the target function under the receiver.
4128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Operand(esp, 0));
4129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(Operand(esp, kPointerSize), eax);
4130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Code common for calls using the IC.
4132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ZoneList<Expression*>* args = expr->arguments();
4133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int arg_count = args->length();
4134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    for (int i = 0; i < arg_count; i++) {
4135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForStackValue(args->at(i));
4136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Record source position of the IC call.
4139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    SetSourcePosition(expr->position());
4140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
4141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
4142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CallStub(&stub);
4143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Restore context register.
4144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    context()->DropAndPlug(1, eax);
4146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Push the arguments ("left-to-right").
4149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int arg_count = args->length();
4150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    for (int i = 0; i < arg_count; i++) {
4151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForStackValue(args->at(i));
4152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Call the C runtime function.
4155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CallRuntime(expr->function(), arg_count);
4156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    context()->Plug(eax);
4158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
4163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (expr->op()) {
4164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::DELETE: {
4165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
4166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Property* property = expr->expression()->AsProperty();
4167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VariableProxy* proxy = expr->expression()->AsVariableProxy();
4168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (property != NULL) {
4170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForStackValue(property->obj());
4171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForStackValue(property->key());
4172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(Immediate(Smi::FromInt(strict_mode())));
4173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
4174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        context()->Plug(eax);
4175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else if (proxy != NULL) {
4176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Variable* var = proxy->var();
4177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Delete of an unqualified identifier is disallowed in strict mode
4178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // but "delete this" is allowed.
4179e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(strict_mode() == SLOPPY || var->is_this());
4180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (var->IsUnallocated()) {
4181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ push(GlobalObjectOperand());
4182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ push(Immediate(var->name()));
4183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ push(Immediate(Smi::FromInt(SLOPPY)));
4184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
4185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          context()->Plug(eax);
4186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        } else if (var->IsStackAllocated() || var->IsContextSlot()) {
4187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          // Result of deleting non-global variables is false.  'this' is
4188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          // not really a variable, though we implement it as one.  The
4189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          // subexpression does not have side effects.
4190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          context()->Plug(var->is_this());
4191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        } else {
4192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          // Non-global variable.  Call the runtime to try to delete from the
4193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          // context where the variable was introduced.
4194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ push(context_register());
4195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ push(Immediate(var->name()));
41964c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org          __ CallRuntime(Runtime::kDeleteLookupSlot, 2);
4197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          context()->Plug(eax);
4198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
4199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
4200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Result of deleting non-property, non-variable reference is true.
4201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // The subexpression may have side effects.
4202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForEffect(expr->expression());
4203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        context()->Plug(true);
4204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
4205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
4206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::VOID: {
4209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
4210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForEffect(expr->expression());
4211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      context()->Plug(isolate()->factory()->undefined_value());
4212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
4213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::NOT: {
4216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
4217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (context()->IsEffect()) {
4218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Unary NOT has no side effects so it's only necessary to visit the
4219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // subexpression.  Match the optimizing compiler by not branching.
4220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForEffect(expr->expression());
4221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else if (context()->IsTest()) {
4222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        const TestContext* test = TestContext::cast(context());
4223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // The labels are swapped for the recursive call.
4224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForControl(expr->expression(),
4225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        test->false_label(),
4226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        test->true_label(),
4227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        test->fall_through());
4228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        context()->Plug(test->true_label(), test->false_label());
4229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
4230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // We handle value contexts explicitly rather than simply visiting
4231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // for control and plugging the control flow into the context,
4232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // because we need to prepare a pair of extra administrative AST ids
4233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // for the optimizing compiler.
4234e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue());
4235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Label materialize_true, materialize_false, done;
4236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForControl(expr->expression(),
4237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        &materialize_false,
4238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        &materialize_true,
4239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        &materialize_true);
4240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ bind(&materialize_true);
4241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
4242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (context()->IsAccumulatorValue()) {
4243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ mov(eax, isolate()->factory()->true_value());
4244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        } else {
4245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ Push(isolate()->factory()->true_value());
4246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
4247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ jmp(&done, Label::kNear);
4248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ bind(&materialize_false);
4249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
4250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (context()->IsAccumulatorValue()) {
4251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ mov(eax, isolate()->factory()->false_value());
4252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        } else {
4253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ Push(isolate()->factory()->false_value());
4254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
4255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ bind(&done);
4256864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
4257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
4258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::TYPEOF: {
4261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
4262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      { StackValueContext context(this);
4263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        VisitForTypeofValue(expr->expression());
4264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
4265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ CallRuntime(Runtime::kTypeof, 1);
4266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      context()->Plug(eax);
4267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
4268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    default:
4271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      UNREACHABLE();
4272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
4277e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(expr->expression()->IsValidReferenceExpression());
4278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ CountOperation");
4280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SetSourcePosition(expr->position());
4281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Expression can only be a property, a global or a (parameter or local)
4283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // slot.
4284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
4285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LhsKind assign_type = VARIABLE;
4286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Property* prop = expr->expression()->AsProperty();
4287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // In case of a property we use the uninitialized expression context
4288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // of the key to detect a named property.
4289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (prop != NULL) {
4290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    assign_type =
4291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
4292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Evaluate expression and get value.
4295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (assign_type == VARIABLE) {
4296e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
4297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    AccumulatorValueContext context(this);
4298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitVariableLoad(expr->expression()->AsVariableProxy());
4299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Reserve space for result of postfix operation.
4301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (expr->is_postfix() && !context()->IsEffect()) {
4302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Immediate(Smi::FromInt(0)));
4303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (assign_type == NAMED_PROPERTY) {
430558a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org      // Put the object both on the stack and in the register.
430658a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org      VisitForStackValue(prop->obj());
430742ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
4308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitNamedPropertyLoad(prop);
4309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
4310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForStackValue(prop->obj());
4311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForStackValue(prop->key());
431242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ mov(LoadDescriptor::ReceiverRegister(),
43137b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org             Operand(esp, kPointerSize));                       // Object.
431442ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0));  // Key.
4315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitKeyedPropertyLoad(prop);
4316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // We need a second deoptimization point after loading the value
4320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // in case evaluating the property load my have a side effect.
4321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (assign_type == VARIABLE) {
4322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PrepareForBailout(expr->expression(), TOS_REG);
4323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PrepareForBailoutForId(prop->LoadId(), TOS_REG);
4325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Inline smi case if we are in a loop.
4328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done, stub_call;
4329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  JumpPatchSite patch_site(masm_);
4330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (ShouldInlineSmiCase(expr->op())) {
4331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label slow;
4332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    patch_site.EmitJumpIfNotSmi(eax, &slow, Label::kNear);
4333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Save result for postfix expressions.
4335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (expr->is_postfix()) {
4336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (!context()->IsEffect()) {
4337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Save the result on the stack. If we have a named or keyed property
4338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // we store the result under the receiver that is currently on top
4339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // of the stack.
4340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        switch (assign_type) {
4341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          case VARIABLE:
4342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            __ push(eax);
4343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            break;
4344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          case NAMED_PROPERTY:
4345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            __ mov(Operand(esp, kPointerSize), eax);
4346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            break;
4347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          case KEYED_PROPERTY:
4348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            __ mov(Operand(esp, 2 * kPointerSize), eax);
4349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            break;
4350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
4351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
4352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (expr->op() == Token::INC) {
4355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ add(eax, Immediate(Smi::FromInt(1)));
4356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
4357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ sub(eax, Immediate(Smi::FromInt(1)));
4358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(no_overflow, &done, Label::kNear);
4360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Call stub. Undo operation first.
4361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (expr->op() == Token::INC) {
4362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ sub(eax, Immediate(Smi::FromInt(1)));
4363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
4364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ add(eax, Immediate(Smi::FromInt(1)));
4365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&stub_call, Label::kNear);
4367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&slow);
4368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ToNumberStub convert_stub(isolate());
4370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CallStub(&convert_stub);
4371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Save result for postfix expressions.
4373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (expr->is_postfix()) {
4374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (!context()->IsEffect()) {
4375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Save the result on the stack. If we have a named or keyed property
4376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // we store the result under the receiver that is currently on top
4377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // of the stack.
4378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      switch (assign_type) {
4379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        case VARIABLE:
4380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ push(eax);
4381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
4382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        case NAMED_PROPERTY:
4383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ mov(Operand(esp, kPointerSize), eax);
4384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
4385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        case KEYED_PROPERTY:
4386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ mov(Operand(esp, 2 * kPointerSize), eax);
4387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
4388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
4389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Record position before stub call.
4393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SetSourcePosition(expr->position());
4394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Call stub for +1/-1.
4396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&stub_call);
4397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx, eax);
4398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, Immediate(Smi::FromInt(1)));
4399b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), expr->binary_op(),
4400b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                              NO_OVERWRITE).code();
4401b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  CallIC(code, expr->CountBinOpFeedbackId());
4402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  patch_site.EmitPatchInfo();
4403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
4404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Store the value returned in eax.
4406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (assign_type) {
4407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case VARIABLE:
4408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expr->is_postfix()) {
4409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Perform the assignment as if via '='.
4410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        { EffectContext context(this);
4411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Token::ASSIGN);
4413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          context.Plug(eax);
4415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
4416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // For all contexts except EffectContext We have the result on
4417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // top of the stack.
4418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (!context()->IsEffect()) {
4419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          context()->PlugTOS();
4420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
4421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
4422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Perform the assignment as if via '='.
4423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Token::ASSIGN);
4425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        context()->Plug(eax);
4427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
4428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
4429864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case NAMED_PROPERTY: {
443042ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ mov(StoreDescriptor::NameRegister(),
44317b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org             prop->key()->AsLiteral()->value());
443242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ pop(StoreDescriptor::ReceiverRegister());
4433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      CallStoreIC(expr->CountStoreFeedbackId());
4434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expr->is_postfix()) {
4436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (!context()->IsEffect()) {
4437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          context()->PlugTOS();
4438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
4439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
4440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        context()->Plug(eax);
4441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
4442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
4443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case KEYED_PROPERTY: {
444542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ pop(StoreDescriptor::NameRegister());
444642ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ pop(StoreDescriptor::ReceiverRegister());
4447b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org      Handle<Code> ic =
4448b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org          CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code();
4449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      CallIC(ic, expr->CountStoreFeedbackId());
4450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expr->is_postfix()) {
4452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Result is on the stack
4453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (!context()->IsEffect()) {
4454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          context()->PlugTOS();
4455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
4456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
4457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        context()->Plug(eax);
4458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
4459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
4460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
4466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VariableProxy* proxy = expr->AsVariableProxy();
4467e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!context()->IsEffect());
4468e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!context()->IsTest());
4469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (proxy != NULL && proxy->var()->IsUnallocated()) {
4471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Comment cmnt(masm_, "[ Global variable");
447242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org    __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
447342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org    __ mov(LoadDescriptor::NameRegister(), Immediate(proxy->name()));
44747c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org    if (FLAG_vector_ics) {
447542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      __ mov(VectorLoadICDescriptor::SlotRegister(),
44767c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org             Immediate(Smi::FromInt(proxy->VariableFeedbackSlot())));
44777c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org    }
4478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Use a regular load, not a contextual load, to avoid a reference
4479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // error.
4480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallLoadIC(NOT_CONTEXTUAL);
4481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PrepareForBailout(expr, TOS_REG);
4482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    context()->Plug(eax);
4483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
4484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Comment cmnt(masm_, "[ Lookup slot");
4485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label done, slow;
4486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Generate code for loading from variables potentially shadowed
4488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // by eval-introduced variables.
44897c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org    EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done);
4490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&slow);
4492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(esi);
4493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(proxy->name()));
44944c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org    __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
4495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PrepareForBailout(expr, TOS_REG);
4496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&done);
4497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    context()->Plug(eax);
4499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4500864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // This expression cannot throw a reference error at the top level.
4501864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    VisitInDuplicateContext(expr);
4502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
4507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                 Expression* sub_expr,
4508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                 Handle<String> check) {
4509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false;
4510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
4511864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
4512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
4513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
4514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
4515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  { AccumulatorValueContext context(this);
4517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    VisitForTypeofValue(sub_expr);
4518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Factory* factory = isolate()->factory();
4522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (String::Equals(check, factory->number_string())) {
4523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(eax, if_true);
4524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
4525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           isolate()->factory()->heap_number_map());
4526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Split(equal, if_true, if_false, fall_through);
4527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (String::Equals(check, factory->string_string())) {
4528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(eax, if_false);
4529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
4530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(above_equal, if_false);
4531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Check for undetectable objects => false.
4532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
4533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org              1 << Map::kIsUndetectable);
4534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Split(zero, if_true, if_false, fall_through);
4535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (String::Equals(check, factory->symbol_string())) {
4536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(eax, if_false);
4537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpObjectType(eax, SYMBOL_TYPE, edx);
4538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Split(equal, if_true, if_false, fall_through);
4539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (String::Equals(check, factory->boolean_string())) {
4540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(eax, isolate()->factory()->true_value());
4541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(equal, if_true);
4542864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(eax, isolate()->factory()->false_value());
4543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Split(equal, if_true, if_false, fall_through);
4544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (String::Equals(check, factory->undefined_string())) {
4545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(eax, isolate()->factory()->undefined_value());
4546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(equal, if_true);
4547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(eax, if_false);
4548864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Check for undetectable objects => true.
4549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
4550864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
4551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(ecx, Immediate(1 << Map::kIsUndetectable));
4552864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Split(not_zero, if_true, if_false, fall_through);
4553864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (String::Equals(check, factory->function_string())) {
4554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(eax, if_false);
4555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
4556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpObjectType(eax, JS_FUNCTION_TYPE, edx);
4557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(equal, if_true);
4558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpInstanceType(edx, JS_FUNCTION_PROXY_TYPE);
4559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Split(equal, if_true, if_false, fall_through);
4560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (String::Equals(check, factory->object_string())) {
4561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(eax, if_false);
45629d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org    __ cmp(eax, isolate()->factory()->null_value());
45639d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org    __ j(equal, if_true);
4564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpObjectType(eax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, edx);
4565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(below, if_false);
4566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpInstanceType(edx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
4567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(above, if_false);
4568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Check for undetectable objects => false.
4569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
4570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org              1 << Map::kIsUndetectable);
4571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Split(zero, if_true, if_false, fall_through);
4572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (if_false != fall_through) __ jmp(if_false);
4574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
4576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4579864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment cmnt(masm_, "[ CompareOperation");
4581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SetSourcePosition(expr->position());
4582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // First we try a fast inlined version of the compare when one of
4584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the operands is a literal.
4585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (TryLiteralCompare(expr)) return;
4586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Always perform the comparison for its control flow.  Pack the result
4588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // into the expression's context after the comparison is performed.
4589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false;
4590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
4591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
4592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
4593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
4594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
4595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Token::Value op = expr->op();
4597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForStackValue(expr->left());
4598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (op) {
4599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::IN:
4600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForStackValue(expr->right());
4601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
4602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
4603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(eax, isolate()->factory()->true_value());
4604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Split(equal, if_true, if_false, fall_through);
4605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
4606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::INSTANCEOF: {
4608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForStackValue(expr->right());
4609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      InstanceofStub stub(isolate(), InstanceofStub::kNoFlags);
4610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ CallStub(&stub);
4611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ test(eax, eax);
4613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // The stub returns 0 for true.
4614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Split(zero, if_true, if_false, fall_through);
4615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
4616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    default: {
4619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      VisitForAccumulatorValue(expr->right());
4620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Condition cc = CompareIC::ComputeCondition(op);
4621864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ pop(edx);
4622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      bool inline_smi_code = ShouldInlineSmiCase(op);
4624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      JumpPatchSite patch_site(masm_);
4625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (inline_smi_code) {
4626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Label slow_case;
4627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(ecx, edx);
4628864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ or_(ecx, eax);
4629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
4630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ cmp(edx, eax);
4631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Split(cc, if_true, if_false, NULL);
4632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ bind(&slow_case);
4633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
4634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Record position and call the compare IC.
4636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      SetSourcePosition(expr->position());
4637b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org      Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
4638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      CallIC(ic, expr->CompareOperationFeedbackId());
4639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      patch_site.EmitPatchInfo();
4640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ test(eax, eax);
4643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Split(cc, if_true, if_false, fall_through);
4644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Convert the result of the comparison into one expected for this
4648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // expression's context.
4649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
4650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
4654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                              Expression* sub_expr,
4655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                              NilValue nil) {
4656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialize_true, materialize_false;
4657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_true = NULL;
4658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* if_false = NULL;
4659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* fall_through = NULL;
4660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
4661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         &if_true, &if_false, &fall_through);
4662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  VisitForAccumulatorValue(sub_expr);
4664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Object> nil_value = nil == kNullValue
4667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ? isolate()->factory()->null_value()
4668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      : isolate()->factory()->undefined_value();
4669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (expr->op() == Token::EQ_STRICT) {
4670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(eax, nil_value);
4671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Split(equal, if_true, if_false, fall_through);
4672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
4674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallIC(ic, expr->CompareOperationFeedbackId());
4675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(eax, eax);
4676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Split(not_zero, if_true, if_false, fall_through);
4677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(if_true, if_false);
4679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
4684864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  context()->Plug(eax);
4685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4688864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgRegister FullCodeGenerator::result_register() {
4689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return eax;
4690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgRegister FullCodeGenerator::context_register() {
4694864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return esi;
4695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4699e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
4700864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(Operand(ebp, frame_offset), value);
4701864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4702864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
4705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(dst, ContextOperand(esi, context_index));
4706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4709864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
4710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Scope* declaration_scope = scope()->DeclarationScope();
4711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (declaration_scope->is_global_scope() ||
4712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      declaration_scope->is_module_scope()) {
4713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Contexts nested in the native context have a canonical empty function
4714864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // as their closure, not the anonymous closure containing the global
4715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // code.  Pass a smi sentinel and let the runtime look up the empty
4716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // function.
4717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(Smi::FromInt(0)));
4718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (declaration_scope->is_eval_scope()) {
4719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Contexts nested inside eval code have the same closure as the context
4720864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // calling eval, not the anonymous closure containing the eval code.
4721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Fetch it from the context.
4722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(ContextOperand(esi, Context::CLOSURE_INDEX));
4723864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4724e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(declaration_scope->is_function_scope());
4725864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
4726864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4728864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4729864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// ----------------------------------------------------------------------------
4731864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Non-local control flow support.
4732864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4733864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::EnterFinallyBlock() {
4734864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Cook return address on top of stack (smi encoded Code* delta)
4735e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!result_register().is(edx));
4736864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(edx);
4737864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ sub(edx, Immediate(masm_->CodeObject()));
4738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
4739864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(kSmiTag == 0);
4740864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiTag(edx);
4741864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(edx);
4742864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4743864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Store result register while executing finally block.
4744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(result_register());
4745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Store pending message while executing finally block.
4747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference pending_message_obj =
4748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::address_of_pending_message_obj(isolate());
4749864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx, Operand::StaticVariable(pending_message_obj));
4750864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(edx);
4751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference has_pending_message =
4753864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::address_of_has_pending_message(isolate());
4754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx, Operand::StaticVariable(has_pending_message));
4755864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiTag(edx);
4756864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(edx);
4757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference pending_message_script =
4759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::address_of_pending_message_script(isolate());
4760864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(edx, Operand::StaticVariable(pending_message_script));
4761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(edx);
4762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4765864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid FullCodeGenerator::ExitFinallyBlock() {
4766e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!result_register().is(edx));
4767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Restore pending message from stack.
4768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(edx);
4769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference pending_message_script =
4770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::address_of_pending_message_script(isolate());
4771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(Operand::StaticVariable(pending_message_script), edx);
4772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(edx);
4774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiUntag(edx);
4775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference has_pending_message =
4776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::address_of_has_pending_message(isolate());
4777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(Operand::StaticVariable(has_pending_message), edx);
4778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(edx);
4780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference pending_message_obj =
4781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::address_of_pending_message_obj(isolate());
4782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(Operand::StaticVariable(pending_message_obj), edx);
4783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Restore result register from stack.
4785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(result_register());
4786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Uncook return address.
4788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(edx);
4789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiUntag(edx);
4790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(edx, Immediate(masm_->CodeObject()));
4791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(edx);
4792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#undef __
4796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#define __ ACCESS_MASM(masm())
4798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgFullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
4800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int* stack_depth,
4801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int* context_length) {
4802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The macros used here must preserve the result register.
4803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Because the handler block contains the context of the finally
4805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // code, we can restore it directly from there for the finally code
4806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // rather than iteratively unwinding contexts via their previous
4807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // links.
4808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Drop(*stack_depth);  // Down to the handler block.
4809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (*context_length > 0) {
4810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Restore the context to its dedicated register and the stack.
4811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(esi, Operand(esp, StackHandlerConstants::kContextOffset));
4812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
4813864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ PopTryHandler();
4815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ call(finally_entry_);
4816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  *stack_depth = 0;
4818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  *context_length = 0;
4819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return previous_;
4820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#undef __
4823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic const byte kJnsInstruction = 0x79;
4826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic const byte kJnsOffset = 0x11;
4827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic const byte kNopByteOne = 0x66;
4828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic const byte kNopByteTwo = 0x90;
4829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef DEBUG
4830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic const byte kCallInstruction = 0xe8;
4831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
4832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4833864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid BackEdgeTable::PatchAt(Code* unoptimized_code,
4835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                            Address pc,
4836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                            BackEdgeState target_state,
4837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                            Code* replacement_code) {
4838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Address call_target_address = pc - kIntSize;
4839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Address jns_instr_address = call_target_address - 3;
4840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Address jns_offset_address = call_target_address - 2;
4841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (target_state) {
4843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case INTERRUPT:
4844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      //     sub <profiling_counter>, <delta>  ;; Not changed
4845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      //     jns ok
4846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      //     call <interrupt stub>
4847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      //   ok:
4848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      *jns_instr_address = kJnsInstruction;
4849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      *jns_offset_address = kJnsOffset;
4850864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
4851864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case ON_STACK_REPLACEMENT:
4852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case OSR_AFTER_STACK_CHECK:
4853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      //     sub <profiling_counter>, <delta>  ;; Not changed
4854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      //     nop
4855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      //     nop
4856864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      //     call <on-stack replacment>
4857864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      //   ok:
4858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      *jns_instr_address = kNopByteOne;
4859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      *jns_offset_address = kNopByteTwo;
4860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
4861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Assembler::set_target_address_at(call_target_address,
4864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                   unoptimized_code,
4865864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                   replacement_code->entry());
4866864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
4867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      unoptimized_code, call_target_address, replacement_code);
4868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgBackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
4872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Isolate* isolate,
4873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Code* unoptimized_code,
4874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Address pc) {
4875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Address call_target_address = pc - kIntSize;
4876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Address jns_instr_address = call_target_address - 3;
4877e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(kCallInstruction, *(call_target_address - 1));
4878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (*jns_instr_address == kJnsInstruction) {
4880e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ(kJnsOffset, *(call_target_address - 2));
4881e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(),
4882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org              Assembler::target_address_at(call_target_address,
4883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                           unoptimized_code));
4884864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return INTERRUPT;
4885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4886864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4887e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(kNopByteOne, *jns_instr_address);
4888e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(kNopByteTwo, *(call_target_address - 2));
4889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (Assembler::target_address_at(call_target_address, unoptimized_code) ==
4891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      isolate->builtins()->OnStackReplacement()->entry()) {
4892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return ON_STACK_REPLACEMENT;
4893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4895e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            Assembler::target_address_at(call_target_address,
4897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                         unoptimized_code));
4898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return OSR_AFTER_STACK_CHECK;
4899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4902864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} }  // namespace v8::internal
4903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4904864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif  // V8_TARGET_ARCH_X87
4905